← The archive
09 / SA· Live·Live
Satchel
Self-hosted file store for a small circle — folders, resumable uploads, member sharing, and short public share links with QR codes. Built from an empty repo to a live, deployed product in five days.
Overview
Self-hosted file store for a small circle — folders, resumable uploads, member sharing, and short public share links with QR codes. Built from an empty repo to a live, deployed product in five days.
Build log
53 entries
The events read API, and the useNotifications seam it feeds
A server-side preview render API for text, code and markdown
Migrate down is not a rollback — serve re-applies it at boot
The events stream — an stl_events collection, hook emitters and a retention policy
The move picker refuses the folder the items are already in
Papercuts — hover-gated row actions, a server-read retention window, and PocketBase datetimes normalised before Date.parse
API defect sweep — 404 for unmatched /api paths, JSON errors for every Accept header, an explicit ISO expiry grammar
ZIP egress recorded per transfer — measured, not capped
child_count now syncs on the destination folder for both move and undo
Member self-purge, closing the folder-purge escalation path
Bulk download over an authenticated ZIP route
Drag to move — onto folders, chips and breadcrumbs alike
Touch selection — long press, 44px targets and a bottom action bar
Selection and bulk actions across the file browser
Sort and view preferences that survive navigation
The first build wave exposed two concurrency defects — recorded before they got patched over
Server-owned trash retention, with a near-expiry countdown on the rows
FileBrowser broken into seams — navigation, surface states and item actions
Circle storage usage, measured against a soft target
A ranked spec set with an explicit cut line, and a build runner to drive it
Vendored a set of engineering skills and configured them for this repo
The brand mark lands — sidebar, login, favicons and the public link pages
serve-local pre-creates a dev superuser so PocketBase stops auto-opening the installer
Deleting a non-empty folder is refused — an orphaning guard
Mobile sweep — min-w-0 on SidebarInset kills the horizontal overflow at its root
A command palette with a band trigger, preview handoff and an owner-scoped search endpoint
Folder chips with cap and expand, backed by a hook-maintained, cascade-aware child_count
Linear-style row anatomy — a contained list surface, tinted type tiles and two-line cells
Indigo accent tokens, AA-checked in light and dark, plus a file-type tint and label vocabulary
A My Files overview line, backed by its own /api/overview endpoint
Closing design house-rules drift — motion tokens, button box, focus rings and placeholders
PocketBase CORS locked to the app origin
Satchel goes live — the Nuxt frontend deployed and verified end-to-end at satcheldrop.com
PocketBase deployed and verified live at api.satcheldrop.com
A departing member's items now transfer to the admin on removal, instead of orphaning
Link expiry was off by one in negative-UTC zones
Mona Sans, locally hosted, replaces Inter — plus reduced-motion, inset focus rings and a URL-persisted links filter
A shadcn-vue-first component pass — Sidebar, ToggleGroup, Breadcrumb, Progress, DatePicker and NumberField replace the hand-rolled ones
Link hardening — rate limiting, a trash warning, dead-link handling and a fail-closed cookie secret
A links dashboard with visit analytics and a nav badge
QR codes on every link, with status badges and link indicators on the items they point at
Streaming ZIP download for public folder links
Short public share links — password gate, byte cap and scope enforcement, all before a single byte is served
Member sharing — a shares collection, an access resolver, and a shared-with-me page
Trash with restore, and a scheduled purge behind it
The file browser — folders, previews and drag-drop uploads
A resumable multipart upload pipeline, with a docked progress panel
An auth-gated storage proxy with range support and cached thumbnails
Folders and files collections, with path maintenance and a common-tree trash guard
A settings page — profile edits, and admin member management
Phase 1 foundation — design tokens, a PocketBase client with an SSR auth cookie, and a global auth guard
Invite-only users with admin and member roles, and a guard against self-promotion
Satchel begins — a self-hosted file store for a small circle, spec'd before a line was written