7.5 KiB
Project Context for AI Agents
This file contains critical rules and patterns that AI agents must follow when implementing code in this project. Focus on unobvious details that agents might otherwise miss.
Project overview
Grateful Journal — A minimal, private-first gratitude journaling web app. Three main pages (Write, History/calendar, Settings/profile) plus Google auth. No feeds or algorithms; privacy by design with client-side encryption; daily use, even one sentence.
User: Jeet
Technology stack & versions
| Layer | Technology | Notes |
|---|---|---|
| Frontend | React 19, TypeScript | Vite 7 build; port 8000 |
| Routing | react-router-dom 7 | Routes: /, /history, /settings, /login |
| Auth | Firebase 12 | Google sign-in only (no database) |
| Styling | Plain CSS | src/index.css (globals), src/App.css (components) |
| Backend | FastAPI 0.104 | Python; port 8001; modular routes |
| Database | MongoDB 6.x | Local instance; collections: users, entries, settings |
Critical implementation rules
Frontend
- Colour palette (Coolors): Use CSS variables from
src/index.css. Primary green#1be62c, background soft#f1eee1, surface#ffffff, accent light#cff2dc, accent bright#c3fd2f. Do not introduce new palette colours without reason. - Layout: Responsive for all screens. Breakpoints:
--bp-sm480px,--bp-md768px,--bp-lg1024px,--bp-xl1280px. On laptop (1024px+), page is single-screen 100vh — no vertical scroll; fonts and spacing scaled so content fits one viewport. - Touch targets: Minimum 44px (
--touch-min) on interactive elements for small screens. - Safe areas: Use
env(safe-area-inset-*)for padding where the app can sit under notches or system UI. Viewport meta includesviewport-fit=cover. - Structure: Main app layout: page container → header + main content + fixed
BottomNav. Content max-widthmin(680px, 100%)(or--content-max720px where appropriate).
Backend (when implemented)
- Framework: FastAPI. APIs in Python only.
- Modularity: Separate file per route. Each feature (users, entries) has its own router module.
- Database: MongoDB. Setup instructions below.
- Port: 8001 (backend); 8000 (frontend). CORS configured between them.
- Authentication: Relies on Firebase Google Auth token from frontend (passed in Authorization header).
Conventions
- Fonts: Inter for UI, Playfair Display for headings/editorial, Lora for body/entry text. Loaded via Google Fonts in
index.html. - Naming: CSS uses BEM-like class names (e.g.
.journal-card,.journal-prompt). Keep the same pattern for new components. - Build: Fixing the current TypeScript/ESLint build errors is deferred to a later step; do not assume a clean build when adding features.
File layout (reference)
src/ # Frontend
App.tsx, App.css # Root layout, routes, global page styles
index.css # Resets, :root vars, base typography
main.tsx
pages/ # HomePage, HistoryPage, SettingsPage, LoginPage
components/ # BottomNav, LoginCard, GoogleSignInButton, ProtectedRoute
contexts/ # AuthContext (Firebase Google Auth)
lib/
firebase.ts # Firebase auth config (Google sign-in only)
api.ts # API client for backend calls
backend/ # FastAPI backend (Port 8001)
main.py # FastAPI app, CORS, routes, lifespan
config.py # Settings, environment variables
db.py # MongoDB connection manager
models.py # Pydantic models (User, JournalEntry, Settings)
requirements.txt # Python dependencies
.env.example # Environment variables template
routers/
users.py # User registration, update, delete endpoints
entries.py # Entry CRUD, date filtering endpoints
Last updated: 2026-03-04
Recent Changes & Status
Port Configuration (Updated)
✅ Frontend port changed to 8000 (was 5173)
✅ Backend port remains 8001
✅ CORS configuration updated in FastAPI
✅ Vite config updated with server port 8000
Backend Setup (Completed)
✅ FastAPI backend initialized (port 8001)
✅ MongoDB connection configured (local instance)
✅ Pydantic models for User, JournalEntry, UserSettings
✅ Route structure: /api/users/* and /api/entries/*
✅ CORS enabled for frontend (localhost:8000)
✅ Firebase Google Auth kept (Firestore completely removed)
✅ MongoDB as single source of truth
API Ready
- User registration, profile updates, deletion
- Entry CRUD (create, read, update, delete)
- Entry filtering by date
- Pagination support
Zero-Knowledge Encryption Implementation (Completed)
✅ Crypto Module — Created src/lib/crypto.ts with complete zero-knowledge privacy
- Libsodium.js integrated for cryptography (XSalsa20-Poly1305)
- Key derivation from Firebase credentials using Argon2i KDF
- Device key generation and localStorage persistence
- Encrypted secret key storage in IndexedDB
- Entry encryption/decryption utilities
✅ Key Management Flow
- Login: KDF derives master key from
firebaseUID + firebaseIDToken + salt - Device Setup: Random device key generated, stored in localStorage
- Key Cache: Master key encrypted with device key → IndexedDB
- Memory: Master key kept in memory during session only
- Subsequent Login: Cached encrypted key recovered via device key
- New Device: Full KDF derivation, new device key generated
- Logout: Master key cleared from memory; device key persists for next session
✅ AuthContext Enhanced
- Added
secretKeystate (in-memory only) - Integrated encryption initialization on login
- Device key and IndexedDB cache management
- Automatic recovery of cached keys on same device
✅ Backend Models Updated — Zero-knowledge storage
JournalEntryCreate: title/content optional (null if encrypted)EncryptionMetadata: stores ciphertext, nonce, algorithm- Server stores encryption metadata only, never plaintext
- All entries encrypted with XSalsa20-Poly1305 (libsodium)
✅ API Routes — Encrypted entry flow
- POST
/api/entries/{userId}accepts encrypted entries - Validation ensures ciphertext and nonce present
- Entry retrieval returns full encryption metadata
- Update routes support re-encryption
- Server processes only encrypted data
✅ HomePage — Encrypted entry creation
- Entry and title combined:
title\n\n{entry} - Encrypted with master key before transmission
- Sends ciphertext, nonce, algorithm metadata to backend
- Success feedback confirms secure storage
✅ HistoryPage — Entry decryption & display
- Fetches encrypted entries from server
- Client-side decryption with master key
- Splits decrypted content: first line = title
- Graceful handling of decryption failures
- Displays original title or
[Encrypted]on error
Next Steps (Implementation)
🔄 Entry detail view with full decryption
🔄 Edit encrypted entries (re-encrypt on changes)
🔄 Search/filter encrypted entries (client-side only)
🔄 Export/backup encrypted entries with device key