Files
verdande/web
Kristian WindandClaude Opus 5 eaff890860 fix(forms): Safari focused none of them, and a board could not make a section
Two reports, one sentence between them: "sections have no function, because you
cannot create more than one."

`autofocus` does not work in Safari for anything inserted after the page has
loaded, and every inline form here is inserted after the page has loaded — rename
a project, add a section, name a group. In Safari they all opened with no cursor
in them and what you typed went nowhere. That does not look like a bug. It looks
like the feature does not work. `use:focusOnMount` replaces all seventeen.

And the board had no way to add a section at all. The button lived only in the
list view, which is the one place nobody looks for it: a column on a board *is* a
section, so that is where you go to make one.

Chasing this turned up a third. The task drawer's three fields save on blur, and
closing the drawer *is* a blur — the input is being unmounted and the browser
fires blur on the way out. If the task left the store in the same moment, `task`
was already null and the handler threw `Cannot read properties of null`, stopping
the page. It only became reproducible once focus actually worked.

Fields are 16px on a touch device now, whatever the component asked for. Below
16px, iOS Safari zooms in when a field takes focus and does not zoom back out —
so the whole interface is left too large and has to be pinched back by hand, once
per field. The type scale tops out at 15px, so every input in the app did it.

The sidebar's resize handle sat at `right: -3px`. An absolutely positioned child
counts towards its container's scrollable overflow, and `overflow-y: auto`
resolves the other axis to `auto` too — so those three pixels gave the whole menu
a horizontal scrollbar on every desktop, always. The account name could do it as
well: `overflow: hidden` with no `min-width: 0` cannot shrink, so the row grew
instead of ellipsing.

There is a WebKit pass in the suite now, over one test. The rest stays Chromium
on purpose — a smoke test exists to catch a build that does not work, and three
engines find the same bug three times — but focus is the exception, and it took a
person using the app to find that out.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:05:02 +02:00
..

web

The SvelteKit PWA. Not written yet — this directory holds its place so the Docker build has something to copy, and so the frontend stage can tell "not built yet" apart from "the build failed".

The Dockerfile builds this directory when it finds a package.json here, and otherwise emits a placeholder page. So adding the real app is exactly: put a SvelteKit project in this directory whose npm run build produces build/.

What it needs to be

  • SvelteKit, adapter-static, output in build/. The Go binary embeds that directory at compile time and serves it, falling back to index.html so client-side routes survive a reload.
  • A PWA: installable, offline reading of already-cached lists, swipe gestures for complete and schedule.
  • Nordic minimalism. Dark by default, light available. One accent colour, everything else neutral. Runic mark for Verdande.
  • Optimistic on every local action. No spinner ever appears for something the browser could already know the answer to.

Talking to the backend

Same origin — the Go binary serves both. /api/v1 for REST, /api/v1/ws for the live sync. Session cookie is httpOnly, so the frontend never handles the token itself.

During development, run the backend on 8080 and point the Vite dev server's proxy at it:

VERDANDE_DATA_DIR=./data VERDANDE_DEV=true go run ./cmd/verdande