Social App - Technical Documentation
This document covers the complete Spark social app - built with Node.js,
Supabase Realtime, and a plain-HTML frontend. Re-run node generate_docs.js to update.
| Layer | Technology | Notes |
|---|---|---|
| Backend | Node.js + Express 4 | REST API + static file serving |
| Real-time | Supabase Realtime | Instant messaging via DB subscriptions |
| Database | Supabase (PostgreSQL) | Cloud Postgres + Realtime + Storage |
| Auth | JWT + bcryptjs | 7-day tokens stored in localStorage |
| File Uploads | Multer | Profile photos (5 MB), chat files (10 MB) |
| Frontend | HTML + CSS + Vanilla JS | No framework - zero build step |
Open a terminal in the project folder and run:
file:// will not work.
file:// instead of http://localhost:3000nav.js ping every 30s (3min when tab hidden), global.js ping every 45s + activity-triggeredbeforeunload sends offline signal via fetch+keepalive (not broken sendBeacon)/api/logout sets lastSeen to 6 min ago so the 5-min online window correctly marks offlinelastSeen is within last 5 minutes or heartbeat is active/api/logs endpoint to read the log fileDELETE /api/logs to clear the logAll routes are relative to http://localhost:3000. Auth = Bearer token required. Admin = admin JWT required.
| Method | Route | Auth? | Description |
|---|---|---|---|
| POST | /api/register | No | Create a new account |
| POST | /api/login | No | Login - returns JWT + userId |
| POST | /api/forgot-password | No | Verify email exists, return reset token (15 min TTL) |
| POST | /api/reset-password | No | Set new password using reset token |
| PUT | /api/change-password | Yes | Change password (current password required) |
| PUT | /api/profile | Yes | Update profile fields + optional photo upload |
| GET | /api/profile/me | Yes | Get own profile data |
| GET | /api/members | Yes | List all members with complete profiles |
| GET | /api/messages/:otherId | Yes | Message history with another user |
| GET | /api/conversations | Yes | Conversation list with last-message preview |
| POST | /api/chat/upload | Yes | Upload a file for use in chat |
| POST | /api/admin/login | No | Admin login - returns admin JWT |
| GET | /api/admin/users | Admin | All users (passwords excluded) |
| GET | /api/admin/messages | Admin | Full message log with sender/receiver names |
| GET | /api/admin/stats | Admin | Aggregate stats (users, messages, etc.) |
| DELETE | /api/admin/users/:id | Admin | Delete user and all their messages |
| DELETE | /api/admin/messages/:id | Admin | Delete a single message |
| GET | /api/logs | Admin | Read the server error log file |
| DELETE | /api/logs | Admin | Clear the error log file |
Real-time messaging uses Supabase Realtime (PostgreSQL logical replication). No persistent WebSocket connections needed.
The following events are handled via REST API endpoints and Supabase Realtime subscriptions:
| Event | Direction | Payload Fields | Description |
|---|---|---|---|
| send_message | Client → Server | receiverId, content, type, fileName | Send message; server saves + routes it |
| new_message | Server → Client | id, sender_id, receiver_id, content, type, sender_name | Delivered to sender and receiver |
| edit_message | Client → Server | messageId, content | Edit own message |
| message_edited | Server → Client | messageId, content | Both parties update the message text |
| delete_message | Client → Server | messageId | Delete own message |
| message_deleted | Server → Client | messageId | Both parties remove the message |
| user_status | Server → All | userId, online, lastSeen | Emitted on every connect / disconnect |
| Path | Purpose |
|---|---|
| Code App/ | -- project root |
| server.js | Express API + Logger (all backend logic) |
| logger.js | Error logging module - writes timestamped entries to error.log |
| error.log | Auto-generated log file (created at runtime) |
| database.js | Supabase client setup - exports @supabase/supabase-js instance |
| db.json | Legacy JSON database (fully migrated to Supabase โ kept for reference only) |
| generate_docs.js | Script to regenerate this documentation |
| package.json | npm dependency manifest |
| public/ | -- static frontend files served by Express |
| index.html | Login, Register, Forgot Password |
| profile.html | Profile editing + Change Password |
| browse.html | Discover member grid |
| chat.html | Real-time chat UI |
| admin.html | Admin dashboard |
| logs.html | Error log viewer (admin-only, auto-refresh) |
| documentation.html | This page - technical documentation |
| nav.js | Shared navbar chip (name + avatar) |
| global.js | Presence heartbeat, Supabase Realtime notifications, tab-title flash |
| style.css | All styles for all pages |
| uploads/ | Profile photos + chat files (exclude from git) |
| Setting | Value | Where to change |
|---|---|---|
| Server port | 3000 | server.js - const PORT |
| JWT secret | social-app-secret-key-change-in-prod | server.js - const JWT_SECRET |
| JWT expiry | 7 days | server.js - jwt.sign expiresIn |
| Admin password | admin1234 | server.js - const ADMIN_PASSWORD |
| Profile photo limit | 5 MB | server.js - upload multer config |
| Chat file limit | 10 MB | server.js - uploadChat multer config |
| Database | Supabase PostgreSQL | database.js - Supabase client config |
| Supabase URL | http://127.0.0.1:54321 | Local Supabase API endpoint |
| Supabase Studio | http://127.0.0.1:54323 | Web UI for database management |
JWT_SECRET and ADMIN_PASSWORD before deploying to any public server.
| Field | Type | Description |
|---|---|---|
| id | number | Auto-incrementing primary key |
| username | string | Unique; chosen at registration |
| string | Unique email address | |
| password | string | bcrypt hash - never returned by any API route |
| name | string | null | Display name set on Profile page |
| age | number | null | Age set on Profile page |
| gender | string | null | Gender set on Profile page |
| bio | string | null | Short bio, max 300 characters |
| photo | string | null | Server path, e.g. /uploads/photo.jpg |
| created_at | ISO string | Registration timestamp |
| lastSeen | ISO string | Updated via heartbeat every 30-45s + on tab close/logout |
| Field | Type | Description |
|---|---|---|
| id | number | Auto-incrementing primary key |
| sender_id | number | ID of the sending user |
| receiver_id | number | ID of the recipient |
| content | string | Message text or /uploads/... path for files |
| type | "text" | "image" | "file" | Defaults to "text" |
| fileName | string | null | Original filename for attachments |
| edited | boolean | true if the sender edited this message |
| created_at | ISO string | Send timestamp (server time) |
Reasonix is a DeepSeek-native coding agent that runs in the terminal. It's designed around DeepSeek's API directly - cache-first loop, flash-first cost control, and automatic tool-call repair.
node --versioncmd, press Entercd C:\Users\andre\Documents\Deepseek\Code Appnpx reasonix@latest code (first run prompts for your API key)C:\Users\andre\.reasonix\config.jsonnotepad C:\Users\andre\.reasonix\config.json| Model | Cost / Turn | Turns for $4.98 | Best For |
|---|---|---|---|
| Flash (default) | ~$0.0006 | ~8,000 | Quick edits, exploration |
Pro (/preset max) | ~$0.01–0.03 | ~200 | Complex reasoning tasks |
| Shortcut / Command | Action |
|---|---|
Ctrl + L | Clear terminal |
Ctrl + C | Exit Reasonix |
Shift + Tab | Auto-apply all suggestions |
y / n | Accept or discard a change |
/preset max | Switch to DeepSeek Pro model |
/stats | Show token/cost statistics |
/cost | Show running cost |
/clear | Clear conversation context |
/help | Show all commands |
/preset max when you need deep reasoning. In v0.28.0, the model/preset fields in config.json are ignored - you must run /preset max manually each session.
Every session, run these four lines:
Spark has migrated from lowdb (JSON file) to Supabase (PostgreSQL) for better scalability and Vercel deployment readiness.
This spins up PostgreSQL + Supabase Studio + all supporting services locally via Docker.
| Service | URL |
|---|---|
| Supabase Studio (web UI) | http://127.0.0.1:54323 |
| API Endpoint | http://127.0.0.1:54321 |
| Database URL | postgresql://postgres:postgres@127.0.0.1:54322/postgres |
| Mailpit (test emails) | http://127.0.0.1:54324 |
Spark uses a cloud Supabase project (CWD) at https://hpezaqvtufrvvczyixwc.supabase.co for production data. The local Supabase instance is used for development and testing.
Access your Supabase PostgreSQL database two ways:
| Setting | Value |
|---|---|
| Host | aws-0-ap-southeast-1.pooler.supabase.com |
| Port | 6543 |
| Database | postgres |
| Username | postgres.hpezaqvtufrvvczyixwc |
| Password | Database password set during project creation |