50 Playwright E2E tests across 13 spec files covering all routes and user flows (items CRUD, check-out/in, locations, labels, scanning, search/filter). Uses vitest as runner with playwright-core for browser automation (bun-compatible alternative to @playwright/test). Includes Gherkin .feature files as living documentation, test support infrastructure (IDB seeding, item factories, assertion helpers, layout measurement), and HANDOFF.md covering project state, deployment, and open design decisions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
139 lines
7.1 KiB
Markdown
139 lines
7.1 KiB
Markdown
# SolidHaus — Project Handoff
|
|
|
|
## What This Is
|
|
|
|
Local-first household inventory app. Scan barcodes, track where things are, check items in/out, generate QR label sheets. Runs as a web app (SPA) or native mobile app via Capacitor.
|
|
|
|
## Tech Stack
|
|
|
|
- **Framework**: SvelteKit 2, Svelte 5 (runes), TypeScript
|
|
- **Styling**: Tailwind CSS 4 (dark slate theme)
|
|
- **Data**: IndexedDB via `idb` (local-first, no server required)
|
|
- **Runtime**: Bun (no Node.js — bun is the only runtime used)
|
|
- **Build**: Vite 7, `@sveltejs/adapter-static` (SPA mode, outputs to `build/`)
|
|
- **Testing**: Vitest 4 (unit) + Vitest + playwright-core (E2E)
|
|
- **Future**: Automerge (multi-device sync), Solid Protocol (linked data), Capacitor (native mobile)
|
|
|
|
## Current State (Feb 2026)
|
|
|
|
### What works
|
|
- All routes functional: dashboard, items list, item detail, new item, scan, locations, labels, settings
|
|
- Item CRUD with full field set (name, category, type, barcode, location, custody state, quantity tracking)
|
|
- Check-out / check-in flow with reasons (in-use, lent, in-transit, in-repair, temporary)
|
|
- Location tree with expand/collapse, item counts per location
|
|
- QR label sheet PDF generation (A4, 5x10 grid) with batch pre-generation
|
|
- Barcode scanning (Capacitor ML Kit on native, Barcode Detection API on web)
|
|
- Search and filter (by name, category, type, custody state)
|
|
- Confidence decay (confirmed → likely → assumed → unknown based on last sighting age)
|
|
- Default German house locations seeded on first run
|
|
|
|
### Test coverage
|
|
- **174 unit tests** — `bun run test`
|
|
- **50 E2E tests** across 13 spec files — `bun run test:e2e`
|
|
- **Build** — `bun run build` (outputs static SPA to `build/`)
|
|
|
|
### What's not done yet
|
|
- **Capacitor native platforms**: Config exists, deps installed, but `android/` and `ios/` dirs not created. Run `npx cap add android && npx cap sync` when ready.
|
|
- **Automerge sync**: Deps installed, not wired up. Intended for multi-device sync without a central server.
|
|
- **Solid Protocol**: Deps installed, not wired up. Intended for linked data / decentralized identity.
|
|
- **Photo support**: Schema exists (`photos` IDB store), no UI for capture/display yet.
|
|
- **Sighting history**: Schema exists (`sightings` IDB store), recorded on check-in/out but no history view UI.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
src/
|
|
routes/
|
|
+layout.svelte # App shell: loading state, bottom nav, inventory init
|
|
+page.svelte # Dashboard: stats, checked-out items, low stock, recent
|
|
items/
|
|
+page.svelte # Item list with search/filter/sort
|
|
new/+page.svelte # New item form
|
|
[id]/+page.svelte # Item detail with check-out/in, edit, delete
|
|
scan/+page.svelte # Barcode scanner
|
|
locations/+page.svelte # Location tree + items at location
|
|
labels/+page.svelte # Batch ID generation + PDF label sheets
|
|
settings/+page.svelte # DB stats, about
|
|
lib/
|
|
components/ # Svelte components (ItemCard, ItemForm, LocationTree, etc.)
|
|
data/ # IndexedDB CRUD (db.ts, items.ts, locations.ts, sightings.ts, labels.ts)
|
|
stores/ # Svelte 5 rune stores (inventory.svelte.ts)
|
|
scanning/ # Barcode detector + ID parser
|
|
printing/ # Label sheet PDF generation
|
|
utils/ # ID generation, confidence decay
|
|
types.ts # All TypeScript types
|
|
|
|
e2e/
|
|
features/ # Gherkin .feature files (living documentation, not executable)
|
|
pages/ # One per route (8 files)
|
|
flows/ # One per user journey (5 files)
|
|
specs/ # Executable vitest + playwright-core tests
|
|
pages/ # Page-level tests (8 files)
|
|
flows/ # Flow-level tests (5 files)
|
|
steps/ # Step definitions (leftover from playwright-bdd attempt, unused)
|
|
support/
|
|
browser.ts # Chromium lifecycle for vitest
|
|
seed.ts # IDB seeding via page.evaluate()
|
|
item-factory.ts # Test data builders
|
|
expect.ts # Playwright locator assertions for vitest
|
|
layout.ts # DOM measurement helpers (touch targets, spacing, viewport)
|
|
vitest.config.ts # E2E-specific vitest config
|
|
playwright.config.ts # Shared Playwright settings (viewport, baseURL, etc.)
|
|
```
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
bun install # install deps
|
|
bun run dev # dev server at localhost:5173
|
|
bun run build # production build → build/
|
|
bun run preview # serve production build at localhost:4173
|
|
bun run test # 174 unit tests
|
|
bun run test:e2e # 50 E2E tests (needs build + preview running, or run build first)
|
|
bun run check # svelte-check type checking
|
|
```
|
|
|
|
## Deployment
|
|
|
|
The app is a static SPA. `bun run build` outputs to `build/`. Serve it with any static file server that supports SPA fallback (all routes → `index.html`).
|
|
|
|
Example with Caddy:
|
|
```
|
|
:8080 {
|
|
root * /srv/solidhaus
|
|
try_files {path} /index.html
|
|
file_server
|
|
}
|
|
```
|
|
|
|
Example with nginx:
|
|
```nginx
|
|
server {
|
|
listen 8080;
|
|
root /srv/solidhaus;
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
}
|
|
```
|
|
|
|
No backend required — all data lives in the browser's IndexedDB.
|
|
|
|
## Design Decisions Under Discussion
|
|
|
|
These are captured but not yet implemented:
|
|
|
|
- **Item name optional**: UID (pre-generated 7-char nanoid) is the only required field. Need at least one of name, description, or image.
|
|
- **Item types rework**: Current `itemType` enum mixes behavior (consumable, perishable) with category (clothing, document). Plan to split into behavioral traits (has quantity, has expiry, is container) + freeform categories.
|
|
- **Acquisition model**: Replace `purchaseDate` with acquisition events (purchased, gifted, loaned, rented, found, inherited) with date.
|
|
- **Container nesting**: A fridge is both an item and a container. Items can be "contained in" other items, separate from location tracking.
|
|
|
|
See `CLAUDE.md` for full implementation guide and data schemas.
|
|
|
|
## Known Quirks
|
|
|
|
- **Bun, not Node**: The project uses bun exclusively. Playwright's test runner (`@playwright/test`) doesn't work with bun (worker thread incompatibility), so E2E tests use vitest as the runner with playwright-core for browser automation.
|
|
- **E2E needs a running server**: The E2E tests connect to `localhost:4173`. Run `bun run build && bun run preview` in a separate terminal before running `bun run test:e2e`, or the webServer in the vitest config handles it.
|
|
- **Gherkin features are documentation only**: The `.feature` files describe behavior in plain English but aren't wired to the test runner (playwright-bdd was abandoned due to bun compat). The `.spec.ts` files are the executable tests, each referencing their `.feature` file via `@see` JSDoc.
|
|
- **Step files unused**: `e2e/steps/` contains step definition files from the playwright-bdd approach. They're documentation artifacts, not executed.
|
|
- **Location tree interaction**: Clicking a location name selects it (shows items). To expand/collapse, click the arrow toggle button (`aria-label="Expand"/"Collapse"`), not the name.
|