Update CLAUDE.md with R2 storage learnings
This commit is contained in:
parent
1495b9f88e
commit
070293498b
1 changed files with 69 additions and 13 deletions
82
CLAUDE.md
82
CLAUDE.md
|
|
@ -7,8 +7,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
```bash
|
||||
# Development
|
||||
pnpm dev # Start dev server at http://localhost:3000
|
||||
pnpm build # Production build
|
||||
pnpm start # Start production server
|
||||
pnpm build # Production build
|
||||
pnpm start # Start production server
|
||||
|
||||
# Database (drizzle)
|
||||
pnpm db:push # Push schema to database
|
||||
|
|
@ -43,11 +43,12 @@ src/
|
|||
│ ├── medical/ # Vaccination tracking
|
||||
│ ├── growth/ # Growth charts
|
||||
│ ├── memories/ # Photo gallery
|
||||
│ ├── menu/ # Navigation menu
|
||||
│ ├── menu/ # Navigation menu
|
||||
│ ├── onboarding/ # First-time setup
|
||||
│ └── login/ # Magic link login
|
||||
├── libs/ # Shared utilities (if any)
|
||||
└── styles/ # Global styles
|
||||
│ ├── settings/ # Settings with theme picker
|
||||
│ └── login/ # Magic link login
|
||||
├── ThemeProvider.tsx # Theme context (light/dark/system/time)
|
||||
├── ThemeProvider
|
||||
drizzle/ # Database migrations
|
||||
docs/ # Design docs
|
||||
```
|
||||
|
|
@ -66,15 +67,24 @@ docs/ # Design docs
|
|||
- **Logs:** Feed, sleep, diaper entries with timestamps
|
||||
- **Vaccinations:** IAP schedule tracking
|
||||
- **Growth:** Weight/height over time
|
||||
- **Memories:** Photos with vision AI tags
|
||||
- **Memories:** Photos with R2 storage
|
||||
|
||||
### Key Patterns
|
||||
|
||||
**ThemeProvider:** Wrap app in ThemeProvider from layout.tsx. Use `useTheme()` hook in components.
|
||||
|
||||
```typescript
|
||||
import { useTheme } from "./ThemeProvider";
|
||||
const { theme, toggle, setMode } = useTheme();
|
||||
// theme: "light" | "dark"
|
||||
// mode: "light" | "dark" | "system" | "time"
|
||||
```
|
||||
|
||||
**Offline Queue:** Uses localStorage (`tia_offline_queue`) for failed API calls, retries when online.
|
||||
|
||||
**Chat Sessions:** Stored in localStorage (`tia_chat_sessions`) as array of sessions with messages. Shared between home page AI card and /ai page.
|
||||
**Chat Sessions:** Stored in localStorage (`tia_chat_sessions`) - shared between home page AI card and /ai page.
|
||||
|
||||
**API Routes:** Return standard JSON `{ entries: [...] }` format for lists.
|
||||
**API Routes:** Return standard JSON `{ success: true, items: [...] }` format for lists.
|
||||
|
||||
**AI Integration:**
|
||||
|
||||
|
|
@ -82,17 +92,63 @@ docs/ # Design docs
|
|||
- Model: `minimax-2.7`
|
||||
- See `/docs/debugging.md` for troubleshooting
|
||||
|
||||
## R2 Storage (Cloudflare)
|
||||
|
||||
### Setup
|
||||
|
||||
1. **Create bucket** in Cloudflare Dashboard → R2
|
||||
2. **Create API token** with "Object Read & Write" permissions
|
||||
3. **Enable Public Development URL** in bucket settings (gives pub-*.r2.dev URL)
|
||||
|
||||
### API Endpoint Format
|
||||
|
||||
The S3 API endpoint is: `https://<accountId>.r2.cloudflarestorage.com`
|
||||
|
||||
For your bucket named "tia":
|
||||
- Account ID: `e71f22a2f8614fb3ba6d9b28a264d8ce`
|
||||
- S3 Endpoint: `https://e71f22a2f8614fb3ba6d9b28a264d8ce.r2.cloudflarestorage.com`
|
||||
- Public URL: `https://pub-37a76fd657c94d1dbc521a109c087a11.r2.dev` (no bucket name in path!)
|
||||
|
||||
### Code Example
|
||||
|
||||
```typescript
|
||||
const client = new S3Client({
|
||||
region: "auto",
|
||||
endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
||||
credentials: { accessKeyId, secretAccessKey },
|
||||
});
|
||||
|
||||
// List objects
|
||||
const command = new ListObjectsV2Command({ Bucket: "tia" });
|
||||
const res = await client.send(command);
|
||||
|
||||
// Get presigned upload URL
|
||||
const command = new PutObjectCommand({ Bucket: "tia", Key: key, ContentType });
|
||||
const url = await getSignedUrl(client, command, { expiresIn: 3600 });
|
||||
```
|
||||
|
||||
### Key Learnings
|
||||
|
||||
1. **S3 API endpoint** does NOT include bucket name: `https://...r2.cloudflarestorage.com`
|
||||
2. **Public URL** does NOT include bucket path: `https://pub-...r2.dev` (NOT `/tia/...`)
|
||||
3. **CORS** needs GET and PUT methods for uploads
|
||||
4. ListObjects needs bucket name in command, not endpoint
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Set in `.env.local` for development, or in Dokploy dashboard for production.
|
||||
|
||||
See `.env.example` for all required vars. Key ones:
|
||||
Required:
|
||||
|
||||
- `DATABASE_URL` - PostgreSQL connection
|
||||
- `AUTH_SECRET` - NextAuth secret
|
||||
- `LITELLM_BASE_URL` - AI gateway URL
|
||||
- `LITELLM_API_KEY` - AI API key
|
||||
- `R2_ACCOUNT_ID` - Cloudflare R2 account ID
|
||||
- `R2_ACCESS_KEY_ID` - R2 access key
|
||||
- `R2_SECRET_ACCESS_KEY` - R2 secret key
|
||||
- `R2_BUCKET_NAME` - R2 bucket name
|
||||
- `R2_BUCKET_NAME` - R2 bucket name (e.g., "tia")
|
||||
- `R2_PUBLIC_URL` - Public R2 URL (e.g., `https://pub-...r2.dev`)
|
||||
|
||||
Optional for AI:
|
||||
|
||||
- `LITELLM_BASE_URL` - AI gateway URL
|
||||
- `LITELLM_API_KEY` - AI API key
|
||||
Loading…
Add table
Reference in a new issue