What this post covers
While doing three seemingly different tasks — file upload, CSS theming, panel resize — I found they share one thing: all three collapse unless you make the "single source of truth and the boundary where values diverge" explicit.
Day summary
| Task | What I wanted | What I did | Result |
|---|---|---|---|
| Upload | Document the 4-step contract with no step missing | presign → PUT → complete → create; skip PUT if dummy URL | complete notification lets the backend register the upload |
| Theming | Separate the @layer·@scope·light-dark() axes + single CSS generator | token abstraction, @layer to end the specificity war, runtime/build unified under one generator | runtime and build CSS don't diverge |
| Layout | Store fr ratios + restore localStorage once after mount | store fr ratio instead of px; defer restore to after mount | auto-adapts to window size + hydration match |
1. Direct-upload contract
Background (concepts)
- Presigned URL: a server-signed URL through which the client PUTs directly to storage.
What the situation was
Relaying large files through the app server incurs heavy load and timeouts. A direct client → storage upload was needed. The goal was to document the 4-step contract with no step missing.
Core work
Instead of relaying large files through the app server, the client gets a backend-signed presigned URL and PUTs directly to storage. The key is the step contract: presign → PUT → complete → create. Skip the complete notification and the backend never registers the upload. Whether to skip PUT in a mock environment is decided by whether the URL is a dummy, not by a global flag.
Takeaways
- Storage does not notify the backend of a successful PUT automatically — the complete notification is mandatory.
- Making "where the SoT is and where values diverge" explicit structurally prevents conflicts.
2. CSS-token theming
Background (concepts)
@layer·@scope·light-dark(): CSS axes responsible for priority, scope, and mode respectively. They must be handled independently to avoid specificity conflicts.
What the situation was
When runtime-injected CSS and build-output CSS diverge, tokens and priority go out of sync. The goal was axis separation + a single CSS generator.
Core work
Abstract the theme into tokens (custom properties), and separate @layer (priority), @scope (scope), and light-dark() (mode) as independent axes. To keep runtime-injected CSS and build-output CSS from diverging, put a single generator as the single source of truth. As a result, runtime and build CSS don't diverge.
Takeaways
- Split theming into independent axes of priority, scope, and mode, and unify CSS generation into one generator.
3. fr layout and the hydration boundary
Background (concepts)
fr(CSS grid/flex): a unit that divides remaining space by ratio. More robust to window-size changes than px.- Hydration mismatch: when server HTML and the client's first render differ, causing React warnings and flicker.
What the situation was
Storing panel width in px makes recomputation tedious when the window changes, and reading localStorage at store-init time makes SSR differ from the client's first render. The goal was storing fr ratios + restoring localStorage once after mount.
Core work
In panel drag-resize, storing width as an fr ratio instead of px makes redistribution automatic even when container width changes. When restoring the saved layout from localStorage, defer it to once after mount so server render and the first client render match. Got auto-adaptation to window size + hydration match.
Takeaways
- Ratio-based (fr) state is more robust to environment change than absolute values (px).
- localStorage and
windowonly after mount — align with the SSR first render.