Initial scaffold for AvtoAmbor parts inventory

SvelteKit 2 + Svelte 4 + adapter-node, SQLite via better-sqlite3 (WAL,
foreign keys on). Bilingual EN/Тоҷикӣ throughout, locale persisted in
localStorage.

Pages: dashboard (totals, low stock, recent movements), parts list with
search and sort, part create/edit, record movement (in/out/adjust with
smart unit-price and adjust-quantity prefill), suppliers list with
inline add.

Schema: categories, suppliers, parts (with _en/_tg name+description
columns, dirams for money), stock_movements with check on movement_type.
On-hand updates are done in JS inside a transaction with the movement
insert.

Dockerized dev: docker compose, named project, bind-mounted data/ for
DB persistence. Seed contains 6 categories, 4 suppliers, 31 realistic
parts (Lada / Nexia / Opel / Toyota bias).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
David Beccue
2026-05-16 07:05:24 +05:00
commit 05be5b03aa
37 changed files with 4617 additions and 0 deletions

167
prompts.txt Normal file
View File

@ -0,0 +1,167 @@
# AvtoAmbor — Auto Parts Inventory System (v1 scaffold)
## Context
Build a simple, single-user inventory system named "AvtoAmbor" for an auto parts
store in Tajikistan. Development is on Linux inside Docker; the production target
is a Windows machine where the owner will access it via browser on localhost.
v1 is PARTS ONLY — no service jobs, customers, or invoicing.
Do not write tests, lint config, or CI in this pass. Keep the code idiomatic,
lightly commented, and not over-engineered.
## Tech stack (strict)
- Node.js 20 LTS, run via Docker
- SQLite via `better-sqlite3`
- SvelteKit 2.x pinned to **Svelte 4** — `"svelte": "^4.2.0"` in package.json.
Use Svelte 4 syntax only: no runes, no `$state`/`$derived`/`$effect`.
- `@sveltejs/adapter-node` for production (so deployment to Windows is just
`node build/index.js`)
- Plain CSS. No Tailwind, no component library.
## Repo layout
avtoambor/
Makefile
Dockerfile
docker-compose.yml
.dockerignore
.gitignore
README.md
package.json
svelte.config.js
vite.config.js
src/
app.html
hooks.server.js # opens db on startup
lib/
server/
db.js # better-sqlite3, WAL mode, foreign keys on
schema.sql
seed.sql
parts.js # CRUD helpers
movements.js
suppliers.js
i18n/
en.json
tg.json
store.js # locale store + t(key) helper
components/
Header.svelte # "AvtoAmbor" wordmark + EN/Тоҷ toggle
routes/
+layout.svelte # renders <Header/>
+page.svelte # dashboard
parts/
+page.svelte # list, search, sort
+page.server.js
new/
+page.svelte
+page.server.js
[id]/
+page.svelte # edit + recent movements
+page.server.js
movements/
new/
+page.svelte
+page.server.js
suppliers/
+page.svelte
+page.server.js
data/ # gitignored; holds avtoambor.db
scripts/
init-db.js # reads schema.sql + seed.sql, writes data/avtoambor.db
## Database schema (initial guess — we will iterate)
- All translated fields use `_en` and `_tg` suffixes.
- Money stored as INTEGER dirams (1 TJS = 100 dirams).
- Timestamps as ISO 8601 TEXT (`datetime('now')`).
Tables:
- categories(id PK, name_en, name_tg, sort_order)
- suppliers(id PK, name, phone, address, notes, created_at)
- parts(id PK, sku UNIQUE NOT NULL, name_en, name_tg,
description_en, description_tg, category_id FK,
unit TEXT, cost_price INT, sale_price INT,
quantity_on_hand INT DEFAULT 0, reorder_level INT DEFAULT 0,
location TEXT, barcode TEXT, active INT DEFAULT 1,
created_at, updated_at)
- stock_movements(id PK, part_id FK, movement_type
CHECK(movement_type IN ('in','out','adjust')),
quantity INT, unit_price INT,
supplier_id FK NULL, reference TEXT, notes TEXT,
created_at)
Indexes on parts.sku, parts.barcode, parts.category_id, stock_movements.part_id.
Update `parts.quantity_on_hand` in application code (in a transaction with
the movement insert), not via trigger — clearer for future-me.
## Seed data
- 56 categories: Filters, Brakes, Engine, Electrical, Fluids, Belts & Hoses
- 34 suppliers with realistic names
- 2530 realistic auto parts with EN and Tajik (Cyrillic) names.
Bias toward parts common for Lada, Daewoo Nexia, Opel, and Toyota,
which are common in Tajikistan. Use realistic somoni prices.
## UI
- `Header.svelte` (in `+layout.svelte`, every page):
- Left: "AvtoAmbor" wordmark
- Right: language toggle showing the *other* language (click EN → switches to
Tajik). Persist choice to `localStorage` under key `avtoambor.locale`.
- Pages for v1:
- `/` dashboard: total SKUs, count of parts at/below reorder level,
total inventory value at cost
- `/parts` searchable + sortable list
- `/parts/new` create
- `/parts/[id]` edit, with recent movements panel
- `/movements/new` record in/out/adjust
- `/suppliers` list + add inline
- Every visible string goes through the i18n helper. Missing keys fall back to
English and log a `console.warn` once per missing key.
GIve it a Tajik look & feel, if that's even possible for such a simple app
## i18n
- `en.json` and `tg.json` with nested keys (e.g. `nav.parts`, `parts.sku`)
- `store.js` exports a writable `locale` store and a derived `t` function:
`$t('parts.sku')` in templates
- Default locale is `'tg'`. On mount in the layout, read `localStorage` and
hydrate if present.
## Makefile
Targets (use `docker compose`). First target = `help`.
- `help` — print a friendly banner + list of targets with descriptions
- `install` — `docker compose run --rm app npm install`
- `run` — `docker compose up` (dev server on 5173)
- `build` — production build via adapter-node into `build/`
- `db-init` — run `scripts/init-db.js`, skip if `data/avtoambor.db` exists
- `db-reset` — confirm prompt, then delete and recreate the db
- `docker-build` — build the image
- `docker-shell` — interactive bash in the container
- `clean` — remove `node_modules`, `build/`, but keep `data/`
- `clean-all` — also wipe `data/`
Use `@` to suppress command echo where it would be noise.
## Dockerfile
- `node:20-bookworm-slim`
- Install `python3 make g++` for the `better-sqlite3` native build
- Non-root user
- WORKDIR `/app`
- EXPOSE 5173 and 3000
## docker-compose.yml
- One service `app`
- Bind-mount the repo to `/app`
- Named volume for `node_modules` so it doesn't shadow the host
- Bind-mount `./data` so the SQLite file persists on the host
- Map 5173:5173 and 3000:3000
## README.md
Short: what it is, prerequisites (Docker), quickstart
(`make install && make db-init && make run`), and a one-liner on production:
`make build` then `node build/index.js` on the Windows host.
## Deliverables for this pass
1. Generate every file above, working out of the box.
2. Print the resulting file tree.
3. Print the exact command sequence to bring it up from a fresh clone.
4. Call out anything you guessed at that I should review before we move on.