utils/dopamine-ux/TODO-07-dufs-theme.md
Krzysztof kuhy Rudnicki 7096c102cd
Some checks are pending
crdt_sync_dart tests / test (push) Waiting to run
crdt_sync_flutter tests / test (push) Waiting to run
crdt-sync pre-commit / pre-commit (push) Waiting to run
crdt-sync tests / test (push) Waiting to run
dependency freshness / dependencies on newest stable (push) Waiting to run
design_system tests / test (push) Waiting to run
file length / file-length (push) Waiting to run
freedays pre-commit / pre-commit (push) Waiting to run
freedays tests / test (push) Waiting to run
gatelock pre-commit / pre-commit (push) Waiting to run
gatelock tests / test (push) Waiting to run
github_device_auth tests / test (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
music_theory tests / test (push) Waiting to run
palette drift / palette (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
sync_settings_ui tests / test (push) Waiting to run
web_ui tests / test (push) Waiting to run
Re-point paths for the ~ reorganisation (home-tidy)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AwtowrowDXx6ccmWVPkCaF
2026-09-11 18:45:55 +02:00

6.9 KiB

Wire dufs-cloud's Flutter app to the shared design_system

findings (2, ranked by value over effort)

  1. app/lib/ui/theme.dart is a fifth, uncompared palette copy — hand-copied hexes that palette_check.py has never seen, so it can drift silently while CI stays green.
  2. The web half of the same repo is wired correctly — which makes the Flutter half's divergence an accident, not a decision.

what

~/src/dufs-cloud/app/lib/ui/theme.dart is a fifth, uncompared copy of the palette. Verified 2026-08-16: the Flutter app has no design_system dependency at all — it hand-restates every hex (Color(0xFF211D1B) // ink, Color(0xFFB8862E) // accent, …) with the shared token names appearing only in comments. palette_check.py has never seen this file, so it can drift from the frozen table silently and CI will stay green.

The web half of the same repo is wired correctly (@kuhyx/web-ui), which makes the Flutter half's divergence an accident rather than a decision.

Fix the root cause: add the dependency, replace the hand-copied hexes with token references, and delete the duplicate. This must land before prompt 08 adds motion to this app, so that motion tokens arrive through the package instead of becoming a sixth hand-copy.

where

Repo: ~/src/dufs-cloud. Flutter app: ~/src/dufs-cloud/app (package dufs_client).

  • app/pubspec.yaml — current deps: archive, cupertino_icons, flutter, flutter_secure_storage, http, image_picker, media_kit*, path, path_provider, share_plus, shared_preferences, webview_flutter, xml. No design_system.
  • app/lib/ui/theme.dart — the hand-copy to eliminate.
  • Every file referencing a colour from it — find them with a grep for the theme's exported symbols rather than trusting any list here.

Source of truth:

  • ~/src/utils/design_system/lib/src/tokens.dart — AppPalette, AppSpacing, AppRadius, AppTextSize (plus AppDuration/AppCurve if prompt 01 ran).
  • ~/src/utils/design_system/lib/src/theme.dart — buildLightTheme(), buildDarkTheme().

Reference implementation: ~/src/todo is the only app already on the package. Its pubspec.yaml uses a git ref (design_system-v0.1.0) and it has deliberately no local theme.dart. Copy that shape.

must

  • Add design_system to app/pubspec.yaml using the git ref style matching ~/src/todo — not a local path: dependency. One dependency convention across the fleet. Pin the tag prompt 01 cut (design_system-v0.2.0 or whatever it printed); if prompt 01 has not run, pin design_system-v0.1.0 and let prompt 08 do the bump.

  • Replace every hand-copied hex in app/lib/ui/theme.dart with the corresponding token reference. Verify each swap is value-identical before making it — the survey found the values byte-identical today, but confirm rather than assume; a silent colour change in a live app is a real regression.

  • Delete the duplicated token declarations once nothing references them. If the app declares helper classes the shared package lacks, keep only those, and say in the session summary which ones survived and why.

  • Keep the app's visual output identical. This is a pure de-duplication: if anything looks different afterwards, a value was wrong and you have found a pre-existing drift — report it rather than papering over it.

  • must not: change any colour, spacing, radius or type value. The shared table is a freeze. If a value genuinely disagrees, stop and surface it — that is a finding, and kuhy decides which side is canonical.

  • must not: add motion/animation here. That is prompt 08. This prompt is dependency plumbing only, so that a visual regression has exactly one possible cause.

  • must not: touch ~/src/dufs-cloud/web/ — its @kuhyx/web-ui wiring is already correct.

  • must not: leave a partial migration. Either the local theme file is gone (or reduced to app-specific extras) and everything resolves through the package, or the change is not done. A half-migrated theme is worse than the current state because it hides which copy is authoritative.

  • optional: once migrated, add app/lib/ui/theme.dart's path to the structural checker from prompt 02 if that is now meaningful. Probably it is not — after this prompt there is nothing left there to compare.

done

  1. app/pubspec.yaml declares design_system at a git ref; flutter pub get resolves.
  2. No hard-coded palette hex remains in app/lib/. A grep for Color(0xFF in app/lib/ui/theme.dart returns nothing (or only app-specific values that are not palette tokens — name them if so).
  3. cd ~/src/dufs-cloud/app && flutter analyze is clean.
  4. cd ~/src/dufs-cloud/app && flutter test passes.
  5. The app looks the same as before on device — verified by screenshot comparison, not by reasoning about the diff.
  6. python3 ~/src/utils/unified-design-system/scripts/palette_check.py still exits 0.

verify

On the phone, and with a before/after comparison — a pure refactor is only verified by showing nothing changed.

adb devices
cd ~/src/dufs-cloud/app
flutter build apk --release
adb install -r build/app/outputs/flutter-apk/app-release.apk

Take a screenshot of the browser screen and the settings screen before starting (from the currently installed build) and after, and compare them. Never adb uninstall or pm clear — the app holds a stored credential (flutter_secure_storage) and wiping it means re-authenticating.

read first

  • ~/src/dufs-cloud/app/lib/ui/theme.dart — in full, before touching anything. The comments naming each token are your mapping table.
  • ~/src/todo/pubspec.yaml — the git-ref dependency line to copy, and the comment explaining why no local theme exists.
  • ~/src/utils/design_system/lib/src/tokens.dart — the canonical names.
  • ~/src/dufs-cloud/DESIGN_AUDIT_TODO.md — a prior audit of this repo; check whether it already records theme findings so you do not contradict it.

context you would otherwise rediscover

  • The web half consumes @kuhyx/web-ui at tag web_ui-v0.3.1, declared in ~/src/dufs-cloud/web/package.json as "github:kuhyx/utils#web_ui-v0.3.1&path:/web_ui". It is correctly wired; the only app-local CSS value is --overlay: rgba(33, 29, 27, 0.82) in web/src/index.css. Prompt 08 bumps that tag — not this prompt.
  • @kuhyx/web-ui is pnpm-only; npm cannot install a monorepo subdirectory. Irrelevant here (this prompt is Flutter-only) but fatal if you wander into web/.
  • palette_check.py compares four sources and has never included this file, so "CI is green" told you nothing about it. That is the whole reason this prompt exists.
  • Three other Flutter apps (diet-guard, workout_app, wake_alarm) have the same hand-copy pattern. They are out of scope — migrating them is a separate, larger job, and doing one app properly is the point here.

REMOVE ME AFTER FINISH