You are a seasoned full-stack developer tasked with building a complete, production-ready MVP of 'Papercraft Haunts' using Next.js. This application allows users to digitally design, customize, and experience printable dark-themed papercraft models, with an augmented reality (AR) feature.
**1. PROJECT OVERVIEW:**
Papercraft Haunts aims to democratize the creation of unique, dark-themed papercraft toys, inspired by the 'Haunted Paper Toys' concept found on Hacker News. It solves the problem of requiring specialized materials, precise printing, and complex assembly for traditional papercrafts. Our core value proposition is to provide an accessible, digital platform where users can easily design, personalize, and visualize intricate papercraft models (haunted houses, monsters, gothic scenes, etc.) using a user-friendly interface and experience them in their own environment through Augmented Reality (AR). Users can then share their creations, fostering a community of digital artisans and hobbyists.
**2. TECH STACK:**
- **Framework:** Next.js (App Router)
- **Language:** TypeScript
- **Styling:** Tailwind CSS
- **ORM:** Drizzle ORM (with PostgreSQL via Vercel Postgres or a similar provider)
- **UI Library:** shadcn/ui (for accessible, reusable components)
- **Authentication:** NextAuth.js (using email/password and potentially OAuth providers like Google)
- **AR Library:** ViroReact or Three.js with AR.js for WebXR capabilities
- **State Management:** React Context API / Zustand (for global state, if needed)
- **Form Handling:** React Hook Form with Zod for validation
- **Deployment:** Vercel
- **Database:** PostgreSQL (managed via Vercel Postgres)
**3. DATABASE SCHEMA (Drizzle ORM - PostgreSQL):**
```typescript
// schema.ts
import { pgTable, text, timestamp, uuid, integer, boolean, jsonb, varchar }
from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name'),
email: text('email').unique().notNull(),
emailVerified: timestamp('emailVerified', { mode: 'date' }),
image: text('image'),
password: text('password'), // Hashed password
createdAt: timestamp('createdAt').defaultNow(),
updatedAt: timestamp('updatedAt').defaultNow(),
});
export const models = pgTable('models', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('userId').notNull().references(() => users.id, { onDelete: 'cascade' }),
name: varchar('name', { length: 255 }).notNull(),
description: text('description'),
category: varchar('category', { length: 100 }), // e.g., 'Haunted House', 'Monster', 'Gothic Scene'
tags: jsonb('tags'), // Array of strings
thumbnailUrl: text('thumbnailUrl'), // URL to a preview image
modelFileUrl: text('modelFileUrl'), // URL to the 3D model file (e.g., GLB)
isPremium: boolean('isPremium').default(false),
createdAt: timestamp('createdAt').defaultNow(),
updatedAt: timestamp('updatedAt').defaultNow(),
});
export const userModelCustomizations = pgTable('userModelCustomizations', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('userId').notNull().references(() => users.id, { onDelete: 'cascade' }),
modelId: uuid('modelId').notNull().references(() => models.id, { onDelete: 'cascade' }),
customizationData: jsonb('customizationData').notNull(), // Stores colors, textures, etc. as JSON
createdAt: timestamp('createdAt').defaultNow(),
updatedAt: timestamp('updatedAt').defaultNow(),
});
export const projects = pgTable('projects', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('userId').notNull().references(() => users.id, { onDelete: 'cascade' }),
name: varchar('name', { length: 255 }).notNull(),
description: text('description'),
modelId: uuid('modelId').notNull().references(() => models.id, { onDelete: 'cascade' }),
customizationData: jsonb('customizationData').notNull(), // Specific customization for this project
isPublic: boolean('isPublic').default(false),
createdAt: timestamp('createdAt').defaultNow(),
updatedAt: timestamp('updatedAt').defaultNow(),
});
// Relations (Example)
export const userRelations = relations(users, ({ many }) => ({
models: many(models),
projects: many(projects),
userModelCustomizations: many(userModelCustomizations),
}));
export const modelRelations = relations(models, ({ one, many }) => ({
creator: one(users, { fields: [models.userId], references: [users.id] }),
userModelCustomizations: many(userModelCustomizations),
projects: many(projects),
}));
// Add more relations as needed for projects, etc.
```
**4. CORE FEATURES & USER FLOW:**
* **Authentication Flow:**
1. User lands on the homepage.
2. Clicks 'Sign Up' or 'Sign In'.
3. Redirected to Auth Page (`/auth`).
4. User enters email/password or uses OAuth.
5. On success, user is redirected to their Dashboard (`/dashboard`).
6. On failure, error message displayed.
7. Protected routes (e.g., `/dashboard`, `/create`) redirect to `/auth` if not logged in.
* **Model Browsing & Downloading:**
1. User navigates to the 'Explore Models' page (`/models`).
2. Models are displayed in a grid/list format with thumbnails, names, categories, and premium badges.
3. User can filter by category, search by name/tags, and sort (newest, popular).
4. Clicking a model card shows a detail view (`/models/[id]`) with a larger preview, description, download button (for free models), or 'Customize/Buy' button (for premium models).
5. For free models, clicking 'Download' initiates a download of the 3D model file (e.g., `.glb`) and potentially a PDF template for printing.
6. For premium models, user is prompted to purchase or subscribe.
* **Model Customization:**
1. User clicks 'Customize' on a free or purchased premium model.
2. Redirected to the Customization Editor page (`/editor/[modelId]`).
3. The page loads the selected 3D model.
4. UI panels allow users to:
* Change base colors using a color picker.
* Apply pre-defined textures (e.g., wood, stone, metallic).
* (Future) Upload custom textures.
* (Future) Modify simple geometry parameters if applicable.
5. Changes are reflected in real-time in a 3D viewer.
6. User can save their customization as a new 'Project' (`/projects/[projectId]`). This saves the base model ID and the specific `customizationData` JSON.
* **Augmented Reality (AR) Experience:**
1. From the Model Detail page (`/models/[id]`) or Project Detail page (`/projects/[projectId]`), user clicks the 'View in AR' button.
2. The app requests camera permissions.
3. If permissions granted, the AR view loads.
4. User points their device at a flat surface.
5. The customized 3D model appears on the surface.
6. User can move, rotate, and scale the model using touch gestures.
7. A 'Take Photo' or 'Record Video' button is available to capture the AR scene.
* **Project Management & Sharing:**
1. User navigates to 'My Projects' (`/dashboard/projects`).
2. A list of saved projects is displayed.
3. Clicking a project shows its details and options to 'Edit Customization', 'View in AR', 'Make Public', 'Share', or 'Delete'.
4. 'Make Public' sets `isPublic: true` and adds it to a community gallery.
5. Sharing generates a unique link to view the project (read-only) and its AR experience.
**5. API & DATA FETCHING (Next.js App Router - Server Components & Route Handlers):**
* **Public Routes (Server Components):** Fetch models, categories, tags directly from DB for pages like `/models` and `/models/[id]`. Use `fetch` with caching. Display `thumbnailUrl`, `name`, `description`, `isPremium` status.
* **Authenticated Routes (Server Components/Client Components):** Fetch user-specific data like projects, saved customizations. Use server actions for mutations (create, update, delete projects, customizations).
* **API Routes (Route Handlers - `app/api/...`):**
* `POST /api/auth/signup`, `POST /api/auth/signin`: Handle user registration and login (integrated with NextAuth.js).
* `POST /api/projects`: Create a new project (requires authentication). Expects `{ modelId, name, description, customizationData }`. Returns the new project data.
* `PUT /api/projects/[projectId]`: Update an existing project. Expects `{ name, description, customizationData }`. Returns updated project data.
* `DELETE /api/projects/[projectId]`: Delete a project. Returns success status.
* `GET /api/models/[modelId]/ar`: Fetch model data specifically for AR view (e.g., `modelFileUrl`, `customizationData` if applicable). Returns `{ modelFileUrl, finalCustomization }`.
* `POST /api/upload/texture`: (Future) Handle texture uploads (requires authentication and storage like S3).
* **Data Fetching Strategy:**
* Use Server Components for initial page loads to fetch data directly from the DB, leveraging caching.
* Use Client Components within Server Components where interactivity is needed (e.g., customization controls, AR viewer).
* Utilize Server Actions for mutations to simplify form handling and data mutations.
* Fetch data for AR view on demand when the 'View in AR' button is clicked.
**6. COMPONENT BREAKDOWN (Next.js App Router Structure):**
* **`app/`**
* **`(public)/`** (Layout for public pages)
* `layout.tsx`: Main layout with header, footer.
* `page.tsx`: Homepage (marketing content, intro to app).
* `models/`
* `page.tsx`: Model browser (grid view, filters, search). Fetches public models.
* `[id]/`
* `page.tsx`: Model detail view (preview, description, download/customize button, 'View in AR'). Fetches specific model data.
* `auth/`
* `page.tsx`: Sign up/Sign in form component. Uses NextAuth.js providers.
* **`(private)/`** (Layout for authenticated pages)
* `layout.tsx`: Dashboard layout with sidebar navigation.
* `dashboard/`
* `page.tsx`: User dashboard overview (recent projects, stats).
* `projects/`
* `page.tsx`: List of user's projects.
* `[projectId]/`
* `page.tsx`: Project detail view (edit options, share, AR view).
* `editor/`
* `[modelId]/`
* `page.tsx`: The AR-powered customization editor. Loads model, UI controls, 3D viewer.
* **`api/`**
* `auth/`
* `[...nextauth]/route.ts`: NextAuth.js handler.
* `projects/`
* `[projectId]/route.ts`: Route handlers for GET, PUT, DELETE projects.
* `models/`
* `[modelId]/route.ts`: Route handler for fetching model data for AR.
* **`components/`**
* **`ui/`** (From shadcn/ui)
* `button.tsx`, `input.tsx`, `card.tsx`, `dialog.tsx`, `avatar.tsx`, `dropdown-menu.tsx`, `slider.tsx`, `color-picker.tsx` (custom), `tabs.tsx`, etc.
* **`layout/`**
* `Header.tsx`: Navigation, logo, auth status.
* `Footer.tsx`: Links, copyright.
* `Sidebar.tsx`: For private dashboard layout.
* **`models/`**
* `ModelCard.tsx`: Renders a single model in a list/grid.
* `ModelFilter.tsx`: Category filters, search input.
* `ModelViewer.tsx`: Basic 3D viewer for model details.
* **`editor/`**
* `CustomizationPanel.tsx`: Contains color pickers, texture selectors.
* `ARViewer.tsx`: Component integrating ViroReact/Three.js for AR experience.
* **`common/`**
* `AuthForm.tsx`: Combined sign-up/sign-in form.
* `Spinner.tsx`: Loading indicator.
* `ErrorMessage.tsx`: Displaying API errors.
* **`lib/`**: Utility functions, API clients, Drizzle config.
* **`hooks/`**: Custom React hooks.
* **`styles/`**: Global CSS.
* **`contexts/`**: React Context providers if needed.
**State Management:**
- Global state (auth status, user info) managed via Context API or Zustand.
- Local component state for forms, UI elements.
- Server state fetched via Server Components/Server Actions.
**7. UI/UX DESIGN & VISUAL IDENTITY:**
* **Design Style:** Dark, Mystical, Slightly Ethereal.
* **Color Palette:**
* Primary Dark: `#1a1a1a` (Deep background)
* Secondary Dark: `#2c2c2c` (Card backgrounds, secondary elements)
* Accent 1 (Mystical Glow): `#6a0dad` (Purple - for buttons, highlights)
* Accent 2 (Ethereal Light): `#ba86fc` (Lighter purple/lavender - subtle highlights)
* Text (Light): `#e0e0e0` (Primary text)
* Text (Muted): `#9ca3af` (Secondary text)
* Error: `#ef4444` (Red)
* Success: `#22c55e` (Green)
* **Typography:**
* Headings: A slightly decorative, perhaps serif font with a gothic feel (e.g., 'IM Fell English SC', 'Cinzel Decorative').
* Body Text: A clean, readable sans-serif font (e.g., 'Inter', 'Roboto').
* **Layout:** Clean, spacious layouts with dark backgrounds. Use of subtle gradients or noise textures in the background for depth. Card-based design for models. Clear separation between content areas.
* **Responsiveness:** Mobile-first approach. Layouts adapt seamlessly from small mobile screens to large desktop monitors. Navigation collapses into a hamburger menu on smaller screens. AR experience optimized for mobile devices.
* **Visual Elements:** Use of subtle, animated particle effects or glowing elements in the background or around interactive elements. Ghostly icons or motifs integrated into the UI where appropriate.
**8. SAMPLE/MOCK DATA:**
* **User:**
```json
{ "id": "uuid-user-1", "name": "Elara", "email": "elara@example.com", "image": "/avatars/elara.png" }
```
* **Model (Free):**
```json
{ "id": "uuid-model-free-1", "name": "Gothic Spire House", "description": "An eerie, towering house perfect for your miniature haunted village.", "category": "Haunted House", "thumbnailUrl": "/thumbnails/gothic-spire.webp", "modelFileUrl": "/models/gothic-spire.glb", "isPremium": false, "tags": ["house", "gothic", "haunted"] }
```
* **Model (Premium):**
```json
{ "id": "uuid-model-premium-1", "name": "Clockwork Gargoyle", "description": "A menacing gargoyle with intricate mechanical details. Animates slightly in AR.", "category": "Monster", "thumbnailUrl": "/thumbnails/gargoyle.webp", "modelFileUrl": "/models/gargoyle.glb", "isPremium": true, "tags": ["gargoyle", "monster", "clockwork", "animated"] }
```
* **Project (Customized):**
```json
{ "id": "uuid-project-1", "userId": "uuid-user-1", "modelId": "uuid-model-free-1", "name": "Elara's Spire House", "description": "My customized version of the Gothic Spire House, with a deep red roof.", "customizationData": { "baseColor": "#8b0000", "texture": "roof_tiles_dark.png" }, "isPublic": false }
```
* **User Customization Data Example:**
```json
{ "baseColor": "#330033", "accentColor": "#6a0dad", "texture": "old_stone.jpg", "glowEffect": true }
```
* **Model Tags Array:**
```json
["haunted", "house", "gothic", "printable", "free"]
```
**9. TURKISH TRANSLATIONS:**
* **App Title:** Kağıt Hayaletler (Papercraft Haunts)
* **Homepage:**
* Headline: Dijital Kağıt Oyuncaklarla Hayal Gücünüzü Canlandırın!
* Sub-headline: Ücretsiz modelleri tasarlayın, özelleştirin ve Artırılmış Gerçeklik ile evinize getirin.
* CTA: Modelleri Keşfet
* **Model Browser:**
* Title: Modeller
* Search Placeholder: Model ara...
* Filter Button: Filtrele
* Premium Badge: Premium
* Free Label: Ücretsiz
* **Model Detail:**
* Title: Model Detayı
* Download Button: İndir (Ücretsiz)
* Customize Button: Özelleştir / Satın Al
* View in AR Button: AR'da Gör
* **Editor:**
* Title: Tasarım Editörü
* Save Button: Kaydet
* Project Name Label: Proje Adı
* Color Picker Label: Renk Seç
* Texture Label: Doku Seç
* **Auth:**
* Sign Up: Kayıt Ol
* Sign In: Giriş Yap
* Email: E-posta
* Password: Şifre
* Forgot Password?: Şifremi Unuttum?
* **Dashboard/Projects:**
* Title: Projelerim
* New Project Button: Yeni Proje
* Project Name Column: Proje Adı
* Date Created Column: Oluşturma Tarihi
* Actions: Eylemler
* Edit: Düzenle
* Delete: Sil
* Make Public: Herkese Aç
* **AR View:**
* Instruction: Kameranızı düz bir yüzeye doğrultun.
* Take Photo Button: Fotoğraf Çek
* Record Video Button: Video Kaydet
**10. ANIMATIONS:**
* **Page Transitions:** Subtle fade-in/fade-out transitions between pages using `next/transitions` or Framer Motion.
* **Hover Effects:** Buttons and cards have slight scale-up or background-color changes on hover.
* **Loading States:** Use shadcn/ui `Skeleton` or `Spinner` components for data loading. AR view initialization should show a loading indicator.
* **Subtle Background Effects:** Animated particle effects or subtle parallax scrolling on the homepage.
* **3D Model Idle Animation:** For specific premium models, implement a gentle, looping idle animation within the 3D viewer and AR scene.
**11. EDGE CASES:**
* **Authentication:** Handle expired tokens, incorrect credentials gracefully. Ensure protected routes redirect correctly. Implement password reset flow.
* **Empty States:** Display user-friendly messages and visuals for when there are no models to display, no user projects, or no search results.
* **Data Validation:** Use Zod with React Hook Form for all user inputs (forms, project names, etc.). Validate model IDs and customization data on the backend.
* **AR Permissions:** Gracefully handle cases where the user denies camera permissions or if the device does not support AR/WebXR.
* **Model Loading Errors:** Implement error handling for 3D model file loading failures. Display a placeholder or error message.
* **Offline Support:** (Future consideration) Service workers for basic offline viewing of downloaded models/templates.
* **API Errors:** Generic error messages for API failures, with more specific logging for developers.
* **Responsiveness:** Ensure all components and AR experiences function correctly across various devices and screen sizes.