Skip to content

divprasad/get-jackdd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

387 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Strength Log πŸ‹οΈ

Strength Log is a mobile-first, local-first workout tracker built on Next.js. It's designed to be instantaneously responsive by writing purely to local IndexedDB (Dexie) and queueing asynchronous syncs to a Prisma/SQLite backend whenever a network is available.

Important

πŸ€– ARE YOU AN AI AGENT? Before making any code changes or tool calls, you MUST read AGENTS.md. It contains strict surgical edit rules, local-first architecture bounds, and the core files you are forbidden from modifying without explicit permission.


πŸ—οΈ Architecture Quick-Start

Strength Log employs a strict Local-First Sync Architecture. The app remains incredibly fast because the UI never waits on a network request to load or save data.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  React UI  (Next.js App Router + Tailwind)      β”‚
β”‚  └─ useLiveQuery() reads from Dexie reactively  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Repository layer  (src/lib/*-repository.ts)    β”‚
β”‚  └─ workout-, exercise-, sync-, utils modules   β”‚
β”‚  └─ All writes go to Dexie β†’ enqueueSync()      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Sync Engine  (src/lib/syncEngine.ts)           β”‚
β”‚  └─ Drains syncQueue β†’ POST /api/workouts       β”‚
β”‚  └─ Auto-triggers on `online` event             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  API Routes  (src/app/api/**/route.ts)          β”‚
β”‚  └─ Prisma $transaction upserts to SQLite       β”‚
β”‚  └─ Auto-backup on every workout sync           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  SQLite  (prisma/dev.db)                        β”‚
β”‚  └─ Final persistent ledger                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Data Rule: All UI components read and write to IndexedDB. Components never call fetch() directly for mutations.


πŸš€ Developer Workflows

This app supports two primary development paths depending on whether you are adjusting UI components or testing the Progressive Web App (PWA) installation flow.

Path A: Standard Local Development (Node)

Use this path for general feature development, UI changes, and testing backend logic.

  1. First, set up your local environment variables:
    cp .env.example .env
    Fill in the required variables:
    Variable Required Notes
    DATABASE_URL βœ… file:./prisma/dev.db for local dev
    JWT_SECRET βœ… openssl rand -hex 32
    RP_ID βœ… for Passkeys localhost for local dev
    RP_ORIGIN βœ… for Passkeys http://localhost:3000 for local dev
    SESSION_TTL_DAYS optional defaults to 7
  2. Install dependencies:
    npm ci
  3. Start the development server:
    npm run dev
    This now runs a local DB bootstrap first: Prisma migrations + conditional seeding for a fresh or partially repaired prisma/dev.db.
  4. Run automated assurance checks:
    npm run check

Path B: Production & PWA Testing (Docker)

Use this path if you need to test the service worker, offline caching, or natively installing the app to a mobile device.

  1. Boot the entire stack (Next.js + Persistent SQLite Volume):
    docker compose up --build -d

(Tip: To test PWA installation on a local mobile device, navigate to brave://flags or chrome://flags on your phone, and explicitly allow http://<your-local-ip>:3400 under "Insecure origins treated as secure")


⚠️ File Boundaries & Danger Zones

To protect the integrity of the off-line syncing mechanisms, explicit boundaries exist within the codebase.


Docker deployment

The app runs as a single Docker container (strength-log). HTTPS is provided by Tailscale Funnel running on the host β€” no Caddy container is needed. PWA installation requires HTTPS, which Tailscale provides via its globally-trusted certificate.

Files involved in Docker deployment

File Purpose Per-deployment edit?
Dockerfile Multi-stage build: deps β†’ build β†’ lean runner (~180 MB) No β€” universal
docker-compose.yml App container + volumes; binds to 127.0.0.1:3000 No β€” universal
docker-entrypoint.sh Validates JWT_SECRET, runs migrations, seeds on first boot No β€” universal
next.config.ts Next.js config with security headers No
.env Required secrets β€” copy from .env.example Yes β€” set before first boot
db/strength_diary.db Live SQLite database (created on first boot, or migrated) Optional β€” bring an existing DB
db/backups/ Append-only numbered backups (auto-created) No
logs/app.log Entrypoint and runtime logging No

Pre-flight: create your .env

The container will refuse to start if JWT_SECRET is missing or is the placeholder value.

cp .env.example .env
# Then edit .env and fill in:

# JWT_SECRET β€” required. Generate with:
openssl rand -hex 32

# RP_ID / RP_ORIGIN β€” required for Passkey (WebAuthn) auth.
# Set to your Tailscale domain:
# RP_ID=your-machine.ts.net
# RP_ORIGIN=https://your-machine.ts.net

Option A: Build and run on the same machine

# 1. Ensure .env is populated (see above)
# 2. Build and start
docker compose up --build -d
# 3. Verify
docker ps                    # strength-log should be Up
docker logs strength-log     # should show version banner and "Migrations applied"

Option B: Cross-compile for a weaker machine (Raspberry Pi, NAS, etc.)

# ========= On the Mac =========

# 1. Build for the target architecture (arm64 for Pi, amd64 for x86 NAS)
docker buildx build --platform linux/arm64 -t strength-log:latest --output type=docker,dest=strength-log.tar .

# 2. Transfer the image + config to the target machine
scp strength-log.tar docker-compose.yml .env user@<TARGET_IP>:~/strength-app/

# ========= On the target machine =========

# 3. Load the pre-built image
docker load -i strength-log.tar

# 4. Edit docker-compose.yml β€” use the image instead of building
#    Change:  build: .
#    To:      image: strength-log:latest
#             pull_policy: never

# 5. Start
docker compose up -d

Updating the app: Repeat steps 1–3. The new image replaces the old one. Run docker compose down && docker compose up -d on the target.

Exposing via Tailscale Funnel (HTTPS)

The container listens on 127.0.0.1:3000. Tailscale Funnel proxies HTTPS traffic from your Tailscale domain to localhost:3000.

# On the host machine (not inside Docker):
tailscale funnel 3000

The app is then reachable at https://<your-machine>.ts.net. Tailscale provides a globally trusted TLS cert β€” no manual certificate installation needed on client devices.

Tip: Set RP_ID=<your-machine>.ts.net and RP_ORIGIN=https://<your-machine>.ts.net in .env so WebAuthn Passkeys work correctly on the public domain.

Migrating your database to a new machine

  1. Copy your latest backup (or live DB) from the old machine:
    scp old-machine:~/strength-app/db/strength_diary.db ./db/strength_diary.db
  2. Place it in the db/ folder on the new machine before running docker compose up.
  3. Do NOT copy -journal, -wal, or -shm files β€” these belong to the old machine's running SQLite instance and will cause "Unable to open database" errors.

Troubleshooting

Symptom Cause Fix
ERROR: JWT_SECRET is not set at container start Missing or placeholder secret Set a real JWT_SECRET in .env and restart
Error code 14: Unable to open the database file Wrong DATABASE_URL or permission issue Ensure DATABASE_URL=file:/app/prisma/strength_diary.db. Run sudo chown -R 1001:1001 db/ on host.
App loads but shows no data Browser IndexedDB is empty on first visit Go to Settings β†’ "Pull from Server" to force bootstrap, or hard-refresh the page.
Passkey registration fails RP_ID / RP_ORIGIN mismatch Must exactly match the domain in the browser address bar.
"Failed to clear server data" API can't write to the database Check docker logs strength-log for Prisma errors. Usually a permissions issue (see above).
Stale -journal file from a different DB Copied a journal file alongside the DB from another machine Delete db/strength_diary.db-journal and restart.

  • πŸ”΄ DANGER ZONE (Do not touch without Extreme Care):

    • src/lib/syncEngine.ts - The heart of the network queue.
    • src/lib/workout-repository.ts, src/lib/exercise-repository.ts, src/lib/sync-repository.ts - The decomposed repository layer. All domain mutations flow through here.
    • src/lib/db.ts - Schema migrations and Dexie config. Any modifications here risk corrupting user data or breaking the sync loop. See AGENTS.md for "Surgical Edit Rules".
  • 🟒 SAFE ZONES:

    • src/components/** - UI views and components.
    • src/app/** - Next.js routes and layouts.

🀝 Contribution Guidelines

To maintain synchronization stability and code legibility, please adhere to the following when submitting PRs:

  • Use Conventional Commits: e.g., feat: offline pin auth, fix: zombie row bug in sync
  • Agent Hand-off: If an AI agent assisted with your contribution, ensure they have updated AGENTS.md or /docs with any new context before terminating the session.
  • Troubleshooting IndexedDB: If you enter a broken local state during development, IndexedDB might be corrupt. Go to Chrome Dev Tools -> Application -> Storage -> Clear site data and reload. Do not attempt to forcefully delete migrations unless you know what you are doing.

πŸ“š Documentation Hub

Before undertaking major refactors, consult the static reference files located in /docs. You can open these natively in any browser:

  • docs/data_model.html - Visual Prisma + Dexie schema map (all models and relationships).
  • docs/api_schema.html - API route inventory (endpoints, auth requirements, payloads).
  • docs/sync_architecture.html - Sync engine deep dive: offline strategy, queue lifecycle, error handling.
  • docs/meta_processes.html - Deep dive into resolving local-first sync conflicts.
  • docs/folder_structure.html - Comprehensive codebase map.
  • docs/tech_stack.html - Reasons behind tooling choices (Dexie, Serwist, Prisma).
  • AGENTS.md - Operating guide, current project status, and strict rules for AI Agents.

🌟 Features & Current Status

The application is functionally complete covering the full workout loop, with automated E2E tests, robust data integrity tooling, and an integrated global command palette.

  • Unit tests use Vitest for pure src/lib/** logic.

  • Fast CI runs lint, typecheck, test:unit, and build on every branch push and on pull requests into main.

  • Playwright E2E (npm run test:e2e) covers the full workout lifecycle and JSON export/import. Requires a running dev server or auto-starts via Playwright webServer config.

  • Progressive Web App (PWA): Installs natively. Boots instantly. Offline-first routing via Serwist.

  • Internet-facing via Tailscale Funnel: Exposed publicly with a globally-trusted HTTPS cert β€” no self-signed CA needed.

  • WebAuthn Passkey Authentication: Face ID / fingerprint login as primary auth. Legacy bcrypt PIN retained as fallback. Brute-force rate limiting (5 tries / 15-min window).

  • Invite-code Registration: Admins generate single-use 8-char codes (48h TTL). New users self-register at /register β€” no open sign-up.

  • Cardio & Non-gym Tracking: time_only tracking mode for treadmill, elliptical, yoga, etc. Non-gym workouts are automatically excluded from the gym session cost counter.

  • Security Hardening: HTTP security headers (HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy), JWT_SECRET validated at container start.

  • Automated DB Backups: Every server sync creates a rolling numbered backup in prisma/backups/.

  • Zero-Latency UI: All CRUD operations happen logically at 0ms latency thanks to Dexie and background syncing.

About

a web app to log strength workouts and track progression

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors