You are an AI assistant tasked with generating a fully functional, multi-page Next.js MVP application for 'Echo Archive' (Ses Arşivi). The application will serve as a digital archive for obsolete and rare sounds, allowing users to upload, discover, listen to, and download these unique audio assets. The goal is to create a platform that preserves auditory heritage and makes these sounds accessible for creative projects.
**1. PROJECT OVERVIEW:**
Echo Archive aims to solve the problem of disappearing and hard-to-find sounds from history and specific environments. It provides a centralized, searchable platform for obsolete sounds – from old machinery and natural phenomena to historical broadcasts and extinct animal calls. The core value proposition is to be the definitive digital repository for auditory artifacts, empowering creators with unique soundscapes and preserving sonic history for future generations. Users can upload their own found sounds, contribute to the archive, and license sounds for use in media, games, music, and research.
**2. TECH STACK:**
- **Framework:** Next.js (App Router)
- **Language:** TypeScript
- **Styling:** Tailwind CSS
- **UI Components:** shadcn/ui (for accessible, customizable components)
- **Database ORM:** Drizzle ORM (PostgreSQL compatible)
- **Database:** PostgreSQL (or Supabase/Neon for ease of use)
- **Authentication:** NextAuth.js (with credentials provider initially, potentially Google/GitHub OAuth later)
- **State Management:** React Context API / Zustand (for global state like auth status, UI themes)
- **Form Handling:** React Hook Form + Zod for validation
- **Audio Player:** `react-use-audio-player` or similar lightweight library
- **Deployment:** Vercel
**3. DATABASE SCHEMA (Drizzle ORM - PostgreSQL):**
```typescript
// schema.ts
import { pgTable, serial, text, timestamp, varchar, integer, boolean, pgEnum } from 'drizzle-orm/pg-core';
import { relations } from 'drizzle-orm';
// Enum for audio file format
export const audioFormatEnum = pgEnum('audio_format', ['mp3', 'wav', 'ogg', 'flac']);
// Enum for license type
export const licenseTypeEnum = pgEnum('license_type', ['cc-by', 'cc-by-sa', 'commercial', 'personal-use']);
// Users Table
export const users = pgTable('users', {
id: serial('id').primaryKey(),
clerkUserId: varchar('clerk_user_id', { length: 255 }).unique().notNull(), // If using Clerk, otherwise use standard auth IDs
email: varchar('email', { length: 255 }).unique().notNull(),
name: varchar('name', { length: 255 }),
avatarUrl: text('avatar_url'),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const usersRelations = relations(users, ({ many }) => ({
uploads: many(audioFiles),
}));
// Audio Files Table
export const audioFiles = pgTable('audio_files', {
id: serial('id').primaryKey(),
userId: integer('user_id').notNull().references(() => users.id, { onDelete: 'CASCADE' }),
title: varchar('title', { length: 255 }).notNull(),
description: text('description'),
filePath: text('file_path').notNull(), // URL to the stored audio file (e.g., S3 bucket URL)
fileName: varchar('file_name', { length: 255 }).notNull(), // Original uploaded filename
format: audioFormatEnum('format').notNull(),
duration: integer('duration'), // Duration in seconds
tags: text('tags').array(), // Array of tags
license: licenseTypeEnum('license').notNull(),
isPublic: boolean('is_public').default(true),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
export const audioFilesRelations = relations(audioFiles, ({ one, many }) => ({
user: one(users, {
fields: [audioFiles.userId],
references: [users.id],
}),
// Add relations for comments, ratings etc. if expanding MVP
}));
// Potential future tables:
// - Categories/Genres
// - Comments
// - Ratings
// - Collections/Playlists
```
**4. CORE FEATURES & USER FLOW:**
* **User Authentication (Sign Up / Sign In):**
* **Flow:** User navigates to `/auth/signin`. Clicks "Sign In" or "Sign Up". Redirected to a modal or dedicated page. Uses email/password with NextAuth.js credentials provider. Upon successful auth, user is redirected to the dashboard. Auth status is managed globally.
* **Edge Cases:** Invalid credentials, account already exists, password reset (out of MVP scope, but consider placeholder).
* **Dashboard (`/dashboard`):**
* **Flow:** Authenticated users land here. Displays recently uploaded files, most popular sounds, quick access to "Upload New Sound" and search.
* **Components:** Welcome message, `AudioFileList` component (showing user's uploads), `FeaturedSounds` carousel/grid, quick action buttons.
* **State:** User info, list of user's audio files, list of featured audio files.
* **Upload New Sound (`/dashboard/upload`):**
* **Flow:** User navigates to upload page. Clicks "Choose File". Selects an audio file (MP3, WAV, OGG initially). Form appears to input Title, Description, Tags (comma-separated), License Type. User submits the form. File is uploaded to a cloud storage (e.g., AWS S3 via a server action/API route), metadata is saved to the database. Progress indicator shown during upload.
* **Components:** File input, multi-line text inputs for title/description, tag input (can be a simple text input initially), select dropdown for license, submit button, progress bar.
* **Validation:** Title is required, file must be audio format, size limits.
* **Server Actions/API:** `POST /api/upload` to handle file upload and metadata insertion.
* **My Sounds (`/dashboard/my-sounds`):**
* **Flow:** Displays a table/list of all audio files uploaded by the logged-in user. Each row shows title, format, date uploaded, license. Options to Edit metadata, Delete, or Download the file.
* **Components:** `DataTable` component with columns for Title, Format, Date, License, Actions. Edit/Delete/Download buttons.
* **Server Actions/API:** `GET /api/my-sounds` to fetch user's files, `DELETE /api/sounds/[id]` to delete.
* **Explore Sounds (`/explore`):**
* **Flow:** Publicly accessible page showing all `isPublic = true` audio files. Features a search bar, filtering/sorting options (by tag, license, date), and a grid/list view of sounds.
* **Components:** Search input, Filter/Sort controls, `AudioGridItem` component for each sound (displaying title, Uploader, license, play button).
* **Server Actions/API:** `GET /api/sounds` to fetch public sounds, supporting query params for search/filter.
* **Sound Detail Page (`/sounds/[id]`):**
* **Flow:** Displays detailed information about a specific sound. Includes a prominent audio player, title, description, uploader (linked to profile), tags, license information. Download button (conditionally enabled based on license and auth status).
* **Components:** `AudioPlayer` component, metadata display (title, description, tags, uploader name), license badge, Download button.
* **Server Actions/API:** `GET /api/sounds/[id]` to fetch single sound details.
**5. API & DATA FETCHING:**
- Use Next.js API Routes or Server Actions for all backend logic.
- **Endpoints (RESTful conventions):**
- `POST /api/auth/signup`, `POST /api/auth/signin` (Handled by NextAuth.js)
- `GET /api/sounds`: Fetch public sounds with filtering/sorting/pagination.
- `GET /api/sounds/[id]`: Fetch single sound details.
- `POST /api/sounds`: Upload new sound (handles file upload to storage and DB entry).
- `PUT /api/sounds/[id]`: Update sound metadata.
- `DELETE /api/sounds/[id]`: Delete a sound.
- `GET /api/my-sounds`: Fetch sounds uploaded by the current user.
- **Data Fetching:** Primarily use Server Components for initial page loads (fetching data directly in the component) and Client Components with `fetch` or libraries like `SWR` for dynamic data, form submissions, and real-time updates. Use `revalidatePath` or `revalidateTag` after mutations.
- **Request/Response:** Standard JSON payloads. For uploads, use `multipart/form-data`.
**6. COMPONENT BREAKDOWN (Next.js App Router):**
* **`app/layout.tsx`:** Root layout (html, body, global providers - ThemeProvider, AuthProvider).
* **`app/page.tsx`:** Landing Page (Public - marketing info, call to action).
* **`app/explore/page.tsx`:** Explore sounds page (Public). Contains `SearchFilter`, `AudioGrid`. Fetches data server-side.
* **`app/sounds/[id]/page.tsx`:** Sound Detail page (Public). Fetches data server-side. Contains `AudioPlayer`, `SoundDetails` component.
* **`app/dashboard/page.tsx`:** User Dashboard (Protected). Contains `UserWelcome`, `UserAudioList`, `FeaturedSounds`. Fetches user-specific data server-side.
* **`app/dashboard/upload/page.tsx`:** Upload sound page (Protected). Contains `SoundUploadForm` component.
* **`app/dashboard/my-sounds/page.tsx`:** My Sounds page (Protected). Contains `UserAudioTable` component.
* **`app/auth/signin/page.tsx`:** Sign In/Sign Up page (Public). Uses NextAuth.js components or custom form.
* **`components/ui/`:** Shared shadcn/ui components (Button, Input, Card, Sheet, Table, Tooltip, etc.).
* **`components/layout/`:** `Navbar`, `Footer`, `Sidebar` (for dashboard).
* **`components/audio/`:** `AudioPlayer` (with play/pause, seek bar, volume), `AudioGridItem` (card for explore/dashboard).
* **`components/forms/`:** `SoundUploadForm`, `EditSoundForm`.
* **`components/data/`:** `AudioFileList`, `UserAudioTable`, `FeaturedSounds`.
* **`lib/`:** Utility functions, API client helpers, auth utils.
* **`db/`:** Drizzle ORM schema, migrations, database client setup.
**7. UI/UX DESIGN & VISUAL IDENTITY:**
* **Design Style:** Minimalist Clean with subtle dark/light mode support. Focus on clarity, ease of navigation, and showcasing the audio content.
* **Color Palette:**
* **Light Mode:** Primary: `#1E40AF` (Deep Blue), Secondary: `#3B82F6` (Bright Blue), Accent: `#10B981` (Green), Background: `#FFFFFF`, Text: `#1F2937` (Dark Gray)
* **Dark Mode:** Primary: `#93C5FD` (Light Blue), Secondary: `#3B82F6` (Bright Blue), Accent: `#10B981` (Green), Background: `#030712` (Very Dark Blue/Black), Text: `#F3F4F6` (Light Gray)
* **Typography:** Sans-serif fonts like Inter or Poppins for headings and body text. Ensure good readability and hierarchy.
* **Layout:** Standard header/footer. Dashboard features a sidebar navigation. Content areas are spacious with clear visual separation.
* **Responsiveness:** Mobile-first approach. Use Tailwind's responsive prefixes (sm:, md:, lg:) extensively. Ensure navigation and key components (player, forms) are usable on small screens.
**8. SAMPLE/MOCK DATA:**
* **User:** `id: 1, clerkUserId: 'user_abc123', email: 'creator@example.com', name: 'Audio Explorer', avatarUrl: '/avatars/default.png'`
* **Audio File 1 (Old Factory Machine):** `id: 101, userId: 1, title: 'Vintage Steam Engine Whistle', description: 'The loud, echoing whistle of a steam engine from a 1920s factory.', filePath: 'https://your-storage.com/sounds/steam_whistle.mp3', fileName: 'steam_whistle.mp3', format: 'mp3', duration: 15, tags: ['industrial', 'vintage', 'steam', 'factory', 'whistle'], license: 'cc-by', isPublic: true`
* **Audio File 2 (Nature - Extinct Bird):** `id: 102, userId: 1, title: 'Call of the Passenger Pigeon', description: 'A recorded attempt to replicate the call of the extinct passenger pigeon.', filePath: 'https://your-storage.com/sounds/passenger_pigeon.wav', fileName: 'passenger_pigeon.wav', format: 'wav', duration: 8, tags: ['nature', 'bird', 'extinct', 'animal', 'call'], license: 'personal-use', isPublic: true`
* **Audio File 3 (Technology - Dial-up):** `id: 103, userId: 1, title: 'Modem Dial-up Connection', description: 'The iconic sound sequence of a 56k modem establishing an internet connection.', filePath: 'https://your-storage.com/sounds/dialup.ogg', fileName: 'dialup.ogg', format: 'ogg', duration: 25, tags: ['technology', 'internet', 'modem', 'dial-up', '90s'], license: 'cc-by-sa', isPublic: true`
* **Audio File 4 (User's Private Upload):** `id: 104, userId: 1, title: 'My Workshop Ambiance', description: 'Background sounds from my woodworking shop.', filePath: 'https://your-storage.com/sounds/workshop.flac', fileName: 'workshop.flac', format: 'flac', duration: 120, tags: ['ambiance', 'workshop', 'tools', 'woodworking'], license: 'personal-use', isPublic: false`
* **Audio File 5 (Radio Broadcast):** `id: 105, userId: 1, title: '1950s Radio Jingle', description: 'A short, catchy advertising jingle from a mid-century radio broadcast.', filePath: 'https://your-storage.com/sounds/radio_jingle.mp3', fileName: 'radio_jingle.mp3', format: 'mp3', duration: 10, tags: ['vintage', 'radio', 'advertisement', 'jingle', '50s'], license: 'commercial', isPublic: true`
**9. TURKISH TRANSLATIONS:**
- **App Title:** Ses Arşivi
- **Navbar Links:** Keşfet, Yükle, Benim Seslerim, Giriş Yap, Kayıt Ol
- **Buttons:** Ses Yükle, Kaydet, İndir, Sil, Düzenle, Arama Yap, Filtrele
- **Labels:** Başlık, Açıklama, Etiketler, Lisans Türü, Dosya Seç
- **Page Titles:** Sesleri Keşfet, Yeni Ses Yükle, Benim Seslerim, Ses Detayları, Gösterge Paneli
- **Placeholders:** Ses başlığı girin, Ses açıklamasını yazın, Etiketleri virgülle ayırın
- **Notifications:** Ses başarıyla yüklendi!, Ses silindi., Hata oluştu.
- **Empty States:** Henüz hiç ses yüklemediniz., Bu kategoride hiç ses bulunamadı.
**10. ANIMATIONS & TRANSITIONS:**
- Use subtle fade-in/fade-out transitions for page loads and component reveals (e.g., using Framer Motion or CSS transitions).
- Animate button hover states (slight scale up or color change).
- Implement loading spinners/skeletons for data fetching states, especially for the audio player and data tables.
- Smooth transitions for expanding/collapsing sections or filter menus.
**11. EDGE CASES & VALIDATION:**
- **Authentication:** Handle cases where user session expires or is invalid gracefully, prompting re-login.
- **File Upload:** Implement robust validation for file types (MIME types and extensions), file size limits (e.g., 100MB for MVP). Handle network errors during upload. Provide clear user feedback on upload status (progress, success, failure).
- **Data Fetching:** Display loading states while data is being fetched. Show user-friendly error messages if API calls fail. Implement empty state UIs for lists/tables when no data is available (e.g., 'No sounds uploaded yet.').
- **Permissions:** Ensure users can only edit/delete their own uploaded files. Publicly accessible routes should not require authentication.
- **Audio Player:** Handle cases where audio fails to load or play. Ensure player state is managed correctly (e.g., pausing other players when a new one starts).
- **Form Validation:** Use Zod with React Hook Form for client-side and server-side validation on all input fields (required fields, format validation for tags if needed).