12 KiB
Insole Production Time Tracker — Rebuild Roadmap & Project Overview
- Created: 2026-06-17
- Status: Approved — living project doc; Phases 0–2 implemented (
docs/plans/phase-2-accounts-roles.md) - Type: Greenfield rebuild of an inherited app
- Tracked in git under
docs/(the project's documentation source of truth).
2026-06-17 — Legacy code removed. The inherited Create/Anything export (
apps/mobile,apps/web,publisher/) was deleted in a full cleanup. The repo is now a single-service backend (apps/api) pluspackages/shared. Reference for the old code is preserved indocs/reference/and in git history. The sections below describe the codebase as inherited and the rebuild plan; treat references to the legacy apps as historical.
1. Context
The codebase was inherited as an export from the Create / Anything AI platform — a working time-tracking app for insole (orthotic) production, originally built by a friend through a chat-driven workflow. It arrived with no history, no documentation, and no clarity on what was complete or where the backend/data lived.
Reverse-engineering established:
- It is a two-app monorepo:
apps/mobile(Expo/React Native) +apps/web(Next.js 16 backend on Neon Postgres). Pluspublisher/(deploy tooling). - It is heavily coupled to the Create platform: "do-not-edit" platform files, patched dependencies, a web-sandbox iframe layer, and ~80 dependencies for what is functionally a stopwatch.
- Auth is
better-auth(email+password, argon2 hashes, bearer tokens for mobile, cookies for web), but the core flow does not actually require login. - The data and accounts are not ours. Users, password hashes, and all task/time
data live in the platform's managed Neon Postgres, bound to the friend's Create
account/organization. This repo contains only the code and an
ANYTHING_PROJECT_TOKEN— no database credentials. Nothing runs locally and no database is reachable from this code.
Work already done this session (committed):
- Git repository initialised; baseline + doc corrections committed.
- Found and fixed
/api/logs— it was both git-ignored (an over-broadlogsrule) and broken at runtime (missing itsimport sql). That route is History + Stop&Save. - Wrote a reverse-engineered
schema.sql(no migration shipped). - Installed dependencies (~1.7 GiB) and confirmed Docker is available.
The existing code is treated as a working reference / seed, not the foundation.
2. Vision
A multi-user, backend-driven shop-floor time-tracking system. The phone is one of several clients, not the source of truth.
A worker, on their own phone with their own account, logs in → goes to a workbench → scans it (QR) or selects manually → picks the activity → times the work → ends it → it is saved → repeats. Because the backend is the source of truth:
- An active session lives server-side, so if the phone dies the worker can end or log the work from a computer instead.
- There is a manual-entry fallback wherever something can fail.
- An admin panel shows live who-is-working-on-what, generates reports, and manages users and activities.
Goals: it must genuinely work in the workshop (reliability, no data loss) and serve as a learning vehicle the owner extends himself.
3. Decisions (resolved during brainstorming)
| # | Decision | Choice |
|---|---|---|
| 1 | Purpose | Real workshop tool and a learning vehicle |
| 2 | Platform relationship | Clean break from Create/Anything |
| 3 | Hosting | Dockerized stack; runs locally now, portable to any cloud later |
| 4 | Build strategy | Greenfield rebuild, porting only the good parts |
| 5 | Backend topology | Dedicated backend service (Option A): single owner of auth + DB; UIs are interchangeable clients |
| 6 | Auth | better-auth (don't hand-roll security for real use) |
| 7 | Database | SQLite (small userbase; one file, easy backup/Docker) |
| 8 | Language | TypeScript everywhere so types flow end-to-end |
4. Architecture
┌─────────────┐ ┌─────────────┐
│ Mobile app │ │ Admin web │ clients — UI only, no DB access
│ (Expo/RN) │ │ (React SPA) │
└──────┬──────┘ └──────┬──────┘
│ HTTP (Bearer) │ HTTP (cookie/Bearer)
└─────────┬─────────┘
▼
┌──────────────────┐
│ Backend service │ the ONLY thing that touches auth + DB
│ better-auth + │
│ business logic │
└────────┬─────────┘
▼
┌─────────┐
│ SQLite │ single file on a Docker volume
└─────────┘
Auth flow
- Mobile — native email+password screen →
POST /api/auth/sign-in/email→ backend returns a bearer token → stored in Expo SecureStore → sent asAuthorization: Bearer <token>on every request. (Drops the current app's embedded login WebView.) - Admin — standard better-auth session cookies.
- Backend — mounts better-auth, owns all DB access, enforces roles.
5. Tech stack (recommended picks, approved)
| Layer | Pick | Notable alternative |
|---|---|---|
| Backend framework | Hono | Fastify |
| Auth | better-auth | — |
| DB access + migrations | Drizzle ORM | Kysely / Prisma |
| Database | SQLite | libsql/Turso (if cloud later) |
| Admin UI | Vite + React (SPA) | Next.js (if SSR wanted) |
| Mobile | Expo / React Native | — |
| Shared contracts | packages/shared (TS types + zod) |
— |
6. Monorepo shape
apps/
mobile/ Expo worker app (client)
admin/ Vite + React panel (client)
api/ Hono + better-auth + Drizzle + SQLite (backend service)
packages/
shared/ TS types + zod schemas (API contracts)
docker-compose.yml + Dockerfiles
7. Data model
Server-authoritative; an open session (end_time null) is "active work".
- users — id, email, name, password hash (better-auth managed), role (
worker|admin) - workbenches — id, name,
qr_code(seeded / hardcoded for now) - activities — id, name,
insole_types[](subset ofKurk|Berk|3D) - sessions — id,
user_id,activity_id,workbench_id,insole_type,pair_count,start_time,end_time(null = running),status(active|completed|discarded),source(app|manual),notes,created_at
(better-auth also creates its own session/account/verification tables; those are
distinct from the domain sessions table above — naming to be disambiguated in Phase 0,
e.g. work_sessions.)
8. Port vs. leave behind
Port (the good parts): the data model, the API route logic, the screen flows/UX, the CSV export logic, the Dutch UI strings, and the lessons captured in the current code's comments (Android font/freeze fixes, SecureStore quirks).
Leave behind: the __create plumbing, the web-sandbox iframe layer, analytics /
Sentry / anything-menu, the patched dependencies, and the ~60 unused libraries (ads, IAP,
maps, 3D, audio, calendar, contacts, sensors, …).
9. Phased roadmap
Each phase keeps the system working and is its own spec → plan → build cycle.
- Phase 0 — Foundation. Greenfield monorepo; dockerized Hono backend with better-auth
- Drizzle + SQLite;
docker compose upbrings it up; health check + one auth round-trip proven end-to-end. Done when: a client can sign in against the containerised backend and the token authorises a protected call.
- Drizzle + SQLite;
- Phase 1 — Worker timing. Activities + server-authoritative work-sessions (open/close) + history + CSV export in the backend; mobile app rebuilt to use it. Done when: a worker can pick an activity, start/stop a server-side session, and see history; CSV exports.
- Phase 2 — Accounts & roles. ✅ Implemented. Worker/admin roles (better-auth
adminplugin), admin-creates-users, per-user data scoping. Workers are scoped to their own sessions; an admin account exists; admin manages users via/api/auth/admin/*and sees all sessions via/api/admin/sessions. Public sign-up is closed; activity writes are admin-only. Done when: workers see only their own sessions; an admin account exists. - Phase 3 — Admin panel. The React admin app: live active-work view, reports/export, user management, manual entry/edit (the fallback). Done when: an admin can see who's working now, manage users, and hand-correct a session.
- Phase 4 — Workbench scanning. QR at the bench → select workbench/activity, with manual selection fallback. Done when: scanning a bench QR pre-fills the session.
- Phase 5 — Polish & deploy. Reporting niceties, dependency slimming, push the container to a chosen cloud host.
10. Open questions & assumptions (confirm as we go)
- Scanning = QR codes on benches, read by the phone camera (no special hardware), always with manual fallback. (Assumption.)
- Start fresh, no data migration. Assumes no live workshop data/users worth preserving in the friend's platform instance. If there are, they must be exported from the friend's Create account — unreachable from this repo.
- Workbench↔activity mapping is hardcoded/seeded for now; real mapping TBD with the friend.
- Deployment host is deferred (Phase 5); the dockerized stack keeps options open.
- Domain term: "insole" / orthotic; Dutch UI (
Type zool,handeling,aantal zolen, etc.).
11. Risks
- Greenfield is more work than evolving in place — mitigated by porting proven logic and keeping the old code as a running reference.
- SQLite is single-writer / single-instance — fine at this scale; swap to Postgres/libsql is a config change via Drizzle/better-auth if ever needed.
- Offline on the shop floor — the friend hit connectivity issues. Backend-as-source- of-truth assumes reachable network; true offline-first is explicitly out of scope for now (revisit if it bites).
12. Next step
Brainstorm Phase 0 in detail, then hand it to the writing-plans skill for an implementation plan. No code before that plan exists.