Skip to content

Commit d5ed15c

Browse files
Merge pull request #40 from programmerShinobi/feat/landing-page
feat: Home landing page + genuinely-mobile experience (prototype match)
2 parents 661205f + 2603119 commit d5ed15c

23 files changed

Lines changed: 1441 additions & 24 deletions

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,46 @@ The decision **model** carries its own version, recorded in the
99

1010
## [Unreleased]
1111

12+
### Added (Genuinely-mobile experience — 2026-07-14)
13+
14+
- **A real mobile UI for the whole app** (plan: [mobile-experience-plan.md](docs/03-blueprint/mobile-experience-plan.md),
15+
written *before* implementation) — not a shrunk desktop layout. On phones (≤640px):
16+
- **Fixed bottom tab bar** (`MobileChrome`) — **Home · Advisor · Insights · More** (thumb-zone
17+
navigation); the desktop top-nav hides.
18+
- **Settings sheet** (slides up from "More") with **Theme · Language · Reading mode** as
19+
first-class segmented controls — so all three product toggles are reachable on mobile (the header
20+
cluster is hidden there). `useTheme` is lifted to `App` and shared, so header + sheet never
21+
desync.
22+
- **Sticky bottom primary action** on the Advisor (`AdvisorMobileBar`) — a contextual
23+
**"Get your plan" → "Save & share"** button (the "primary button at the bottom" pattern) that
24+
scrolls the one-page flow forward via an `IntersectionObserver`. It's navigation sugar; the flow,
25+
steps, and model are unchanged.
26+
- Decluttered mobile header (brand + Guide); safe-area insets (`viewport-fit=cover`,
27+
`env(safe-area-inset-bottom)`); content padding clears the fixed bars.
28+
- Desktop (≥641px) is unchanged. Both themes verified. e2e updated for the mobile chrome; budget
29+
total JS 193.2/200 kB, CSS 22.9/25 kB.
30+
31+
### Added (Home landing page — 2026-07-13)
32+
33+
- **A proper Home landing page** (`LandingView` + `HeroRadar`), now the **default view**, mirroring
34+
the composition of the approved [`prototype-v2/preview-modern.html`](docs/03-blueprint/prototype-v2/preview-modern.html)
35+
— closing the gap between the prototype's *layout* and the app (the Aurora reskin had applied the
36+
prototype's *style* but kept the tool-first structure).
37+
- **Hero:** gradient headline, eyebrow badge, lede, primary/secondary CTAs, hero-meta stats, and
38+
the decorative 5-dimension **radar motif** with floating chips (static brand art, distinct from
39+
the Advisor's functional radar).
40+
- **Pattern Library bento:** four **real** architectures from the frozen model (Event-driven,
41+
Modular Monolith, Serverless, CQRS — names from `dimensions.ts`, blurbs bilingual in the dict),
42+
each **deep-linking into its Insights Catalog page**.
43+
- **How it works:** the three real Advisor steps.
44+
- Fully **bilingual** (EN/ID via the dict), **responsive** (radar-first on mobile, bento reflows),
45+
reveal-on-scroll (reduced-motion safe), and pointer-glow cards — all reusing the Aurora tokens.
46+
- Top nav is now **Home · Advisor · Insights** (Home default). A shared `#s=…` link still opens the
47+
Advisor directly. CTAs drive the Advisor; "All architectures" opens Insights.
48+
- Kept light: the landing uses `DIMENSIONS` + dict strings (no `readerContent` pulled into the
49+
initial bundle); initial JS+CSS 134.1 kB, total JS 191.9 kB — within budget. +3 unit tests
50+
(`LandingView.test.tsx`); e2e updated for the new default view. All gates green.
51+
1252
### Added (PWA resilience polish — 2026-07-13)
1353

1454
- **Stale-chunk auto-recovery.** A tab left open across a deploy could 404 on an old lazy chunk

DECISIONS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,16 @@ Appendix A). Direction chosen with the maintainer: **client-rendered first, Wave
196196
SPA): the vanilla rewrite, the multi-file `@layer`/`js/` split + `ROOT` depth helper + per-page
197197
anti-FOUC script, cross-document View Transitions, a hand-rolled service worker/manifest, and the
198198
`.card`/`.nav` class rename. PWA remains an optional future follow-up.
199+
- **The prototype's *layout* now ships too — as a Home landing (2026-07-13, FR-SHELL-11).** The
200+
reskin first applied only the prototype's *style*; a follow-up added a real **Home landing view**
201+
(`LandingView` + `HeroRadar`) mirroring the prototype's composition (hero + Pattern Library +
202+
how-it-works). It is the **default** view (top nav Home · Advisor · Insights). Reconciliations vs
203+
the prototype (a marketing mockup): the Pattern Library features **real** model architectures
204+
(deep-linking into Insights), copy is **bilingual** via the dict, and the decorative hero radar is
205+
a *separate* static motif — **not** the Advisor's functional 12-attribute radar (M13 discipline:
206+
one radar visual system, two uses). The landing deliberately avoids importing `readerContent`
207+
(uses `DIMENSIONS` + dict strings) so the now-default view doesn't pull the content layer into the
208+
initial-JS budget. A shared `#s=…` link sets `aa.main=advisor` pre-render so it opens the Advisor.
199209

200210
## PWA — installable + offline (2026-07)
201211

docs/02-requirement-analysis/software-requirements-specification.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
| 1.3 | 2026-07-06 | **Insights holistic coverage + English-first**: FR-LEARN-6 extended to all four sections (Catalog/Playbook/Review/Library) with distinct structured lenses and a per-page lens navigation (the Catalog → Playbook → Review → Library knowledge journey) for every one of the 21 architectures; FR-SHELL-2 default language flipped to **EN** (toggle unchanged); FR-LEARN-2 content gate now requires **at least the `en` version**. See [DECISIONS.md](../../DECISIONS.md). No requirements removed |
3333
| 1.4 | 2026-07-06 | **Insights Wave C + SEO**: added FR-LEARN-8 (Roadmap — guided learning paths), FR-LEARN-9 (Academy — client-side quiz modules), FR-LEARN-10 (Lab — hypothesis experiments that load prepared scenarios into the live engine), and FR-SEO-1 (build-time sitemap/robots/JSON-LD + static crawlable article snapshots; SSG-lite — the SPA architecture is unchanged, superseding "SSG deferred" for discoverability). §3.10 updated to seven sections. No requirements removed |
3434
| 1.5 | 2026-07-06 | **Wave C holistic parity**: FR-LEARN-8/9/10 strengthened — the Roadmap, Academy, and Lab must each cover **all 21 architectures** (every architecture in ≥1 learning path, reviewed by ≥1 quiz question, and in play in ≥1 experiment), matching the four lenses' 21×4 parity so Wave C can never mismatch the lens coverage; enforced by per-section unit tests. No requirements removed |
35+
| 1.6 | 2026-07-13 | **Home landing page** (FR-SHELL-11): added a default Home view mirroring the approved prototype composition (hero + real Pattern Library + how-it-works), bilingual/responsive, CTAs into the Advisor and deep-links into Insights; top nav becomes Home · Advisor · Insights. Part of the "Aurora Slate" visual programme (ADR-009). No requirements removed |
3536

3637
---
3738

@@ -216,6 +217,7 @@ v1.0:
216217
| FR-SHELL-8 | Provide a **command palette and keyboard shortcuts** covering all core actions. | Should | UI/UX Playbook Task 2 | T |
217218
| FR-SHELL-9 | Provide an in-app **Manual / Guide** that explains the tool end to end — including the full scoring calculation — with a **live worked example** computed from the user's current inputs. | Should | v1.1 enhancement | D |
218219
| FR-SHELL-10 | Extend the in-app **Manual / Guide** into a genuine deep-dive that, alongside the scoring walkthrough, **explains every architecture the Advisor evaluates** (see §3.9). The Manual is **lazy-loaded** on demand. | Should | v1.1 enhancement | T |
220+
| FR-SHELL-11 | Provide a **Home landing view** — the **default** top-nav destination (Home · Advisor · Insights) — that mirrors the approved prototype composition: a hero (headline, CTAs, key stats, decorative radar motif), a **Pattern Library** featuring **real** architectures from the frozen model (each deep-linking into its Insights Catalog), and a **how-it-works** summary of the Advisor flow. Bilingual, responsive, and reveal-on-scroll (reduced-motion safe). CTAs open the Advisor; a shared `#s=…` link bypasses Home and opens the Advisor directly. | Should | 2026-07 landing | T |
219221

220222
### 3.2 Step 1 — Project Factors
221223

docs/03-blueprint/design-specification.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
| 0.9 | 2026-07-04 | **Responsive UI redesign**: added the `--aa-*` token layer + base classes (§6.1 — fluid spacing/type, soft elevation, 44 px touch targets, global focus ring, canonical breakpoints ≤640/641–1024/≥1025). Supersedes prototype-exact *look* (copy/features/model unchanged — see DECISIONS.md); Advisor & Insights views restyled responsive/card-based. No logic or data changes |
2929
| 1.0 | 2026-07-12 | **"Aurora Slate" visual direction (ADR-009)** — approved reskin *in place* of the existing React app (aurora palette + accent gradient + Space Grotesk display face, two signatures: aurora background + the existing radar restyled). The blueprint's proposed vanilla/MPA rewrite is **rejected** (ADR-003/004 stand — engine, model, seven-section Insights, and 99 tests preserved). Visual source of truth committed to [`prototype-v2/preview-modern.html`](prototype-v2/preview-modern.html). Implementation is token-value remapping, not a rewrite |
3030
| 1.1 | 2026-07-13 | **PWA — installable + offline (ADR-010)** via `vite-plugin-pwa` (Workbox `generateSW`, `autoUpdate`); manifest + generated service worker, app shell precached / fonts runtime-cached / SEO snapshots excluded, subpath-safe scope. No app-logic or model changes |
31+
| 1.2 | 2026-07-13 | **Home landing page (FR-SHELL-11)** — new default view (`LandingView` + `HeroRadar`) mirroring the prototype composition (hero + real Pattern Library + how-it-works); top nav Home · Advisor · Insights; CTAs → Advisor, pattern cards deep-link → Insights Catalog. Part of ADR-009 (Aurora Slate). Landing kept out of `readerContent` to protect the initial-JS budget. No model changes |
32+
| 1.3 | 2026-07-14 | **Genuinely-mobile experience** ([mobile-experience-plan.md](mobile-experience-plan.md)) — phone-tier bottom tab bar (`MobileChrome`) + settings sheet (theme/language/reading-mode) + Advisor sticky bottom primary action (`AdvisorMobileBar`); `useTheme` lifted to `App` and shared; desktop unchanged. Presentation/navigation only — no flow or model change |
3133

3234
---
3335

@@ -121,7 +123,7 @@ src/
121123
├── lib/ scoring · sensitivity · antiPatternEngine · adr · report
122124
│ c4 · urlState · customConfig · content · frontmatter · markdown
123125
├── hooks/ usePersistedState · useUrlSyncedState
124-
└── components/ Header · ManualBook (Guide + architecture explanations, lazy) · Disclaimer · ModeToggle · PresetBar · FactorGroup …
126+
└── components/ Header · LandingView + HeroRadar (Home landing, default) · AuroraBackground · ManualBook (Guide, lazy) · Disclaimer · ModeToggle · PresetBar · FactorGroup …
125127
QaWeightChart · DimensionResults · RadarTradeoff · ContributionTable
126128
ComparisonMode · SensitivityCard · RiskRegister · AntiPatternAlerts
127129
FitnessFunctions · MigrationPath · MethodologyPanel · ReportPreview …
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Mobile Experience Plan — Architecture Advisor
2+
3+
**Status:** **Implemented** 2026-07-14 (written 2026-07-13, before implementation, per the maintainer's docs-first rule)
4+
**Owner:** Faqih Pratama Muhti · **Relates to:** ADR-009 (Aurora Slate), FR-SHELL-1/2/3/11, design-spec §6.1, [`prototype-v2/preview-modern.html`](prototype-v2/preview-modern.html)
5+
6+
## 1. Goal
7+
8+
Make the **core Advisor and Insights** (and the Home landing) feel like a **genuinely mobile app** on
9+
phones — not a desktop layout squeezed small — while keeping the exact decision-model flow and all
10+
logic unchanged. Concretely, on phones (≤640px):
11+
12+
- A **fixed bottom tab bar** for primary navigation (thumb-zone), the mobile convention — replacing
13+
the top tab row that currently wraps.
14+
- A **sticky bottom primary action** on the Advisor (the "main button at the bottom" pattern) that
15+
drives the process flow (factors → priorities → plan → save).
16+
- **First-class, reachable controls** for the three product toggles — **theme (light/dark)**,
17+
**language (EN/ID)**, and **Guided/Expert** — surfaced in a mobile **settings sheet** (the header
18+
control cluster is cramped on phones).
19+
- Mobile-native spacing/typography/hit-targets and safe-area handling.
20+
21+
Desktop (≥641px) is unchanged (top nav + header controls as today).
22+
23+
## 2. Non-negotiables
24+
25+
- **No change to the flow or the model.** Same four steps, same scoring, same content — only the
26+
*presentation/navigation* changes on phones. All model/content guards and the 102 unit + 14 e2e
27+
tests stay green (e2e updated for the new mobile chrome where needed).
28+
- **No new runtime dependency.** Token-based (`--color-*`, `--aa-*`), `aa-`/`lp-` class conventions,
29+
no `!important`, reuse the existing `<dialog>`-based sheet pattern if present or a small one.
30+
- **Accessibility:** bottom-nav items ≥44px, `aria-current` on the active tab, `env(safe-area-inset-*)`,
31+
visible focus, `prefers-reduced-motion` respected, WCAG AA in both themes (axe-gated).
32+
- **Budget:** stay within the initial-JS/CSS and total-JS budgets (mobile chrome is small CSS + a
33+
little JS).
34+
35+
## 3. Components & changes (planned)
36+
37+
| Area | Change |
38+
|---|---|
39+
| **`MobileTabBar`** (new) | Fixed bottom bar, phone-only (`aa-only-phone`), 3 tabs **Home · Advisor · Insights** (icon + label), `aria-current`, safe-area padding. Drives the same `mainView` state. The top tab row gets `aa-hide-phone`. |
40+
| **`MobileSettingsSheet`** (new) | A bottom sheet (slide-up) holding **Theme**, **Language**, **Guided/Expert** as large, labelled controls. Opened from a compact header button (gear) shown on phones. Closes on backdrop/Esc; focus-trapped. |
41+
| **Header** | On phones, collapse the control cluster (⌘K/?/save already hidden via `aa-hide-phone`); keep brand + theme quick-toggle + the settings (gear) button. Desktop unchanged. |
42+
| **`AdvisorMobileBar`** (new) | Phone-only sticky bottom action bar (above the tab bar): a **contextual primary button** that advances the flow — *See what matters**Get your plan**Save & share* — by scrolling to that section (the Advisor stays one page; the bar is the mobile "next"). Uses the existing StepTracker sections as anchors. |
43+
| **Advisor layout** | Content gets bottom padding = `tabbar + actionbar + safe-area` so nothing hides behind the fixed chrome. Cards/inputs already responsive; verify one-column, comfortable tap targets. |
44+
| **Insights layout** | Already card-based/stacks; ensure bottom padding for the tab bar and that section/detail navigation is thumb-reachable. |
45+
| **Landing** | Already responsive (radar-first, reflowing bento); add bottom padding for the tab bar; CTAs unaffected. |
46+
| **CSS** | New `aa-only-phone` / `aa-hide-phone` usage; `.aa-tabbar`, `.aa-mobile-actionbar`, `.aa-sheet` under the ≤640 breakpoint; all token-based. |
47+
48+
## 4. Interaction / flow (unchanged semantics)
49+
50+
- **Navigation:** bottom tab bar switches `mainView` exactly like the top tabs (Home/Advisor/Insights);
51+
a shared `#s=…` link still opens the Advisor.
52+
- **Advisor bottom action (contextual):**
53+
1. On the Factors area → primary button **"See what matters"** scrolls to Priorities.
54+
2. Past Priorities → **"Get your plan"** scrolls to the Recommendation.
55+
3. At the plan → **"Save & share"** opens the export/share.
56+
The determination is by scroll position / which section is in view — no state-machine change; the
57+
single-page flow is preserved (this is navigation sugar, not a wizard rewrite).
58+
- **Toggles:** the settings sheet mutates the same `theme` / `lang` / `mode` state used everywhere;
59+
changes apply instantly and persist (localStorage), identical to the header controls.
60+
61+
## 5. Breakpoint & tokens
62+
63+
- Phone tier: **≤640px** (canonical, design-spec §6.1). Bottom nav + action bar + settings sheet are
64+
phone-only; ≥641px keeps the current top-nav desktop layout.
65+
- Safe area: `padding-bottom: env(safe-area-inset-bottom)` on the fixed bars; the viewport already
66+
uses `viewport-fit=cover`? (verify/set in index.html).
67+
68+
## 6. Testing (planned)
69+
70+
- **Unit:** a small render test for `MobileSettingsSheet` (toggles call the right setters) and that
71+
the bottom tab bar switches views.
72+
- **e2e (`responsive.spec.ts`):** at the 360px viewport, assert the bottom tab bar is visible and
73+
switches Home/Advisor/Insights; the settings sheet opens and toggles theme/lang/mode; no horizontal
74+
scroll; the Advisor bottom action advances the flow. Desktop specs unchanged.
75+
- **a11y:** axe on the mobile chrome (both themes); bottom-nav roles/`aria-current`; focus trap in the
76+
sheet.
77+
78+
## 7. Rollout
79+
80+
Incremental, each step gate-green: (1) bottom tab bar + hide top nav on phones; (2) settings sheet +
81+
header gear; (3) Advisor sticky bottom action; (4) padding/polish for Insights & Landing; (5) e2e +
82+
a11y + screenshots (both themes), docs, PR. Documented in CHANGELOG + design-spec on completion; this
83+
plan is the pre-implementation record.
84+
85+
## 8. Implementation notes (as built, 2026-07-14)
86+
87+
- **`MobileChrome`** renders the bottom tab bar (**Home · Advisor · Insights · More**) and the
88+
settings sheet; the "More" tab opens the sheet with **Theme · Language · Reading mode** as
89+
segmented controls. `useTheme` was **lifted to `App`** and passed to both the header and
90+
`MobileChrome` (they share one theme state — `usePersistedState` does not sync across instances).
91+
- **`AdvisorMobileBar`** is the phone-only sticky primary action; an `IntersectionObserver` on
92+
`#adv-plan` flips it from **Get your plan****Save & share** as the recommendation reaches the
93+
viewport's middle band. Anchors `#adv-plan` / `#adv-save` added to the Advisor sections.
94+
- The desktop **top nav** and the header **theme/language/mode cluster** move to CSS classes
95+
(`.aa-topnav`, `.aa-desktop-controls`) that hide ≤640px — avoiding the inline-`display` footgun
96+
that beats `aa-hide-phone` (DECISIONS.md). Content clears the fixed bars via `.aa-page` /
97+
`.aa-page.has-actionbar` bottom padding + `env(safe-area-inset-bottom)`; `index.html` gained
98+
`viewport-fit=cover`.
99+
- **Tests:** e2e `responsive.spec.ts` updated to assert the bottom bar + settings sheet on phones;
100+
the two App-level a11y unit tests select the first nav match (top nav + bottom bar both render
101+
under `css:false`). Desktop specs unchanged. All gates green; budget total JS 193.2/200 kB.

e2e/a11y.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ test('no WCAG A/AA violations incl. color-contrast (Guided, dark theme)', async
2525
test('no WCAG A/AA violations incl. color-contrast (Expert mode + light theme)', async ({ page }) => {
2626
await page.goto(APP);
2727
await page.getByRole('button', { name: 'EN', exact: true }).click();
28+
await page.getByRole('button', { name: 'Advisor', exact: true }).click(); // default view is now Home
2829
await page.getByRole('button', { name: 'Expert', exact: true }).click();
2930
await page.getByRole('button', { name: 'Toggle theme' }).click(); // → light
3031
await page.getByRole('button', { name: /Adjust weights/ }).click(); // mount the override panel
@@ -78,5 +79,6 @@ test('controls are keyboard-operable', async ({ page }) => {
7879
// which renames the Indonesian preset chips to their English labels)
7980
await page.getByRole('button', { name: 'EN', exact: true }).focus();
8081
await page.keyboard.press('Enter');
82+
await page.getByRole('button', { name: 'Advisor', exact: true }).click(); // default view is now Home
8183
await expect(page.getByRole('button', { name: 'Busy online shop' })).toBeVisible();
8284
});

0 commit comments

Comments
 (0)