Files
grateful-journal/.github/copilot-instructions.md
2026-03-09 10:54:07 +05:30

7.0 KiB

Grateful Journal — Project Instructions for Copilot

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-sm 480px, --bp-md 768px, --bp-lg 1024px, --bp-xl 1280px. 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 includes viewport-fit=cover.
  • Structure: Main app layout: page container → header + main content + fixed BottomNav. Content max-width min(680px, 100%) (or --content-max 720px where appropriate).

Backend

  • Framework: FastAPI. APIs in Python only.
  • Modularity: Separate file per route. Each feature (users, entries) has its own router module.
  • Database: MongoDB. Setup instructions in docs/MONGODB_SETUP.md.
  • 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

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 (src/lib/crypto.ts) — Complete zero-knowledge privacy

  • Libsodium.js (sodium-native compatible) for cryptography (XSalsa20-Poly1305)
  • KDF: deriveSecretKey(firebaseUID, firebaseIDToken, salt) using Argon2i
  • Device key: random 256-bit, persisted in localStorage
  • Master key: encrypted with device key → stored in IndexedDB
  • Session: Master key in memory only, cleared on logout

AuthContext Enhanced — Encryption initialization

  • secretKey state (Uint8Array, in-memory) added to AuthContext
  • Key derivation on login with Firebase credentials
  • Device key auto-generation and caching
  • IndexedDB encryption key recovery on returning visits
  • Graceful handling of key mismatch on cross-device login

HomePage — Encrypted entry creation

  • Combines title + entry: {title}\n\n{entry}
  • Encrypts with encryptEntry(content, secretKey)
  • Transmits only ciphertext + nonce to backend
  • Backend never receives plaintext

HistoryPage — Client-side decryption

  • Fetches encrypted entries with ciphertext + nonce
  • Decrypts with decryptEntry(ciphertext, nonce, secretKey)
  • Extracts title from first line of decrypted content
  • Graceful error display on decrypt failure

Backend Models — Zero-knowledge storage

  • EncryptionMetadata: stores ciphertext, nonce, algorithm only
  • JournalEntry: title/content optional (null if encrypted)
  • All encrypted entries use XSalsa20-Poly1305 algorithm
  • Server processes metadata only, never accesses plaintext

API Routes — Encrypted entry flow

  • POST /api/entries/{userId}: validates ciphertext + nonce required
  • GET /api/entries/{userId}: returns full encryption metadata
  • Entries automatically return decryption data to authorized clients
  • No decryption performed server-side

Next Steps (Implementation)

🔄 Entry detail view with full plaintext display
🔄 Edit encrypted entries (re-encrypt on update)
🔄 Search encrypted entries (client-side decryption)
🔄 Export/backup entries with device key encryption
🔄 Multi-device key sync (optional: manual backup codes)


Last updated: 2026-03-05