feat: Add online user guide with screenshots to public website #203
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Create a public-facing user guide page accessible before login, rendering the existing
docs/USER-GUIDE.mdcontent as an interactive single-page guide with screenshots captured from the live application.Context
docs/USER-GUIDE.md(955 lines, 10 major sections)/public/docs/v2026-01-03.pdf/) with nav: Home | Features | About | Sign Up | Login/guidepublic route and integrates into both public and authenticated navigationRequirements
Page Structure
Navigation Integration
Screenshots
Content Mapping
Map USER-GUIDE.md sections to page sections:
Design
docs/MVP-COLOR-SCHEME.md)Acceptance Criteria
/guideroute accessible without authenticationTechnical Notes
react-markdownor building custom section components from the guide contentfrontend/public/guide/or similar/public/docs/v2026-01-03.pdfcan be removed after this feature shipsPlan: Online User Guide with Screenshots
Phase: Planning | Agent: Planner | Status: AWAITING_REVIEW
Overview
Add a public
/guideroute renderingdocs/USER-GUIDE.mdcontent as styled React components with interspersed screenshots captured from the live application. The guide page uses a sticky TOC sidebar on desktop and collapsible TOC on mobile, matching existing MUI + Tailwind patterns. Guide links are added to public navigation, authenticated sidebar, and mobile hamburger drawer. No new npm dependencies required.Planning Context
Decision Log
Rejected Alternatives
Constraints and Assumptions
Known Risks
Invisible Knowledge
Architecture
Data Flow
Why This Structure
Invariants
Tradeoffs
Milestones
Milestone 1: Guide page foundation and routing
Sub-issue: feat: Guide page foundation and routing (#203)
Files:
frontend/src/pages/GuidePage/GuidePage.tsx(NEW)frontend/src/pages/GuidePage/GuideTableOfContents.tsx(NEW)frontend/src/pages/GuidePage/guideTypes.ts(NEW)frontend/src/pages/GuidePage/components/GuideScreenshot.tsx(NEW)frontend/src/pages/GuidePage/components/GuideTable.tsx(NEW)frontend/src/pages/GuidePage/sections/index.ts(NEW - placeholder exports)frontend/src/App.tsx(MODIFY)Requirements:
/guideroute detection:isGuideRoute = location.pathname === '/guide'shouldShowHomePageto exclude guide route/guideto mobile URL sync skip lists (lines 371, 383)Acceptance Criteria:
Tests:
Code Changes:
Add lazy import in App.tsx after auth pages section:
Add /guide to mobile URL sync skip lists:
Add guide route detection and render block:
Milestone 2: Guide content sections 1-5
Sub-issue: feat: Guide content sections 1-5 (#203)
Files:
frontend/src/pages/GuidePage/sections/GettingStartedSection.tsx(NEW)frontend/src/pages/GuidePage/sections/DashboardSection.tsx(NEW)frontend/src/pages/GuidePage/sections/VehiclesSection.tsx(NEW)frontend/src/pages/GuidePage/sections/FuelLogsSection.tsx(NEW)frontend/src/pages/GuidePage/sections/MaintenanceSection.tsx(NEW)frontend/src/pages/GuidePage/sections/index.ts(MODIFY - add real exports)Requirements:
Acceptance Criteria:
Tests:
Milestone 3: Guide content sections 6-10
Sub-issue: feat: Guide content sections 6-10 (#203)
Files:
frontend/src/pages/GuidePage/sections/GasStationsSection.tsx(NEW)frontend/src/pages/GuidePage/sections/DocumentsSection.tsx(NEW)frontend/src/pages/GuidePage/sections/SettingsSection.tsx(NEW)frontend/src/pages/GuidePage/sections/SubscriptionSection.tsx(NEW)frontend/src/pages/GuidePage/sections/MobileExperienceSection.tsx(NEW)frontend/src/pages/GuidePage/sections/index.ts(MODIFY - add remaining exports)Requirements:
Acceptance Criteria:
Tests:
Milestone 4: Screenshot capture and integration
Sub-issue: feat: Guide screenshot capture and integration (#203)
Files:
frontend/public/guide/(NEW directory)frontend/public/guide/*.webp(NEW - ~15-20 screenshot files)frontend/src/pages/GuidePage/sections/*.tsx(MODIFY - update screenshot src paths)Requirements:
frontend/public/guide/with descriptive filenames (e.g.,dashboard-desktop.webp,vehicles-list-desktop.webp)Acceptance Criteria:
frontend/public/guide/Tests:
Milestone 5: Navigation integration, tests, and cleanup
Sub-issue: feat: Guide navigation integration and tests (#203)
Files:
frontend/src/pages/HomePage.tsx(MODIFY)frontend/src/components/Layout.tsx(MODIFY)frontend/src/shared-minimal/components/mobile/HamburgerDrawer.tsx(MODIFY)frontend/src/pages/__tests__/GuidePage.test.tsx(NEW)frontend/public/docs/v2026-01-03.pdf(DELETE)Requirements:
frontend/public/docs/v2026-01-03.pdfAcceptance Criteria:
Tests:
frontend/src/pages/__tests__/GuidePage.test.tsxCode Changes:
Add Guide link to HomePage desktop nav (between About and Sign Up):
Add Guide link to HomePage mobile menu (between About and Sign Up):
Add Guide link to authenticated sidebar in Layout.tsx:
Note: Requires adding
HelpOutlineRoundedIconimport at top of Layout.tsx:Add Guide link to HamburgerDrawer.tsx:
Note: The Guide item uses
as MobileScreencast and the handleNavigate function will need a guard to handle the Guide case by navigating to /guide via window.location. Requires addingHelpOutlineRoundedIconimport.Milestone 6: Documentation
Sub-issue: docs: Guide page documentation (#203)
Files:
frontend/src/pages/CLAUDE.md(MODIFY or CREATE)frontend/src/pages/GuidePage/CLAUDE.md(NEW)Requirements:
Acceptance Criteria:
Source Material: Invisible Knowledge section of this plan
Milestone Dependencies
M2 and M3 can execute in parallel after M1 completes.
M4 requires M2 and M3 (screenshot placement in section components).
M5 requires M4 (tests verify screenshot loading).
M6 is final documentation pass.
Verdict: AWAITING_REVIEW | Next: Plan review cycle (QR plan-completeness -> TW plan-scrub -> QR plan-code -> QR plan-docs)
QR Review: Plan Completeness
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS_WITH_CONCERNS
Findings
[PLAN] SHOULD_FIX: Decision Log lacks HamburgerDrawer navigation implementation multi-step reasoning
{ screen: 'Guide' as MobileScreen, label: 'Guide', icon: ... }with cast and mentions "handleNavigate function will need a guard" but Decision Log doesn't explain this guard implementation decision. The reasoning stops at "simpler: direct URL navigation" without explaining the guard pattern.[PLAN] SHOULD_FIX: Missing screenshot count validation in Milestone 4
[PLAN] SUGGESTION: Milestone dependency graph could clarify M4 screenshot placement
Considered But Not Flagged
const GuidePage = lazy(...)), M4 uses lazy loading for images (loading="lazy"attribute in GuideScreenshot component)frontend/src/pages/GuidePage/GuidePage.tsx, not "guide files")Verdict
PASS_WITH_CONCERNS
The plan is comprehensive and covers all acceptance criteria with specific, testable milestones. The 3 findings are quality improvements (1 incomplete reasoning chain, 1 missing count validation note, 1 clarity enhancement) rather than blocking gaps.
Recommended action: Address SHOULD_FIX findings to strengthen Decision Log completeness and milestone acceptance criteria clarity, then proceed to TW plan-scrub phase.
Next: Technical Writer plan-scrub review
TW Review: Plan Scrub
Phase: Plan-Review | Agent: Technical Writer | Status: PASS
Findings
[TEMPORAL] CLEAN: All diff block comments pass Timeless Present Rule
Reviewed all diff blocks in Milestone 1 (App.tsx, 4 diffs) and Milestone 5 (HomePage.tsx 2 diffs, Layout.tsx 2 diffs, HamburgerDrawer.tsx 1 diff). Only one code comment exists in the diffs:
// Public pages (lazy-loaded)-- Describes what this code section IS. Clean. No change-relative language, no baseline reference, no location directive, no planning artifact, no intent leakage.All other diff blocks contain pure code with no comments. No temporal contamination detected.
[PROSE] CLEAN: Milestone 5 "Note:" blocks are plan instructions, not code comments
Two "Note:" blocks follow diffs in Milestone 5:
HelpOutlineRoundedIconimport at top of Layout.tsx"as MobileScreencast and the handleNavigate function will need a guard..."These are developer instructions within the plan, not code comments that would appear in source files. The phrase "will need a guard" is planning language but is correctly scoped -- it tells the developer what to implement, not what to write as a comment. No action required.
[COMMENT QUALITY] SUGGESTION: Decision Log entries could inform 2-3 WHY comments
The Decision Log has entries that could produce valuable code comments during implementation. The planner is not expected to author these comments (that is the developer's responsibility), but noting the strongest candidates for the developer's awareness:
"Guide link as window.location in mobile hamburger" -- The HamburgerDrawer guard for 'Guide' screen should have a WHY comment explaining
/guideis a public route outside the/garage/*shell, so it bypasses Zustand navigation. The Decision Log reasoning chain provides the material."Custom React components over react-markdown" -- GuidePage.tsx or its CLAUDE.md could note: "Static JSX components rather than react-markdown; content changes quarterly; avoids ~48KB runtime + 15-20 transitive deps for content that needs full MUI/Tailwind control." This is an architecture decision not apparent from code alone.
"Individual section component files" -- The sections/index.ts barrel file could note the rationale if it is not already captured in the GuidePage CLAUDE.md (Milestone 6 covers this).
These are suggestions for the developer during implementation, not plan defects.
[PROSE CLARITY] CLEAN: Requirements and acceptance criteria are clear and testable
All milestone requirements use precise, unambiguous language:
One minor note: M1 acceptance criteria item "Navigation bar present with Guide link active/highlighted" -- "active/highlighted" could be more precise (does it mean CSS active state, aria-current, visual indicator?). This is minor and implementation context will clarify.
[PROSE CLARITY] CLEAN: Invisible Knowledge section is well-structured
Architecture diagram, data flow, "Why This Structure" explanations, invariants, and tradeoffs are all clearly written in timeless present tense. No temporal contamination. The explanations document architecture decisions not apparent from code (exactly what Invisible Knowledge should contain).
Verdict
PASS
All diff block comments are temporally clean. Plan prose is clear, testable, and free of forbidden patterns. The Decision Log provides strong material for the developer to derive WHY comments during implementation (3 suggestions noted above, non-blocking). No temporal contamination detected anywhere in the plan.
Next: QR plan-code review
QR Review: Plan Docs
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Findings
[DOCS] CLEAN: Documentation milestone exists (M6)
Milestone 6 is dedicated to documentation with clear requirements:
No issues found.
[DOCS] CLEAN: CLAUDE.md specifies tabular index format
M6 requirements state: "Create CLAUDE.md index for GuidePage directory with file listings and when-to-read". The project convention (shown in docs/CLAUDE.md, frontend/src/pages/CLAUDE.md patterns) uses the
| File | What | When to read |format. The requirement "with file listings and when-to-read" confirms this format is expected, even though it doesn't explicitly say "tabular" - the project pattern is consistent and unambiguous.No issues found.
[DOCS] CLEAN: README.md appropriately scoped
The plan creates a feature-level CLAUDE.md but does NOT create a README.md. This is correct because:
No issues found.
[DOCS] QUALITY: Invisible Knowledge captures non-obvious decisions
The Invisible Knowledge section includes 4 key subsections that document decisions not apparent from reading code:
All 5 subsections explain architectural choices that a new team member could NOT deduce from reading the source files alone. The "Why This Structure" section is particularly strong - each rationale explains the CONTEXT that drove the decision.
No issues found.
[DOCS] SUGGESTION: Architecture diagram could be enhanced with visual representation
The Architecture diagram is text-based (tree structure using ASCII art). While it clearly shows the component hierarchy, a Mermaid diagram could improve clarity for complex relationships like:
Example Mermaid enhancement:
This is a SUGGESTION, not a requirement. The text-based diagram is functional and complete. Visual enhancement would improve comprehension but is not blocking.
[DOCS] CLEAN: All new files referenced in documentation milestone
M6 files list includes:
frontend/src/pages/CLAUDE.md(MODIFY or CREATE)frontend/src/pages/GuidePage/CLAUDE.md(NEW)This covers documentation for the new GuidePage directory and its integration into the parent pages/ directory structure. The MODIFY or CREATE handling for pages/CLAUDE.md correctly accounts for uncertainty about whether that file currently exists.
All new directories introduced in the plan (GuidePage/, sections/, components/) will have documentation coverage through these two CLAUDE.md files.
No issues found.
Considered But Not Flagged
Verdict
PASS
All 6 documentation completeness criteria are met:
The plan's documentation approach is comprehensive and follows project conventions. The Invisible Knowledge section provides strong architectural context that will enable future maintainers to understand WHY decisions were made, not just WHAT was built.
Next: QR plan-code review
QR Review: Plan Code
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS
Findings
[RULE 1] CLEAN: All diffs follow existing App.tsx lazy loading pattern
Verified M1 App.tsx diffs against existing code structure (lines 16-65):
const GuidePage = lazy(...)after auth pages section (line 53) - correct location matching existing patternlazy(() => import('./pages/GuidePage/GuidePage').then(m => ({ default: m.GuidePage })))matches existing pattern from lines 16-25isGuideRoute,shouldShowHomePageupdate follows existing pattern from lines 497-498No RULE 1 violations detected. Pattern conformance is correct.
[RULE 1] CLEAN: HomePage navigation additions maintain existing structure
Verified M5 HomePage.tsx diffs against existing code (lines 79-110 desktop, lines 138-179 mobile):
text-white/75 hover:text-white transition-colors) matching existing links at lines 80-90py-2matching existing mobile links (line 159), effective height ~48px - meets >= 44px requirement from default-conventionsNo RULE 1 violations. Navigation integration follows existing HomePage patterns.
[RULE 1] CLEAN: Layout.tsx sidebar addition follows navigation array pattern
Verified M5 Layout.tsx diffs against existing code (line 46-54):
{ name: 'Guide', href: '/guide', icon: <HelpOutlineRoundedIcon sx={{ fontSize: 20 }} /> }matching exact format from lines 47-53sx={{ fontSize: 20 }}matches all other nav icons (lines 47-53)import HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';matching import style from lines 10-19/guideis absolute path matching existing/garage/documents,/garage/settingspatternNo RULE 1 violations. Sidebar integration is correct.
[RULE 1] SUGGESTION: HamburgerDrawer navigation guard implementation needs clarification in M5 code changes
Location: Milestone 5 > Code Changes > HamburgerDrawer.tsx
Issue: M5 diff shows
{ screen: 'Guide' as MobileScreen, label: 'Guide', icon: <HelpOutlineRoundedIcon /> }with note "The Guide item usesas MobileScreencast and the handleNavigate function will need a guard to handle the Guide case by navigating to /guide via window.location." The note is accurate but incomplete - it doesn't show the actual guard implementation.Why this matters: Developer implementing M5 will need to modify the
handleNavigatefunction (lines 59-62 in current HamburgerDrawer.tsx) to check for 'Guide' screen and usewindow.location.href = '/guide'instead of callingonNavigate(screen). Without the guard code in the diff or note, the implementation is left ambiguous.Suggested Fix: Add a second diff block in M5 showing the handleNavigate guard:
This is a SUGGESTION not a blocker - the Decision Log entry "Guide link as window.location in mobile hamburger" provides the reasoning, and the M5 note mentions the guard. Adding the explicit guard diff would eliminate implementation ambiguity.
[RULE 2] CLEAN: Individual section files prevent god object anti-pattern
Reviewed proposed file structure: 10 section files at ~150-250 lines JSX each (per M2/M3 requirements). Decision Log entry "Individual section component files" provides reasoning: single file would be 2000+ lines god object; individual files follow default-conventions file-creation domain (clear module boundary).
Verified against RULE 2 god object threshold: >15 public methods or >10 dependencies. Static JSX section components have 0 public methods and ~3-5 dependencies (React, MUI Typography, GuideTable, GuideScreenshot). No god object risk.
Tradeoffs section acknowledges file count cost: "18 new files vs single content file: chose modularity over fewer files". Explicit decision documented.
No RULE 2 violations. File organization is sound.
[RULE 2] CLEAN: No duplicate logic detected across section components
Reviewed M2/M3 section component requirements: shared GuideScreenshot and GuideTable components extract common patterns. Decision Log entries:
This is correct RULE 2 duplication prevention. Each section uses GuideScreenshot/GuideTable for common patterns rather than copy-pasting MUI Table code or img tags 15+ times.
No RULE 2 duplication violations.
[RULE 0] CLEAN: No unhandled error paths detected in diffs
Reviewed all code diffs in M1 and M5:
No RULE 0 violations detected.
[RULE 0] CLEAN: GuideScreenshot lazy loading prevents resource exhaustion
M4 acceptance criteria specifies "Total guide image payload under 5MB (WebP compression)" and GuideScreenshot component uses
loading="lazy"attribute. Decision Log entry: "Large page size with ~15+ screenshots -> Lazy loading with loading="lazy" attribute; WebP format reduces file sizes ~30%; images only load when scrolled into viewport".This prevents loading 15-20 images on page mount (potential 10-20MB uncompressed PNGs) which could exhaust mobile device memory or bandwidth. Lazy loading defers image fetch until scroll. WebP compression reduces payload.
Correct RULE 0 resource exhaustion mitigation.
[RULE 1] CLEAN: Responsive design coverage meets mobile + desktop requirement
M1 acceptance criteria includes "Desktop: TOC is sticky sidebar on left, content scrolls on right" and "Mobile: TOC is collapsible accordion above content". M2/M3 acceptance criteria both include "Responsive layout: content readable at 320px, 768px, 1920px".
Issue acceptance criteria requires "Responsive design: works on mobile (320px, 768px) and desktop (1920px)". Plan milestones cover all three breakpoints.
CLAUDE.md mobile + desktop requirement: "ALL features MUST be implemented and tested on BOTH mobile and desktop." Plan meets requirement.
No RULE 1 violations.
[RULE 1] CLEAN: Dark mode support via existing ThemeProvider pattern
Constraints list "Dark mode support via existing ThemeProvider (doc-derived: ThemeContext.tsx pattern)". M2 requirements include "Dark mode compatible styling using Tailwind dark: prefixes and MUI theme".
App.tsx diff wraps GuidePage in ThemeProvider (same as HomePage wrapper at lines 629-636). This provides MUI theme context and Tailwind dark mode class toggling via existing pattern.
No RULE 1 violations. Dark mode integration correct.
Considered But Not Flagged
frontend/src/pages/__tests__/GuidePage.test.tsxwhich follows existing test pattern fromfrontend/src/features/dashboard/components/__tests__/DashboardScreen.test.tsx. Correct location.useAuth0orisAuthenticatedconditional). Issue acceptance criteria: "/guide route accessible without authentication". Correct - public route like HomePage.frontend/public/docs/v2026-01-03.pdf". CLAUDE.md code completion criteria: "Old code is deleted". Plan includes cleanup step.scroll-behavior: smoothCSS or JavaScriptscrollIntoView({ behavior: 'smooth' })- trivial implementation, no RULE violations.frontend/src/pages/GuidePage/GuidePage.tsxnot "guide files"). Follows planning best practices.Verdict
PASS
All code diffs follow existing codebase patterns for routing, navigation, lazy loading, and styling. No RULE 0 (production reliability) or RULE 1 (project conformance) violations detected. RULE 2 (structural quality) is sound - shared components prevent duplication, individual section files prevent god objects. One SUGGESTION for M5 HamburgerDrawer guard implementation clarity (not a blocker - reasoning is in Decision Log, note mentions the guard, just missing explicit diff).
Mobile + desktop responsive design covered (320px, 768px, 1920px). Dark mode via ThemeProvider. Touch targets >= 44px. Lazy loading prevents resource exhaustion. Tests deferred to M5 with valid reason. No unhandled error paths.
Recommended action: Plan is approved for implementation. Optional: Address SUGGESTION for HamburgerDrawer guard diff block to eliminate implementation ambiguity.
Next: QR plan-docs review
Milestone: M5 Navigation Integration and Tests
Phase: Execution | Agent: Developer | Status: PASS
Completed
window.location.hrefguard (bypasses Zustand navigation since/guideis outside/garage/*shell)frontend/src/pages/__tests__/GuidePage.test.tsx:frontend/public/docs/v2026-01-03.pdfQuality Checks
Commit
197aedafeat: add guide navigation integration and tests (refs #203)Verdict: PASS | Next: M6 Documentation
Milestone: M6 Documentation
Phase: Execution | Agent: Developer | Status: PASS
Completed
frontend/src/pages/GuidePage/CLAUDE.mdwith:frontend/src/pages/CLAUDE.mdindex referencing GuidePage/, HomePage/, admin/, and page-level filesCommit
b047199docs: add GuidePage documentation (refs #203)Overall Milestone Status
864da556196ebf6196ebf197aedab047199Verdict: PASS | Next: M4 screenshots (user responsibility), then PR