Project Overview:
Build a high-performance SaaS application called "ErosionPro" that allows users to generate realistic and visually stunning terrain erosion effects on heightmaps or basic 3D primitives quickly. The core problem solved is the computational cost and time associated with traditional erosion simulation methods. ErosionPro offers a procedural, shader-based approach, enabling artists and developers to achieve high-quality erosion results in seconds, suitable for game development, VR/AR experiences, architectural visualization, and procedural content generation without lengthy simulation times or complex setups.
Value Proposition: Generate gorgeous, realistic terrain erosion effects instantly without complex simulations. Speed up your content creation workflow and enhance visual fidelity with our powerful, easy-to-use SaaS platform.
Tech Stack:
- Frontend: Next.js (App Router), React, Tailwind CSS, shadcn/ui for components, Zustand or Jotai for state management, three.js for 3D preview.
- Backend: Next.js API Routes or a dedicated Node.js/Express server.
- Database: PostgreSQL with Drizzle ORM.
- Shader Language: GLSL (for WebGL shaders).
- Authentication: NextAuth.js (Auth.js).
- Deployment: Vercel or similar cloud platform.
- Other Libraries: Axios for API requests, react-konva or similar for 2D canvas manipulation if needed for heightmap editing, a robust charting library (e.g., Chart.js or Recharts) for visualizing parameter impacts.
Database Schema:
1. `users` table:
- `id`: UUID (Primary Key)
- `name`: VARCHAR
- `email`: VARCHAR (Unique)
- `emailVerified`: TIMESTAMP (Nullable)
- `image`: VARCHAR (Nullable)
- `createdAt`: TIMESTAMP (Default: NOW())
- `updatedAt`: TIMESTAMP (Default: NOW())
2. `projects` table:
- `id`: UUID (Primary Key)
- `userId`: UUID (Foreign Key to `users.id`)
- `name`: VARCHAR
- `description`: TEXT (Nullable)
- `createdAt`: TIMESTAMP (Default: NOW())
- `updatedAt`: TIMESTAMP (Default: NOW())
3. `erosionSettings` table:
- `id`: UUID (Primary Key)
- `projectId`: UUID (Foreign Key to `projects.id`)
- `userId`: UUID (Foreign Key to `users.id`)
- `baseType`: ENUM('heightmap', 'primitive') // primitive could be 'plane', 'cube'
- `heightmapName`: VARCHAR (Nullable) // Original filename if uploaded
- `primitiveSettings`: JSONB (Nullable) // e.g., { width: 100, height: 100, widthSegments: 50, heightSegments: 50 } for plane
- `erosionParameters`: JSONB // Stores all erosion parameters (e.g., {"flowRate": 0.5, "sedimentationRate": 0.2, "terrainHardness": 0.8, ...})
- `createdAt`: TIMESTAMP (Default: NOW())
- `updatedAt`: TIMESTAMP (Default: NOW())
4. `generatedTerrains` table:
- `id`: UUID (Primary Key)
- `erosionSettingId`: UUID (Foreign Key to `erosionSettings.id`)
- `userId`: UUID (Foreign Key to `users.id`)
- `outputFormat`: ENUM('heightmap', 'normalmap', 'albedo', 'rendered')
- `outputUrl`: VARCHAR // URL to the generated asset (e.g., S3 bucket)
- `generationTimeMs`: INTEGER
- `generatedAt`: TIMESTAMP (Default: NOW())
Core Features & User Flow:
1. **User Authentication:**
* Flow: User lands on the homepage -> Clicks 'Sign Up' or 'Login' -> Redirected to NextAuth.js login page (email/password, Google, GitHub) -> Upon successful auth, redirected to dashboard.
* Edge Case: Handle OAuth callback errors, email verification flow.
2. **Project Management:**
* Flow: Authenticated user sees 'My Projects' dashboard -> Clicks 'New Project' -> Enters project name/description -> Project created and user is redirected to the project editor.
* Features: Create, View, Edit (name, description), Delete Projects.
* Edge Case: Project name validation, handling deleted projects.
3. **Erosion Generation:**
* Flow: Within a project -> User clicks 'New Erosion' -> Chooses base type ('heightmap' or 'primitive') -> If 'heightmap', uploads a heightmap file (e.g., .png, .raw) OR uses a default placeholder -> If 'primitive', selects primitive type (e.g., 'plane') and configures basic dimensions -> User accesses the 'Erosion Parameters' panel -> Adjusts sliders/inputs for parameters like flow rate, sedimentation, terrain hardness, etc. -> A live (or near-live) 3D preview updates using three.js and a GLSL shader -> User clicks 'Generate' -> Backend processes the request (potentially queues it if heavy) -> User is notified upon completion -> User can preview/download the result (heightmap, normal map, etc.).
* Features: Heightmap upload, primitive selection, parameter adjustment, real-time (or near real-time) preview, asynchronous generation, multiple output formats (heightmap, normal map, albedo, basic render).
* Edge Cases: Invalid heightmap format/size, generation failure, large file handling, queue management for backend tasks, parameter validation.
4. **Asset Management & Download:**
* Flow: After generation, results are listed under the project -> User can click to preview -> Clicks 'Download' -> Selects desired format -> File is downloaded.
* Features: List generated assets, preview results, download in various formats.
* Edge Cases: Download errors, expired asset links.
API & Data Fetching:
- **`/api/auth/*`**: Handled by NextAuth.js for authentication.
- **`/api/projects` (POST, GET, PUT, DELETE):** CRUD operations for user projects.
* POST ` /api/projects`: `{ name: string, description?: string }` -> `{ id: string, ... }`
* GET ` /api/projects`: `[]` (Array of project objects for the logged-in user)
- **`/api/projects/[projectId]/erosionSettings` (POST, GET):** CRUD for erosion settings associated with a project.
* POST ` /api/projects/[projectId]/erosionSettings`: `{ baseType: 'heightmap'|'primitive', heightmapFile?: File, primitiveSettings?: object, erosionParameters: object }` -> `{ id: string, ... }`
* GET ` /api/projects/[projectId]/erosionSettings`: `[]` (Array of settings)
- **`/api/generate` (POST):** Initiates the erosion generation process.
* POST ` /api/generate`: `{ erosionSettingId: string }` -> `{ jobId: string, status: 'queued'|'processing'|'completed'|'failed' }`
- **`/api/generate/status/[jobId]` (GET):** Polls for the status of a generation job.
* GET ` /api/generate/status/[jobId]`: ` { status: 'queued'|'processing'|'completed'|'failed', results?: [{ format: string, url: string }] }`
- **`/api/assets/[assetId]/download` (GET):** Serves the generated asset for download.
Data Fetching:
- Frontend components will use `fetch` or libraries like `axios` to interact with these API routes.
- Server Components in Next.js App Router will fetch project data directly from the DB using Drizzle ORM.
- Client Components will fetch settings, generation status, and asset lists.
- Real-time preview will be handled client-side using three.js and WebGL shaders, potentially re-running a simplified shader pass on parameter change.
UI/UX Design & Visual Identity:
- **Style:** Modern, Clean, Functional. Emphasis on clarity and ease of use.
- **Color Palette:** Primary: Deep Teal (#008080), Secondary: Dark Gray (#282c34), Accent: Bright Cyan (#40e0d0), Neutral: Light Gray (#f0f0f0) and Off-White (#fafafa).
* Dark Mode Primary: Off-Black (#1a1a1a)
* Dark Mode Accent: Bright Cyan (#40e0d0)
- **Typography:** Sans-serif, highly readable. Example: Inter or Poppins.
- **Layout:**
* Dashboard: Sidebar navigation (Projects, Settings, Account), main content area displaying projects in cards or list view.
* Project Editor: Main area for 3D preview (using three.js), left or right sidebar for upload/primitive controls and erosion parameter sliders/inputs. Top bar for project name, save, generate actions.
* Components: Use shadcn/ui components for consistency (Buttons, Inputs, Sliders, Dialogs, Cards, Tabs).
- **Responsiveness:** Mobile-first approach. Sidebars collapse into drawers/menus on smaller screens. Preview area resizes gracefully. Key controls remain accessible.
- **Visual Elements:** Subtle gradients in the background, clean icons, smooth transitions between states.
Component Breakdown (Next.js App Router structure):
- `(app)/layout.tsx`: Root layout, Tailwind CSS setup, global providers (Auth, Theme).
- `(app)/page.tsx`: Landing page (marketing, features overview, CTA).
- `(app)/auth/page.tsx`: Login/Signup page using NextAuth.js components.
- `(app)/dashboard/layout.tsx`: Dashboard layout with sidebar.
- `(app)/dashboard/page.tsx`: Displays user's projects (list/card view). Uses Server Components to fetch projects.
- `(app)/projects/[projectId]/layout.tsx`: Layout for the project editor.
- `(app)/projects/[projectId]/page.tsx`: The main project editor page. Contains:
* `ProjectHeader.tsx`: Displays project name, save button, generate button. (Client Component)
* `PreviewCanvas.tsx`: Renders the 3D preview using `three.js` and GLSL shader. Handles user interaction for camera control. (Client Component)
* `ControlsPanel.tsx`: Contains tabs/sections for:
* `InputControls.tsx`: Heightmap upload or primitive selection. (Client Component)
* `ErosionParams.tsx`: Sliders and inputs for all erosion parameters. Triggers preview updates. (Client Component)
* `OutputSettings.tsx`: Options for download format, resolution. (Client Component)
* `GenerationStatus.tsx`: Displays the status of ongoing or completed generation jobs. (Client Component)
* `AssetList.tsx`: Shows downloadable results. (Client Component)
- `(app)/settings/page.tsx`: User account and application settings.
- `@/components/ui/*`: Re-exported shadcn/ui components.
- `@/components/common/*`: Shared components like `Navbar.tsx`, `Footer.tsx`, `LoadingSpinner.tsx`.
- `@/lib/db.ts`: Drizzle ORM setup.
- `@/lib/shaders/erosion.glsl`: The core GLSL shader code.
- `@/hooks/useErosion.ts`: Custom hook for managing generation state and API calls.
Animations:
- **Page Transitions:** Subtle fade-in/out using `Framer Motion` or CSS transitions on route changes.
- **Button Hovers:** Slight scale-up or color change on hover.
- **Loading States:** Use `shadcn/ui`'s loading indicators or custom spinners with smooth transitions during data fetching or generation.
- **Parameter Sliders:** Smooth visual feedback in the preview as sliders are dragged.
- **UI Elements:** Fade-in animations for newly added items (e.g., generated assets).
Edge Cases:
- **Authentication:** Handle expired sessions, ensure API routes are protected.
- **Empty States:** Display informative messages and clear CTAs when there are no projects, no generated assets, etc.
- **Form Validation:** Client-side and server-side validation for all inputs (project names, dimensions, parameters).
- **Error Handling:** Graceful error display for API failures, generation errors, invalid uploads. Provide user-friendly error messages and potential solutions.
- **Large File Uploads:** Implement chunking or use services designed for large file uploads if necessary. Provide clear progress indicators.
- **Generation Queuing:** Implement a robust queuing system (e.g., using Redis Queue or similar) for handling potentially long-running generation tasks to prevent server overload and timeouts.
- **Permissions:** Ensure users can only access and modify their own projects and settings.
- **Browser Compatibility:** Test WebGL/three.js rendering across major modern browsers.
Sample Data:
1. **User:**
```json
{
"id": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"name": "Alice Smith",
"email": "alice@example.com"
}
```
2. **Project:**
```json
{
"id": "f0e9d8c7-b6a5-4321-fedc-ba9876543210",
"userId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"name": "Mountain Valley Erosion",
"description": "Initial test for mountain range erosion."
}
```
3. **Erosion Setting (Heightmap based):**
```json
{
"id": "12345678-90ab-cdef-1234-567890abcdef",
"projectId": "f0e9d8c7-b6a5-4321-fedc-ba9876543210",
"userId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"baseType": "heightmap",
"heightmapName": "original_terrain.png",
"erosionParameters": {
"flowRate": 0.6,
"sedimentationRate": 0.3,
"terrainHardness": 0.7,
"initialWater": 1.0,
"gravity": 9.81
}
}
```
4. **Erosion Setting (Primitive - Plane):**
```json
{
"id": "abcdef12-3456-7890-abcd-ef1234567890",
"projectId": "f0e9d8c7-b6a5-4321-fedc-ba9876543210",
"userId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"baseType": "primitive",
"primitiveSettings": {
"type": "plane",
"width": 200,
"height": 200,
"widthSegments": 100,
"heightSegments": 100
},
"erosionParameters": {
"flowRate": 0.45,
"sedimentationRate": 0.25,
"terrainHardness": 0.85,
"initialWater": 0.8,
"gravity": 9.81
}
}
```
5. **Generated Terrain Asset:**
```json
{
"id": "98765432-10fe-dcba-9876-543210fedcba",
"erosionSettingId": "12345678-90ab-cdef-1234-567890abcdef",
"userId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"outputFormat": "heightmap",
"outputUrl": "https://cdn.example.com/assets/terrain_hm_1.png",
"generationTimeMs": 3500,
"generatedAt": "2024-07-27T10:30:00Z"
}
```
6. **Generated Terrain Asset (Normal Map):**
```json
{
"id": "11223344-5566-7788-9900-aabbccddeeff",
"erosionSettingId": "12345678-90ab-cdef-1234-567890abcdef",
"userId": "a1b2c3d4-e5f6-7890-1234-567890abcdef",
"outputFormat": "normalmap",
"outputUrl": "https://cdn.example.com/assets/terrain_nm_1.png",
"generationTimeMs": 4200,
"generatedAt": "2024-07-27T10:30:05Z"
}
```
7. **Mock Heightmap Data (Conceptual for Frontend Dev):** A 2D array representing pixel height values, e.g., `[[0.1, 0.15, ...], [0.12, 0.17, ...], ...]`. This would be used to populate the initial state of the `PreviewCanvas` before a real upload or for placeholders.
8. **Default Primitive Settings:** ` { type: 'plane', width: 100, height: 100, widthSegments: 50, heightSegments: 50 }`
9. **Default Erosion Parameters:** `{ flowRate: 0.5, sedimentationRate: 0.2, terrainHardness: 0.8, initialWater: 1.0, gravity: 9.81, ... }`
10. **Generation Job Status (Queued):** `{ jobId: 'job-xyz-789', status: 'queued' }`