# CODEDUMP Internal dashboard for tracking AI tools and coding projects. Provides a high-level overview of what the team is building, what tools are available, and the completion status of active work — all in one place. --- ## Purpose CODEDUMP gives teams a single place to: - Track AI tools and coding projects with completion percentages - Attach markdown documentation and project files - Link to internal/external URLs and Google Drive sources - Highlight new tools available to the team - Manage access via admin accounts and 4-digit user PINs --- ## Tech Stack | Layer | Technology | |---|---| | Frontend | React 18 + TypeScript + Vite | | Styling | Tailwind CSS (dark mode, CSS variable theming) | | Backend | Node.js + Express + TypeScript | | Database | SQLite via `better-sqlite3` | | Auth | JWT (12h expiry) + bcryptjs (admin passwords) + HMAC-SHA256 (user PINs) | | File uploads | Multer (local disk storage) | | Markdown | `react-markdown` + `remark-gfm` | | Container | Docker (multi-stage build, single container) | --- ## Project Structure ``` codedump/ ├── client/ # React frontend │ ├── src/ │ │ ├── api/index.ts # Typed fetch wrappers (JWT injected automatically) │ │ ├── hooks/ │ │ │ ├── useAuth.ts # AuthContext — JWT storage, login/logout │ │ │ └── useSettings.ts # SettingsContext — branding, accent color │ │ ├── components/ │ │ │ ├── layout/ │ │ │ │ ├── Layout.tsx # App shell (sidebar + outlet) │ │ │ │ └── Sidebar.tsx # Nav — auth-aware, admin section, logout │ │ │ ├── projects/ │ │ │ │ ├── ProjectCard.tsx # Card with progress bar, links, tags │ │ │ │ └── ProjectForm.tsx # Create/edit form with color picker │ │ │ ├── tools/ │ │ │ │ └── ToolCard.tsx # Tool card with NEW badge │ │ │ └── ui/ │ │ │ ├── Badge.tsx # Status/role badges │ │ │ ├── Button.tsx # Primary/secondary/ghost/danger variants │ │ │ ├── Modal.tsx # Accessible overlay (Escape to close) │ │ │ └── ProgressBar.tsx # Accent-colored progress indicator │ │ ├── pages/ │ │ │ ├── Login.tsx # PIN pad + admin login │ │ │ ├── Dashboard.tsx # Stats, new tools spotlight, recent projects │ │ │ ├── Projects.tsx # Filterable project grid │ │ │ ├── ProjectDetail.tsx # Docs viewer, completion editor, links │ │ │ ├── Tools.tsx # Tool catalog with search + filter │ │ │ ├── Settings.tsx # Branding, logo upload, accent color │ │ │ └── AdminUsers.tsx # User management (admin only) │ │ └── types/index.ts # Shared TypeScript interfaces │ ├── index.html │ ├── vite.config.ts # Dev proxy: /api → localhost:3000 │ ├── tailwind.config.js │ └── tsconfig.json │ ├── server/ # Express backend │ ├── src/ │ │ ├── db/schema.ts # SQLite schema, migrations, admin bootstrap │ │ ├── lib/pinHash.ts # HMAC-SHA256 PIN hashing (deterministic lookup) │ │ ├── middleware/auth.ts # requireAuth / requireAdmin JWT guards │ │ └── routes/ │ │ ├── auth.ts # POST /pin, POST /login, GET /me │ │ ├── projects.ts # CRUD + tag/category support │ │ ├── tools.ts # CRUD │ │ ├── uploads.ts # POST (multer) + DELETE for documents │ │ ├── settings.ts # GET/PUT settings, POST logo upload │ │ └── users.ts # Admin-only user CRUD │ ├── tsconfig.json │ └── package.json │ ├── Dockerfile # Multi-stage: client build → server build → runtime ├── docker-compose.yml ├── .dockerignore ├── INSTALL.md # Unraid GUI install guide └── package.json # npm workspaces root ``` --- ## Database Schema **`users`** — Authentication accounts | Column | Type | Notes | |---|---|---| | `id` | TEXT PK | UUID | | `username` | TEXT UNIQUE | Display name | | `role` | TEXT | `admin` or `user` | | `pin_hash` | TEXT UNIQUE | HMAC-SHA256 of 4-digit PIN (users only) | | `password_hash` | TEXT | bcrypt hash (admins only) | | `created_at` | TEXT | ISO datetime | **`projects`** — Core project records | Column | Type | Notes | |---|---|---| | `id` | TEXT PK | UUID | | `name` | TEXT | Required | | `description` | TEXT | | | `category` | TEXT | e.g. AI/ML, DevOps, Research | | `status` | TEXT | `active`, `complete`, `archived` | | `completion` | INTEGER | 0–100 | | `external_url` | TEXT | Internal or external link | | `drive_url` | TEXT | Google Drive link | | `tags` | TEXT | JSON array of strings | | `accent_color` | TEXT | Hex color for card theming | | `is_new` | INTEGER | Boolean flag | | `created_at` / `updated_at` | TEXT | ISO datetime | **`documents`** — Files attached to projects | Column | Type | Notes | |---|---|---| | `id` | TEXT PK | UUID | | `project_id` | TEXT FK | Cascades on project delete | | `filename` | TEXT | UUID-named file on disk | | `original_name` | TEXT | Display name | | `mimetype` | TEXT | | | `created_at` | TEXT | | **`tools`** — Available AI/dev tools catalog | Column | Type | Notes | |---|---|---| | `id` | TEXT PK | UUID | | `name` | TEXT | | | `description` | TEXT | | | `category` | TEXT | | | `external_url` | TEXT | | | `is_new` | INTEGER | Boolean — shown in dashboard spotlight | | `added_at` | TEXT | | | `notes` | TEXT | Usage tips, caveats | **`settings`** — Key/value app configuration | Key | Default | Description | |---|---|---| | `app_title` | `CODEDUMP` | Shown in sidebar and login page | | `company_name` | `Your Company` | Shown under the app title | | `logo_url` | `null` | Uploaded or external URL | | `accent_color` | `#6366f1` | CSS variable applied globally | --- ## Auth Model Two account types with separate login flows: **Users** — Standard team members - Select no username; just enter their 4-digit PIN directly on the keypad - PINs are unique system-wide (enforced by DB unique constraint) - Stored as `HMAC-SHA256(JWT_SECRET, pin)` — deterministic, allowing single-query lookup - Can: create/edit/delete projects and tools, upload documents, view all content - Cannot: access Settings or User Management **Admins** — Elevated accounts - Log in with username + password via the "Admin Login" link on the login page - Passwords stored as bcrypt hashes (cost factor 10) - Can: everything users can do, plus Settings (branding/theme) and User Management - A bootstrap admin is created on first startup from `ADMIN_USERNAME` / `ADMIN_PASSWORD` env vars - The last admin account cannot be deleted **JWT** — 12-hour tokens stored in `localStorage`. Expiry is checked client-side on load; the server re-validates on every request. A 401 response from the server clears the token and redirects to `/login`. --- ## Environment Variables | Variable | Default | Description | |---|---|---| | `PORT` | `3000` | Server listen port | | `DATA_DIR` | `./data` | SQLite DB + uploads root on disk | | `MAX_UPLOAD_MB` | `50` | Max file upload size | | `ADMIN_USERNAME` | `admin` | Bootstrap admin username (first-run only) | | `ADMIN_PASSWORD` | `codedump2024` | Bootstrap admin password (first-run only) — change this | | `JWT_SECRET` | *(insecure default)* | Token signing secret — set to a 32+ char random string | Generate a strong `JWT_SECRET`: ```bash openssl rand -hex 32 ``` --- ## Running Locally ```bash # Install all workspace dependencies npm install # Start both server (port 3000) and client (port 5173) with hot reload npm run dev ``` Visit `http://localhost:5173`. The Vite dev server proxies `/api/*` to `localhost:3000`. Default admin credentials on first run: `admin` / `codedump2024` --- ## Building for Production ```bash npm run build # Client builds to client/dist/ # Server builds to server/dist/ # Server serves client/dist/ as static files npm start ``` --- ## Docker ```bash # Build image docker build -t codedump:latest . # Run with docker-compose (recommended) docker-compose up -d ``` Data persists in `./data/` (local) or `/mnt/user/appdata/codedump/` (Unraid). See [INSTALL.md](./INSTALL.md) for the full Unraid GUI setup guide including port mapping, volume paths, and all environment variable fields. --- ## File Upload Details - Accepted types: `.md`, `.txt`, `.pdf`, `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg` - Files are stored in `DATA_DIR/uploads/` with UUID filenames - Served publicly at `/api/uploads/:filename` via `express.static` (no auth required — needed for `` tags and the markdown doc viewer) - Upload and delete operations require authentication - Logo uploads follow the same path; the URL is saved in settings and served the same way --- ## Deployment Notes - SQLite with WAL mode — suitable for a single-server internal tool; no separate database service needed - All persistent state (DB + uploads) lives under `DATA_DIR` — back up that directory - The bootstrap admin only runs if no admin account exists in the DB; changing env vars after first run does not change existing credentials - `JWT_SECRET` must stay consistent across restarts — changing it invalidates all active sessions