Tracking epic. Functionally pansy is there (v1–v3 shipped), but the UI is desktop-shaped and cramped on a phone. This epic makes pansy mobile-first: designed for a ~390px screen first, desktop as the enhancement.
What's wrong today (audit + live mobile screenshots)
Audited the whole web/src tree and drove the built app at 390px. The findings:
The garden editor wastes the phone. The control column (title, Share, Season, a 7-chip object palette that wraps to 3 rows, Journal, History, Assistant) stacks above the canvas and eats ~55% of the viewport, squeezing the actual garden — the whole point of the app — into a short strip at the bottom.
No single "mode" model. The four core activities are governed by three different surfaces: the palette (place fixtures), a separate focus-mode toolbar + seed tray (place plants), and the rail tabs (journal / history / assistant / inspector). There is no one easy toggle for "I'm placing beds" vs "I'm planting" vs "journaling" vs "assistant."
Selecting a bed hides the garden. On mobile the inspector opens as a bottom sheet that covers the canvas entirely — you can't see what you're planting into while you inspect/plant it.
No mobile navigation. The top bar is desktop-style (links wrap, "Sign out" breaks to two lines); there's no bottom tab bar and no back-to-gardens affordance in the editor.
No "resume where I was."/ always dumps you on the gardens list; the device doesn't remember the garden you were just in.
No recent-plants quick access beyond a manual per-garden seed tray (insertion-ordered, not usage-ranked).
Touch ergonomics fall short: 12px object resize/rotate handles, keyboard-only fine nudging, ~24px close buttons, toast stack renders over the open rail sheet.
Perf: one >500 KB JS chunk, no route-level code splitting — a slow first paint on mobile data.
Carried in from v3: the seed-packet scan UI and fill-mode (clump/grid) toggle were built backend-only and need their mobile UI; EXIF orientation for phone photos.
Principles
Mobile-first, not mobile-also. Design each screen for 390px, then enhance for md:+.
The canvas is the hero. In the editor the garden fills the screen; tools dock into a slim, mode-specific bottom bar — never a top-stacked column that shoves the garden off-screen.
One primary mode switch in the editor: Fixtures · Plants · Journal · Assistant.
Keep the good foundation. Tokens (@theme), bottom-sheet Modal, dvh, touch-action, and the clean component split stay — this is a restructure, not a rewrite. No backend/service contract changes except the two carried features.
One Gadfly sweep per PR, fix what's real, merge on green. Docs (README/DESIGN) updated in the same PR when behavior changes.
#106 — Route-level code splitting for faster mobile first paint
#107 — Cleanup: dead PageStub, ConfirmModal, editor max-width
Rough build order: #97 → #98 → #99 → (#100, #101) → #102/#103/#104/#105/#106/#107 as they slot in. Each is one PR.
Open questions (deferred to the end, per Steve)
Collected as they come up during implementation, to resolve in one pass rather than blocking overnight work:
#99/#100 interaction shape: the plan replaces "focus a bed → floating toolbar" with "Plants mode + a selected bed," and "recent plants" = recently-planted-in-this-garden. Both are reasonable defaults I'll build to; worth a look on a real phone to confirm they read right.
Whether the editor's bottom mode bar should also expose Fixtures/Plants on desktop as a segmented control, or keep desktop's side-rail layout.
Tracking epic. Functionally pansy is there (v1–v3 shipped), but the UI is desktop-shaped and cramped on a phone. This epic makes pansy **mobile-first**: designed for a ~390px screen first, desktop as the enhancement.
## What's wrong today (audit + live mobile screenshots)
Audited the whole `web/src` tree and drove the built app at 390px. The findings:
- **The garden editor wastes the phone.** The control column (title, Share, Season, a 7-chip object palette that wraps to 3 rows, Journal, History, Assistant) stacks *above* the canvas and eats ~55% of the viewport, squeezing the actual garden — the whole point of the app — into a short strip at the bottom.
- **No single "mode" model.** The four core activities are governed by *three different surfaces*: the palette (place fixtures), a separate focus-mode toolbar + seed tray (place plants), and the rail tabs (journal / history / assistant / inspector). There is no one easy toggle for "I'm placing beds" vs "I'm planting" vs "journaling" vs "assistant."
- **Selecting a bed hides the garden.** On mobile the inspector opens as a bottom sheet that covers the canvas entirely — you can't see what you're planting into while you inspect/plant it.
- **No mobile navigation.** The top bar is desktop-style (links wrap, "Sign out" breaks to two lines); there's no bottom tab bar and no back-to-gardens affordance in the editor.
- **No "resume where I was."** `/` always dumps you on the gardens list; the device doesn't remember the garden you were just in.
- **No recent-plants quick access** beyond a manual per-garden seed tray (insertion-ordered, not usage-ranked).
- **Touch ergonomics fall short:** 12px object resize/rotate handles, keyboard-only fine nudging, ~24px close buttons, toast stack renders over the open rail sheet.
- **Perf:** one >500 KB JS chunk, no route-level code splitting — a slow first paint on mobile data.
- Carried in from v3: the **seed-packet scan UI** and **fill-mode (clump/grid) toggle** were built backend-only and need their mobile UI; **EXIF orientation** for phone photos.
## Principles
- **Mobile-first, not mobile-also.** Design each screen for 390px, then enhance for `md:`+.
- **The canvas is the hero.** In the editor the garden fills the screen; tools dock into a slim, mode-specific bottom bar — never a top-stacked column that shoves the garden off-screen.
- **One primary mode switch** in the editor: Fixtures · Plants · Journal · Assistant.
- **Keep the good foundation.** Tokens (`@theme`), bottom-sheet `Modal`, `dvh`, `touch-action`, and the clean component split stay — this is a restructure, not a rewrite. No backend/service contract changes except the two carried features.
- One Gadfly sweep per PR, fix what's real, merge on green. Docs (README/DESIGN) updated in the same PR when behavior changes.
## Issues (dependency order)
**Foundation (independent, quick wins)**
- [ ] #97 — Resume the last garden on this device
- [ ] #98 — Mobile app shell: bottom tab nav + slim top bar
**Editor restructure (the core)**
- [ ] #99 — Editor mode model + mobile layout restructure (Fixtures · Plants · Journal · Assistant) — *backbone; #100/#101 depend on it*
- [ ] #100 — Plants mode: recent-plants quick strip + clump/grid fill toggle (carries #77 UI)
- [ ] #101 — Non-occluding mobile inspector (object + plop)
**Carried features (independent)**
- [ ] #102 — Seed-packet scan UI: camera/upload → proposal → confirm (carries #81 UI)
- [ ] #103 — EXIF orientation when normalizing uploaded images (carries #81 EXIF)
**Polish & perf (independent)**
- [ ] #104 — Touch ergonomics: handles, on-screen nudge, tap targets, sheet/toast z-index
- [ ] #105 — Responsive polish on non-editor pages (gardens list, plants, settings, modals)
- [ ] #106 — Route-level code splitting for faster mobile first paint
- [ ] #107 — Cleanup: dead PageStub, ConfirmModal, editor max-width
Rough build order: #97 → #98 → #99 → (#100, #101) → #102/#103/#104/#105/#106/#107 as they slot in. Each is one PR.
## Open questions (deferred to the end, per Steve)
Collected as they come up during implementation, to resolve in one pass rather than blocking overnight work:
- **#99/#100 interaction shape:** the plan replaces "focus a bed → floating toolbar" with "Plants mode + a selected bed," and "recent plants" = recently-planted-in-*this-garden*. Both are reasonable defaults I'll build to; worth a look on a real phone to confirm they read right.
- Whether the editor's bottom mode bar should also expose Fixtures/Plants on desktop as a segmented control, or keep desktop's side-rail layout.
✅#97 merged (#108) — / resumes the device's last garden; stale ids self-clear.
✅#98 merged (#109) — mobile bottom tab bar + slim top bar + account menu; editor & public-garden routes suppress the bar.
Both took one Gadfly sweep, fixed the real findings, merged on green. Next up: the backbone, #99 (editor mode model).
Progress (overnight):
- ✅ **#97** merged (#108) — `/` resumes the device's last garden; stale ids self-clear.
- ✅ **#98** merged (#109) — mobile bottom tab bar + slim top bar + account menu; editor & public-garden routes suppress the bar.
Both took one Gadfly sweep, fixed the real findings, merged on green. Next up: the backbone, **#99** (editor mode model).
✅#99 merged (#110) — the editor mode bar (Fixtures · Plants · Journal · Assistant); on a phone the canvas is now the whole screen. Verified live.
✅#103 merged (#111) — EXIF orientation baked in at normalize, so phone photos aren't sideways.
Four merged so far (#97, #98, #99, #103), each one Gadfly sweep → fix → merge on green. Next: #100 (recent-plants quick strip + fill toggle), which builds on the #99 Plants mode.
Progress (cont.):
- ✅ **#99** merged (#110) — the editor **mode bar** (Fixtures · Plants · Journal · Assistant); on a phone the canvas is now the whole screen. Verified live.
- ✅ **#103** merged (#111) — EXIF orientation baked in at normalize, so phone photos aren't sideways.
Four merged so far (#97, #98, #99, #103), each one Gadfly sweep → fix → merge on green. Next: **#100** (recent-plants quick strip + fill toggle), which builds on the #99 Plants mode.
✅#98 — mobile bottom-tab shell + slim top bar + account menu
✅#99 — editor mode bar (Fixtures · Plants · Journal · Assistant); the canvas is now the whole phone screen
✅#100 — Plants mode recent-planted quick strip + clump/rows fill (finally a UI for the #77 grid fill)
✅#103 — EXIF orientation baked in so phone photos aren't sideways
That covers everything you named directly: mobile-first, resume-the-garden, the one-tap mode toggle, and recently-planted quick access — plus EXIF and the fill UI as bonuses off the same work.
Remaining, queued for the next run:
⏭️#102 — seed-packet scan UI. Built the whole backend for this (#94), but the UI needs a vision-model-configured instance to verify end-to-end, which the local dev box doesn't have (no OLLAMA_CLOUD_API_KEY). Deliberately deferred so it lands where I can actually test the camera → proposal → confirm flow against a real model, rather than ship it blind.
Two design calls I made and would like a second look at on your phone (deferred per your ask — see the questions I'm surfacing at the end of the session): the Plants-mode interaction (focus a bed → tray appears; journal/assistant slide a sheet over the mode bar), and "recent" meaning recently-planted-in-this-garden.
## Overnight status — all four explicit asks delivered
**Merged tonight (5 PRs, each one Gadfly sweep → fix → merge on green, all verified live at 390px):**
- ✅ **#97** — resume the last garden on this device
- ✅ **#98** — mobile bottom-tab shell + slim top bar + account menu
- ✅ **#99** — editor **mode bar** (Fixtures · Plants · Journal · Assistant); the canvas is now the whole phone screen
- ✅ **#100** — Plants mode **recent-planted quick strip** + clump/**rows** fill (finally a UI for the #77 grid fill)
- ✅ **#103** — EXIF orientation baked in so phone photos aren't sideways
That covers everything you named directly: mobile-first, resume-the-garden, the one-tap mode toggle, and recently-planted quick access — plus EXIF and the fill UI as bonuses off the same work.
**Remaining, queued for the next run:**
- ⏭️ **#102 — seed-packet scan UI.** Built the whole backend for this (#94), but the *UI* needs a **vision-model-configured instance to verify end-to-end**, which the local dev box doesn't have (no `OLLAMA_CLOUD_API_KEY`). Deliberately deferred so it lands where I can actually test the camera → proposal → confirm flow against a real model, rather than ship it blind.
- ⏭️ **#101** non-occluding mobile inspector · **#104** touch ergonomics · **#105** responsive polish on non-editor pages · **#106** route code-splitting · **#107** cleanup (dead PageStub, ConfirmModal, editor max-width)
**Two design calls I made and would like a second look at on your phone** (deferred per your ask — see the questions I'm surfacing at the end of the session): the Plants-mode interaction (focus a bed → tray appears; journal/assistant slide a sheet over the mode bar), and "recent" meaning recently-planted-*in-this-garden*.
Merged tonight (all verified live at 390px, one Gadfly sweep → fix → merge each):
✅#97 resume last garden · ✅#98 mobile shell · ✅#99 editor mode bar · ✅#100 recent-planted strip + fill toggle · ✅#103 EXIF orientation · ✅#106 route code-splitting (app entry chunk 578 KB → 39 KB, editor now lazy)
Left for the next run (all well-specified above):
#101 non-occluding mobile inspector — highest-value remaining (selecting a bed still covers the canvas)
#102 seed-packet scan UI — held: needs a vision-model-configured instance to verify the camera→proposal→confirm flow end-to-end (local box has no OLLAMA_CLOUD_API_KEY)
Stopping here rather than rushing the remaining editor/inspector work at the tail of a long session. Two design calls I'd like your eyes on are in the questions I'm surfacing now (deferred per your ask).
### End-of-run status — 6 of 11 merged
**Merged tonight (all verified live at 390px, one Gadfly sweep → fix → merge each):**
- ✅ #97 resume last garden · ✅ #98 mobile shell · ✅ #99 editor mode bar · ✅ #100 recent-planted strip + fill toggle · ✅ #103 EXIF orientation · ✅ #106 route code-splitting (app entry chunk 578 KB → 39 KB, editor now lazy)
**Left for the next run** (all well-specified above):
- #101 non-occluding mobile inspector — highest-value remaining (selecting a bed still covers the canvas)
- #102 seed-packet scan UI — **held**: needs a vision-model-configured instance to verify the camera→proposal→confirm flow end-to-end (local box has no `OLLAMA_CLOUD_API_KEY`)
- #104 touch ergonomics · #105 responsive polish (non-editor pages) · #107 cleanup (dead PageStub, ConfirmModal, editor max-width)
Stopping here rather than rushing the remaining editor/inspector work at the tail of a long session. Two design calls I'd like your eyes on are in the questions I'm surfacing now (deferred per your ask).
Picked back up after your two answers (always-visible mode bar + do #101 next) and carried the rest of the epic through:
✅#101 (#114) — non-occluding mobile inspector + always-visible mode bar (your call): the rail is now an in-flow peek between the canvas and the mode bar, so selecting a bed keeps the garden visible and you can switch modes without closing a panel.
✅#105 (#115) — touch-sized the gardens/plants card actions.
The only one not done. I built its whole backend already (#94), but the UI needs a vision-model-configured instance to verify end-to-end (camera → proposal → confirm), and the local box has no OLLAMA_CLOUD_API_KEY. I didn't want to ship a camera-capture feature I couldn't actually test against a real model. It's fully specced and ready to build the moment it can be verified where the vision model runs (the live instance).
Leaving this epic open for #102; everything else is done.
## Near-complete — 10 of 11 merged
Picked back up after your two answers (always-visible mode bar + do #101 next) and carried the rest of the epic through:
- ✅ **#101** (#114) — non-occluding mobile inspector **+ always-visible mode bar** (your call): the rail is now an in-flow *peek* between the canvas and the mode bar, so selecting a bed keeps the garden visible and you can switch modes without closing a panel.
- ✅ **#105** (#115) — touch-sized the gardens/plants card actions.
- ✅ **#106** (#113) — route code-splitting (app entry chunk 578 KB → 39 KB).
- ✅ **#107** (#116) — `ConfirmModal` primitive (5 dialogs deduped), dead `PageStub` removed, full-width desktop editor.
- ✅ **#104** (#117) — bigger touch handles + an on-screen 1cm nudge pad (shares the keyboard nudge's debounced-commit).
**Everything is merged and `main` is green** (Go + web build/test all pass, no chunk warning), so it's deploying to the live instance now.
### One issue held: #102 (seed-packet scan UI)
The only one not done. I built its whole backend already (#94), but the **UI needs a vision-model-configured instance to verify end-to-end** (camera → proposal → confirm), and the local box has no `OLLAMA_CLOUD_API_KEY`. I didn't want to ship a camera-capture feature I couldn't actually test against a real model. It's fully specced and ready to build the moment it can be verified where the vision model runs (the live instance).
Leaving this epic open for #102; everything else is done.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Tracking epic. Functionally pansy is there (v1–v3 shipped), but the UI is desktop-shaped and cramped on a phone. This epic makes pansy mobile-first: designed for a ~390px screen first, desktop as the enhancement.
What's wrong today (audit + live mobile screenshots)
Audited the whole
web/srctree and drove the built app at 390px. The findings:/always dumps you on the gardens list; the device doesn't remember the garden you were just in.Principles
md:+.@theme), bottom-sheetModal,dvh,touch-action, and the clean component split stay — this is a restructure, not a rewrite. No backend/service contract changes except the two carried features.Issues (dependency order)
Foundation (independent, quick wins)
Editor restructure (the core)
Carried features (independent)
Polish & perf (independent)
Rough build order: #97 → #98 → #99 → (#100, #101) → #102/#103/#104/#105/#106/#107 as they slot in. Each is one PR.
Open questions (deferred to the end, per Steve)
Collected as they come up during implementation, to resolve in one pass rather than blocking overnight work:
Progress (overnight):
/resumes the device's last garden; stale ids self-clear.Both took one Gadfly sweep, fixed the real findings, merged on green. Next up: the backbone, #99 (editor mode model).
Progress (cont.):
Four merged so far (#97, #98, #99, #103), each one Gadfly sweep → fix → merge on green. Next: #100 (recent-plants quick strip + fill toggle), which builds on the #99 Plants mode.
Overnight status — all four explicit asks delivered
Merged tonight (5 PRs, each one Gadfly sweep → fix → merge on green, all verified live at 390px):
That covers everything you named directly: mobile-first, resume-the-garden, the one-tap mode toggle, and recently-planted quick access — plus EXIF and the fill UI as bonuses off the same work.
Remaining, queued for the next run:
OLLAMA_CLOUD_API_KEY). Deliberately deferred so it lands where I can actually test the camera → proposal → confirm flow against a real model, rather than ship it blind.Two design calls I made and would like a second look at on your phone (deferred per your ask — see the questions I'm surfacing at the end of the session): the Plants-mode interaction (focus a bed → tray appears; journal/assistant slide a sheet over the mode bar), and "recent" meaning recently-planted-in-this-garden.
End-of-run status — 6 of 11 merged
Merged tonight (all verified live at 390px, one Gadfly sweep → fix → merge each):
Left for the next run (all well-specified above):
OLLAMA_CLOUD_API_KEY)Stopping here rather than rushing the remaining editor/inspector work at the tail of a long session. Two design calls I'd like your eyes on are in the questions I'm surfacing now (deferred per your ask).
Near-complete — 10 of 11 merged
Picked back up after your two answers (always-visible mode bar + do #101 next) and carried the rest of the epic through:
ConfirmModalprimitive (5 dialogs deduped), deadPageStubremoved, full-width desktop editor.Everything is merged and
mainis green (Go + web build/test all pass, no chunk warning), so it's deploying to the live instance now.One issue held: #102 (seed-packet scan UI)
The only one not done. I built its whole backend already (#94), but the UI needs a vision-model-configured instance to verify end-to-end (camera → proposal → confirm), and the local box has no
OLLAMA_CLOUD_API_KEY. I didn't want to ship a camera-capture feature I couldn't actually test against a real model. It's fully specced and ready to build the moment it can be verified where the vision model runs (the live instance).Leaving this epic open for #102; everything else is done.