Parked sketch · Drag-and-drop file field pattern
Sketched 21 May 2026. Dan’s ask: “sketch a pattern for drag-and-drop images into a target field area on a page, that lights up when a file is detected, and becomes an attachment to the field expecting image, images or CSV etc.”
A reusable UI component that any portfolio form (ingest form, contractor record, watch record, claim sidecar form, land-registry document slot) can drop in to capture files via drag-and-drop without needing a server roundtrip during the design phase.
Problem statement
Across the portfolio there are many places where a form needs an attachment:
| Where | What’s expected | Current state |
|---|---|---|
Contents-claim ingest form (_ingest-form.html) |
photo per item + receipt per replacement | text-only field — Dan pastes filename, no drop |
| Contractor records | yard sign / work photo / business card | manually copied to pa/contractors/photos/ then HTML-referenced |
| Watch records | dial + caseback + serial-plate shots | same manual copy + reference |
| Land registry | deed PDF / survey / title insurance | placeholder awaiting scan flags |
| Utility / sense / harvest records | CSV imports of readings, time entries, sales | non-existent — no drop pattern anywhere yet |
Every one of these would benefit from a “drag a file in, see it attached, export with the form data” flow — without needing to wire up a server, S3 bucket, or auth gate.
Architectural choices — three depths
Depth 1 — Pure client-side, embed-as-data-URL (Recommended for MVP)
- File dragged in →
FileReader.readAsDataURL()→ base64 string - Stored in localStorage with the rest of the form’s working state
- On form export (YAML / JSON / clipboard), files included inline as data URLs
- Dan (or Claude) parses the exported data + writes files to disk on a separate step
- No server, no upload, no auth — same shape as the existing
_ingest-form.html
Limits: ~5MB practical per-file (localStorage quotas + base64 30% bloat); fine for receipts, photos, single PDFs; not for large videos or multi-MB scans.
Depth 2 — Worker-backed direct R2 upload (when MVP outgrows localStorage)
- Drop file → POST metadata to a CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Worker → Worker mints a pre-signed PUT URL → client uploads directly to R2
- Form stores R2 path reference, not the file
- Worker needs auth (re-use CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Access cookie zone)
- Scales to large files
Limits: needs new Worker + R2 bucket + auth wiring; overkill for the MVP use cases above.
Depth 3 — GitHub-API direct commit (the substrate-extreme play)
- Drop file → POST via GitHub REST API to commit directly to the home-projects repo at the expected path
- Auto-triggers the existing pre-push deploy chain → file lives on pa.gf.cx within minutes
- No new infrastructure beyond a Personal Access Token
Limits: browser-side GitHub PAT exposure unless behind auth proxy; rate-limited; not ideal for high-frequency.
Decision for the first build: Depth 1. Lift to Depth 2/3 later if a specific surface needs it.
Visual state machine
Five states the drop zone cycles through: