Project Overview:
Build a fully functional Next.js MVP application called 'Nomad Archive'. This application acts as a personal, offline-first knowledge server and digital archive. It allows users to download, manage, and access vast amounts of information without an internet connection. The core value proposition is digital independence, data sovereignty, and ubiquitous access to knowledge and tools, especially in environments with unreliable or no internet connectivity. Key content includes Wikipedia dumps, offline maps, educational resources (like Khan Academy), and the ability to run local Large Language Models (LLMs). The target audience ranges from preppers and off-grid enthusiasts to privacy-conscious tech individuals and students needing offline learning materials.
Tech Stack:
- Frontend Framework: React with Next.js (App Router)
- Styling: Tailwind CSS
- ORM: Drizzle ORM (PostgreSQL compatible, for example, with Neon or Turso)
- Database: PostgreSQL (or a compatible alternative like Turso for edge deployments)
- Authentication: NextAuth.js (or Clerk for easier integration)
- UI Components: shadcn/ui (built on Radix UI and Tailwind CSS)
- State Management: React Context API / Zustand (for global state)
- Offline Data Handling: Local storage / IndexedDB (for metadata and smaller files), potentially a local file system access API for larger downloads.
- LLM Integration: Ollama (for local LLM execution) or a similar local inference engine. Direct API calls for local models.
- Icons: Lucide React
- Form Handling: React Hook Form
- Data Fetching: React Server Components (RSC), Server Actions, and client-side fetching with SWR/React Query if needed.
- Deployment: Vercel or similar platform supporting Next.js.
Database Schema (PostgreSQL with Drizzle ORM):
1. `users` table:
* `id` (UUID, primary key)
* `email` (VARCHAR, unique, not null)
* `name` (VARCHAR)
* `hashedPassword` (VARCHAR, not null)
* `emailVerified` (TIMESTAMP)
* `image` (VARCHAR)
* `createdAt` (TIMESTAMP, default NOW())
* `updatedAt` (TIMESTAMP, default NOW())
2. `accounts` table (for NextAuth.js):
* `id` (BIGSERIAL, primary key)
* `userId` (UUID, foreign key to users.id)
* `type` (VARCHAR, not null)
* `provider` (VARCHAR, not null)
* `providerAccountId` (VARCHAR, not null)
* `refresh_token` (TEXT)
* `access_token` (TEXT)
* `expires_at` (BIGINT)
* `token_type` (VARCHAR)
* `scope` (VARCHAR)
* `id_token` (TEXT)
* `session_state` (VARCHAR)
* `oauth_token_secret` (TEXT)
* `oauth_callback_url` (VARCHAR)
3. `sessions` table (for NextAuth.js):
* `id` (BIGSERIAL, primary key)
* `sessionToken` (VARCHAR, unique, not null)
* `userId` (UUID, foreign key to users.id)
* `expires` (TIMESTAMP, not null)
4. `verificationTokens` table (for NextAuth.js):
* `identifier` (VARCHAR, not null)
* `token` (VARCHAR, not null)
* `expires` (TIMESTAMP, not null)
5. `content_categories` table:
* `id` (SERIAL, primary key)
* `name` (VARCHAR, unique, not null) // e.g., 'Wikipedia', 'Offline Maps', 'LLM Models', 'Education'
* `description` (TEXT)
* `icon` (VARCHAR) // e.g., icon name from Lucide React
6. `content_items` table:
* `id` (SERIAL, primary key)
* `categoryId` (INTEGER, foreign key to content_categories.id)
* `name` (VARCHAR, not null) // e.g., 'English Wikipedia Dump (2024-01)', 'OpenStreetMap - Europe', 'Llama 3 8B Model'
* `description` (TEXT)
* `size_bytes` (BIGINT) // Size of the download
* `downloadUrl` (VARCHAR) // Direct download link or identifier for local download script
* `version` (VARCHAR) // e.g., '2024-01-01'
* `isAvailableOffline` (BOOLEAN, default: false)
* `localPath` (VARCHAR) // Path where the content is stored locally
* `lastDownloadedAt` (TIMESTAMP)
7. `user_content` table (Tracks which content a user has downloaded):
* `userId` (UUID, foreign key to users.id)
* `contentItemId` (INTEGER, foreign key to content_items.id)
* `downloadProgress` (INTEGER, 0-100)
* `isDownloaded` (BOOLEAN, default: false)
* `addedAt` (TIMESTAMP, default NOW())
* `PRIMARY KEY (userId, contentItemId)`
8. `llm_models` table (Specific for LLMs, could be part of content_items or separate):
* `id` (SERIAL, primary key)
* `name` (VARCHAR, unique, not null) // e.g., 'llama3:8b', 'mistral:7b'
* `description` (TEXT)
* `downloadUrl` (VARCHAR) // Link to model file or Ollama library
* `size_bytes` (BIGINT)
* `installedPath` (VARCHAR) // Path to model file locally
* `isInstalled` (BOOLEAN, default: false)
* `userId` (UUID, foreign key to users.id, if per-user models)
9. `user_notes` table (For personal notes):
* `id` (SERIAL, primary key)
* `userId` (UUID, foreign key to users.id)
* `title` (VARCHAR, not null)
* `content` (TEXT)
* `createdAt` (TIMESTAMP, default NOW())
* `updatedAt` (TIMESTAMP, default NOW())
Core Features & User Flow:
1. Authentication:
* User lands on the landing page.
* Options: Sign Up, Log In, Browse Public Content (limited).
* Sign Up: Email, Password, Confirm Password. On submit, hash password, create user in DB, send verification email (optional for MVP, can skip for simplicity). Redirect to login.
* Log In: Email, Password. Validate credentials against DB. If valid, create a session using NextAuth.js. Redirect to Dashboard.
* Password Reset: (Future enhancement) Email verification flow.
* OAuth: Google/GitHub login via NextAuth.js.
* MVP Flow: Email/Password signup and login, potentially Google OAuth.
2. Content Discovery & Download:
* User navigates to the 'Library' or 'Discover' page.
* Displays `content_categories` with associated `content_items`.
* Each item shows name, description, size. A 'Download' button is present.
* Clicking 'Download':
* For authenticated users: Creates an entry in `user_content` table with `isDownloaded: false`, `downloadProgress: 0`.
* Initiates a background download process (using a separate service or a Next.js Server Action that handles streaming).
* Updates `downloadProgress` in `user_content` periodically.
* Upon completion: Sets `isDownloaded: true`, `lastDownloadedAt`, updates `localPath` in `content_items` if necessary. Notifies the user (e.g., toast notification).
* For unauthenticated users: Prompt to log in or sign up.
* Offline Note: The download mechanism needs careful implementation. For large files, it might involve streaming directly to the user's file system (challenging in browsers) or instructing the user to download via a link and then manually import/verify. For MVP, we can simulate downloads or use smaller placeholder files. A robust solution might involve a desktop app wrapper or specific browser APIs.
3. Offline Content Access:
* User navigates to 'My Archive' or 'Downloads' page.
* Lists `content_items` where `user_content.userId` matches the current user and `isDownloaded` is true.
* Clicking an item:
* Wikipedia/Text: Opens in an in-app viewer component, rendering content from `localPath`.
* Maps: Loads map tiles/data from `localPath` using a compatible mapping library (e.g., Leaflet with local tile storage).
* LLM Models: Makes the model available for use in the AI Chat feature.
* Search Functionality: Within downloaded text-based content, implement a client-side search (e.g., using Fuse.js or similar library against local data) or a server-side search if data is indexed on the backend.
4. Local LLM Integration & Chat:
* User navigates to the 'AI Chat' page.
* Displays a list of available local LLMs (from `llm_models` table or detected via Ollama).
* User selects an LLM.
* Presents a chat interface (similar to ChatGPT).
* User input is sent to the local LLM inference engine (e.g., via API call to Ollama running locally on the user's machine or a server).
* Response from the LLM is displayed in the chat interface.
* State management handles the conversation history.
* MVP: Focus on integrating with a single, easily installable LLM like Llama 3 8B via Ollama. The app needs to guide the user on setting up Ollama.
5. Personal Notes:
* User navigates to 'Notes' page.
* Displays a list of `user_notes`.
* 'Create New Note' button.
* Clicking a note opens an editor (e.g., a simple textarea or a Rich Text Editor like TipTap/Quill).
* Saving the note triggers a Server Action to update/create the entry in the `user_notes` table.
* Search functionality for notes.
API & Data Fetching:
- NextAuth.js routes for authentication (`/api/auth/...`).
- Server Actions for mutations (creating notes, initiating downloads, user settings updates).
- React Server Components (RSC) for fetching and displaying data on initial page loads (e.g., `content_categories`, `user_content`, `user_notes`). This leverages Drizzle ORM directly within the Server Components.
- Client Components for interactive elements (download buttons, chat interface, note editor).
- API routes (if needed for specific async operations not suitable for Server Actions, e.g., `POST /api/download-chunk`).
- Data fetching for LLM responses will be client-side, making a `fetch` request to the local Ollama API endpoint (e.g., `http://localhost:11434/api/generate`). The app needs to handle potential connection errors to the local service.
UI/UX Design & Visual Identity:
- Style: Minimalist Clean with subtle futuristic elements.
- Color Palette:
* Primary (Dark Background): `#121212` (Very Dark Gray)
* Secondary (Accent): `#00bcd4` (Cyan Blue)
* Tertiary (Subtle Highlight): `#333333` (Dark Gray)
* Text (Light): `#e0e0e0` (Light Gray)
* Text (Muted): `#9e9e9e` (Medium Gray)
* Success: `#4caf50` (Green)
* Warning/Error: `#f44336` (Red)
- Typography:
* Headings: Inter (Bold, Semi-Bold)
* Body Text: Inter (Regular)
- Layout:
* Sidebar Navigation (collapsible) for main sections: Dashboard, Library, My Archive, AI Chat, Notes, Settings.
* Main content area displays selected section.
* Clean cards for content items, clear visual distinction between categories.
* Progress indicators for downloads.
* Standard chat interface layout.
- Responsive Rules:
* Sidebar collapses into a hamburger menu on smaller screens.
* Content cards reflow into fewer columns.
* Ensure readability and usability across desktop, tablet, and mobile.
Component Breakdown (Next.js App Router Structure):
- `app/layout.tsx`: Root layout, includes `<html>`, `<body>`, global providers (e.g., NextAuth SessionProvider, ThemeProvider), Tailwind CSS setup.
- `app/page.tsx`: Landing Page (public).
- `app/(auth)/login/page.tsx`: Login form.
- `app/(auth)/signup/page.tsx`: Signup form.
- `app/(app)/layout.tsx`: Authenticated layout, includes sidebar navigation and main content area.
- `app/(app)/dashboard/page.tsx`: Dashboard overview (e.g., download stats, recent notes, AI summary).
- `app/(app)/library/page.tsx`: Content discovery. Fetches `content_categories` and `content_items`. Displays categories and items, includes download buttons.
- `components/ui/ContentCard.tsx`: Displays individual content item info.
- `components/ui/DownloadButton.tsx`: Handles download initiation logic (calls Server Action).
- `components/ui/CategoryBrowser.tsx`: Filters/displays content by category.
- `app/(app)/archive/page.tsx`: Displays downloaded content. Lists items from `user_content`.
- `components/ui/ArchiveItem.tsx`: Represents a downloaded item, links to viewer/action.
- `components/ui/ContentViewer.tsx`: Generic viewer for text-based content (Markdown, plain text).
- `app/(app)/ai/page.tsx`: AI Chat interface.
- `components/chat/ChatWindow.tsx`: Main chat display area.
- `components/chat/MessageBubble.tsx`: Individual message display.
- `components/chat/ChatInput.tsx`: Text input and send button.
- `components/llm/ModelSelector.tsx`: Dropdown to choose local LLM.
- `app/(app)/notes/page.tsx`: Notes overview and editor.
- `components/notes/NoteList.tsx`: List of user notes.
- `components/notes/NoteEditor.tsx`: Rich Text Editor component (e.g., using TipTap).
- `app/(app)/settings/page.tsx`: User settings (profile, account management).
- `components/ui/Sidebar.tsx`: Collapsible navigation menu.
- `components/ui/Navbar.tsx`: Top navigation bar (visible on auth pages).
- `components/ui/Toast.tsx`: For notifications (e.g., download complete).
- `components/ui/LoadingSpinner.tsx`: Generic loading indicator.
State Management:
- Global state (Auth status, user info, possibly UI theme) via NextAuth SessionProvider and Zustand/Context.
- Local component state for forms, chat messages, editor content.
- Server Components handle data fetching, reducing the need for client-side state management for core data.
Animations:
- Page Transitions: Subtle fade-in/out using `next/transitions` or a library like `Framer Motion`.
- Hover Effects: Slight scale-up or background color change on interactive elements (buttons, cards) using Tailwind CSS utility classes (`hover:scale-105`, `hover:bg-gray-700`).
- Loading States: Use `LoadingSpinner` components within content areas while data is being fetched or downloads are in progress. Skeleton loaders for list items.
- Sidebar Toggle: Smooth slide or fade animation.
- Chat Bubbles: Appear with a slight fade-in/stagger effect.
Edge Cases:
- **Empty States**: 'My Archive', 'Notes', 'AI Chat' pages should display informative messages and clear calls-to-action when no data exists (e.g., 'No notes yet. Click "Create Note" to start.', 'Download some content to see it here.').
- **Authentication**: Ensure all protected routes (`/app/*`) redirect unauthenticated users to `/login`. Handle expired sessions gracefully.
- **Authorization**: Ensure users can only access their own data (notes, downloads). Use Server Actions/API routes with user ID checks.
- **Download Errors**: Network interruptions, insufficient disk space. Provide user feedback, allow retries. Handle potential errors during file streaming/saving.
- **LLM Connection Errors**: If Ollama or another local inference server isn't running or accessible, display a clear error message in the AI Chat interface and guide the user on how to start the service.
- **Validation**: Implement robust form validation for login, signup, and note creation (e.g., email format, password strength, required fields) using React Hook Form.
- **Large File Handling**: Implement chunking for downloads and uploads if necessary. Consider browser limitations and provide clear instructions for large manual downloads.
- **Data Integrity**: Implement checks or checksums for downloaded files if possible.
Sample/Mock Data:
1. `content_categories`:
* `{ id: 1, name: 'Wikipedia', description: 'Offline copy of Wikipedia articles.', icon: 'wikipedia' }`
* `{ id: 2, name: 'Offline Maps', description: 'Downloadable map data for navigation.', icon: 'map' }`
* `{ id: 3, name: 'AI Models', description: 'Run powerful LLMs locally.', icon: 'brainCog' }`
* `{ id: 4, name: 'Education', description: 'Learning resources for all ages.', icon: 'graduationCap' }`
2. `content_items` (Examples for Wikipedia category):
* `{ id: 101, categoryId: 1, name: 'English Wikipedia - Full Dump (2024-01)', description: 'Snapshot of all English Wikipedia articles as of Jan 2024.', size_bytes: 150000000000, downloadUrl: '/downloads/en-wikipedia-2024-01.zip', version: '2024-01-01', isAvailableOffline: true, localPath: null }`
* `{ id: 102, categoryId: 1, name: 'English Wikipedia - Main Namespace Only (2024-01)', description: 'Only main article content, smaller size.', size_bytes: 50000000000, downloadUrl: '/downloads/en-wikipedia-main-2024-01.zip', version: '2024-01-01', isAvailableOffline: true, localPath: null }`
3. `content_items` (Example for Maps):
* `{ id: 201, categoryId: 2, name: 'Europe - OpenStreetMap (Vector Tiles)', description: 'Detailed vector map data for Europe.', size_bytes: 25000000000, downloadUrl: 'osm://europe-vector.mbtiles', version: 'latest', isAvailableOffline: true, localPath: null }`
4. `content_items` (Example for AI Models):
* `{ id: 301, categoryId: 3, name: 'Llama 3 8B Instruct', description: 'Meta AI Chat model - 8 Billion parameters.', size_bytes: 4700000000, downloadUrl: 'ollama://pull/llama3:8b', version: '1.0', isAvailableOffline: true, localPath: null }`
5. `user_content` (Example for a user who downloaded the smaller Wikipedia dump):
* `{ userId: 'uuid-of-user-1', contentItemId: 102, downloadProgress: 100, isDownloaded: true, addedAt: '2024-05-15T10:30:00Z', lastDownloadedAt: '2024-05-15T10:35:00Z', localPath: '/path/to/downloads/en-wikipedia-main-2024-01.zip' }`
6. `user_notes`:
* `{ id: 1, userId: 'uuid-of-user-1', title: 'Project Nomad Ideas', content: 'Need to implement better error handling for downloads...', createdAt: '2024-05-14T09:00:00Z', updatedAt: '2024-05-15T11:00:00Z' }`
* `{ id: 2, userId: 'uuid-of-user-1', title: 'Off-grid Setup Plan', content: 'Check generator fuel levels weekly...', createdAt: '2024-05-10T14:20:00Z', updatedAt: '2024-05-10T14:20:00Z' }`
7. Mock Chat Message:
* `{ role: 'user', content: 'Explain the concept of dark matter.', timestamp: '...' }`
* `{ role: 'assistant', content: 'Dark matter is a hypothetical form of matter thought to account for approximately 85% of the matter in the universe...', timestamp: '...' }`
8. Mock LLM Detection:
* `[{ name: 'llama3:8b', size: 4.7e9, last_modified: '...' }]` (Simulated response from Ollama API)
Turkish Translations (for UI elements):
- Login: Giriş Yap
- Sign Up: Kayıt Ol
- Email: E-posta
- Password: Şifre
- Dashboard: Pano
- Library: Kütüphane
- My Archive: Arşivim
- AI Chat: Yapay Zeka Sohbeti
- Notes: Notlar
- Settings: Ayarlar
- Download: İndir
- Downloading: İndiriliyor...
- Downloaded: İndirildi
- Search: Ara
- Create Note: Not Oluştur
- Save: Kaydet
- Cancel: İptal
- Add Content: İçerik Ekle
- Select Model: Model Seçin
- Type your message...: Mesajınızı yazın...
- Send: Gönder
- No content available: İçerik bulunamadı.
- No notes found: Not bulunamadı.
- Error: Hata
- Offline Mode: Çevrimdışı Mod
- Digital Independence: Dijital Bağımsızlık
- Knowledge Server: Bilgi Sunucusu
- Manage Your Data: Verilerinizi Yönetin