# Cursor Rules
## Tech Stack
- Next.js 16 (App Router)
- React 19
- TypeScript 5
- Tailwind CSS 4
- Drizzle ORM
- TanStack Query
- PostgreSQL 17
## Infrastructure
```
사용자 (Web/PWA/앱)
└─ Cloudflare (cloudflare/terraform/)
├─ DNS (dns-records.tf)
│ ├─ Cloud Run (Next.js Web) (Dockerfile.nextjs, cloudbuild.*.nextjs.yaml)
│ ├─ Cloud Run (Hono API) (Dockerfile.hono, cloudbuild.*.hono.yaml)
│ ├─ Vercel (Next.js Edge API) (vercel/)
│ ├─ Render (Next.js Web) (render.yaml)
│ ├─ Cloudflare R2 (public.r2.dev)
│ └─ Cloudflare Tunnel → Next.js Web + Hono API + Monitoring
├─ Edge rules
├─ cache-rules.tf (TTL/Bypass/Respect origin, R2 1y)
├─ redirects.tf (www → apex)
├─ managed-transforms.tf (headers)
└─ rate-limiting.tf (zone rate limit)
배치 (Cloud Run Jobs) (cloud-run/)
├─ manga-crawl: Cloud Scheduler → Job → Postgres(NEON_DATABASE_URL)
└─ crawl-and-notify: (스케줄러 연결) Job → Postgres(POSTGRES_URL) + Web Push(VAPID)
데이터/캐시
├─ Postgres: POSTGRES_URL (Web/API/notify), NEON_DATABASE_URL (manga-crawl)
└─ Redis: UPSTASH_KV_REST_* (KV), REDIS_URL (Next.js cache 등)
```
## Code Style
### Colocation
- **Keep non-reusable logic close to where it's used.** Types, utilities, and constants used only in a specific component or page should be defined in that file or the same folder.
```typescript
// ❌ Bad - separating non-reusable types into a separate file
// src/types/order-form.ts
export interface OrderFormData {
productId: string
quantity: number
}
// src/app/orders/page.tsx
import { OrderFormData } from '@/types/order-form'
// ✅ Good - define types used only in this page within the same file
// src/app/orders/page.tsx
interface OrderFormData {
productId: string
quantity: number
}
export default function OrdersPage() {
// ...
}
```
```typescript
// ❌ Bad - separating single-use utilities into lib folder
// src/lib/utils/format-order-id.ts
export function formatOrderId(id: string) {
return `ORD-${id.toUpperCase()}`
}
// ✅ Good - define within the component file
// src/components/orders/order-table.tsx
function formatOrderId(id: string) {
return `ORD-${id.toUpperCase()}`
}
export function OrderTable() {
// uses formatOrderId
}
```
- Only move to shared folders (`lib/`, `utils/`, `types/`) when reused across multiple files.
Workflows from the Neura Market marketplace related to this Cursor resource