Two SSH keys needed:
- DEPLOY_KEY: CI runner → LXC server (SSH access)
- REPO_DEPLOY_KEY: LXC server → Gitea repo (git pull access)
Workflow writes the repo deploy key to ~/.ssh on the server and
configures SSH to use it for git.b4l.co.th. Handles first deploy
(clone) and subsequent deploys (pull) automatically.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- component_documents table matching device_documents structure
- Upload/delete actions on component detail page
- Documents section in sidebar with file icon, filename, delete on hover
- Devices already had document support; components now match
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Edit buttons were missing type="button" so they could trigger parent
form submissions. Kanban edit now switches to list view where the
inline edit form is rendered.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- todos table with title, description, status (todo/in_progress/done),
priority (urgent/high/medium/low), optional device link, due date
- List view: sorted by priority, inline edit, click-to-advance status
circle (empty → blue dot → green check), edit/delete actions
- Kanban board view: three columns, move buttons between statuses,
priority badges, device links, due dates
- Toggle between List and Board views via URL param
- Optional link to a device for repair-related todos
- Sidebar nav item added
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Sidebar navItems uses $derived() so badge counts stay reactive
- const destructures (c, d, cd) use $derived() to track prop changes
- Added aria-label to hamburger and add-item buttons
- Filter state_referenced_locally warnings in svelte.config.js — these
are intentional one-shot initializers for mutable form inputs
Result: 0 errors, 0 warnings, 0 files with problems.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed page-break-after: always and reset html/body height to auto
so the print renderer doesn't generate a trailing empty page.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The (app) layout's flex h-screen + overflow-hidden container was
clipping label content in the print renderer. Print routes now use
a dedicated (print) layout group with no sidebar/header/flex shell,
just the raw label HTML. Routes changed to /print/device/[id] and
/print/component/[id].
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved all label styling to inline styles with explicit color: black and
background: white so dark mode and Tailwind resets can't hide content.
Print styles use :global() scoped selectors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Label width/height was inside @media screen so print had no dimensions.
Moved to base CSS so labels render in both screen preview and print.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
QR code on the left, text and barcode on the right. Fits the pre-cut
DK-1201 address label format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Print page formatted for Brother DK-22210 (29mm continuous tape)
- Each label has: title, brand/model, serial, QR code, Code 128 barcode
- CSS @page sized to 29mm width with minimal margins
- Print button opens popup that auto-triggers print dialog
- Copies selector to print multiple labels at once
- Barcode encodes short ID (first 8 chars) scannable by the lookup endpoint
- Available on both device and component detail pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Multiple voltages are stored as comma-separated string (e.g. "110V, 220V").
Edit form pre-selects existing values by parsing the stored string.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All items use a consistent grid layout (checkbox/indicator, content, delete)
- Input items show a green check indicator when a value is filled
- Saving a value auto-sets checked=true (clearing it sets checked=false)
- Progress bar and count now include input items with values as completed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checklist items can now be either 'checkbox' (tick/untick) or 'input'
(text value with optional unit). Useful for recording measurements
like RPM, wow & flutter, torque, voltage, dB levels, etc.
- itemType and unit fields on template_items and checklist_items
- Template page shows type selector and unit field when adding items
- Device checklist renders input items as labeled text fields with unit
- Save button persists measured values
- Import copies item types and units from templates
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bind:value + onsubmit pattern caused the input to be empty when
enhance submitted the form. Replaced with post-submission DOM reset
so the value is intact during submission.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- checklist_templates and template_items tables for reusable checklists
- /checklists page: create/edit/delete templates with ordered items
- "Import" button on device detail imports a template as a new checklist
with all items copied (unchecked)
- Sidebar nav item for Checklists between Locations and Gallery
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Checklists feature:
- device_checklists and checklist_items tables
- Create multiple named checklists per device
- Add/toggle/delete items with progress bar
- Checkbox UI with green check, strikethrough for completed items
- Delete checklist button with item count display
Also adds the classic Mac happy face as favicon.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Users and sessions tables (Argon2 password hashing, SHA-256 session tokens)
- Server hooks validate session cookie on every request
- (app) routes redirect to /login if not authenticated
- Login page with email/password, styled matching budget app
- Logout via POST form action (invalidates session)
- User display name and sign out button in header
- create-user CLI script: npm run create-user <email> <password> [name]
- 30-day sessions with auto-refresh after 15 days
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Upgrade to nodejs_22 (22.22.2) for better Vite 6 compatibility
- Fix wrapper script shebang broken by heredoc indentation
- Add preBuild step for svelte-kit sync
- Default databaseUrl to "" so environmentFile-only configs don't fail eval
- Add assertion ensuring either databaseUrl or environmentFile is set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Includes nix develop shell (node, pg, vips), buildNpmPackage derivation,
and a NixOS module for deploying as a systemd service with hardening,
dedicated user, and configurable secrets via environmentFile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SvelteKit + PostgreSQL app for tracking vintage computers, audio equipment,
components, and installation history. Features device/component CRUD, operation
logs, QR code labels, global search, image uploads, and dark mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>