Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The Jekyll presentation layer (`_layouts/`, `_includes/`, `_sass/`, `assets/`) r

## Validation and documentation upkeep

Node 20 is the CI runtime. From `web/`, use `npm ci` for lockfile installs, `npm run dev` for development and `npm run build` for static export. Prebuild runs the design guard, the image-reference check and focused calendar tests; the build validates TypeScript and generates redirects. `npm run test:calendar` uses Node's built-in test runner. There is no broader application test suite or repository-wide lint command.
Node 20 is the CI runtime. From `web/`, use `npm ci` for lockfile installs, `npm run dev` for development and `npm run build` for static export. Prebuild runs the design guard, the image-reference check and focused calendar/content-loader tests; the build validates TypeScript, generates redirects and checks the exported 404 styles and Home social-image URL. `npm run test:calendar` uses Node's built-in test runner. There is no broader application test suite or repository-wide lint command.

For affected UI, inspect fresh 1440px desktop and 375px mobile screenshots, both themes and relevant intermediate widths. Check links, images, keyboard focus, mobile menu/Escape, theme persistence and relevant calendar controls/details/dates. Use targeted accessibility scans with manual review; record incomplete findings honestly. Judge the approved design by screenshots, not legacy CSS parity.

Expand Down
16 changes: 9 additions & 7 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Cambridge AI Builder Club design rules

Last updated: 11 October 2026. Applies to all production Next.js routes and the design playground.
Last updated: 19 October 2026. Applies to all production Next.js routes and the design playground.

## Maintain this document first

Expand Down Expand Up @@ -42,7 +42,7 @@ For a fix that preserves the rules, add a change record explaining the regressio
| Secondary text | `#5F5E57` | `#C4C2B8` |
| Rule/border | `#D0CEC5` | `#45453F` |

- Warm Paper is the default. The appearance toggle persists the user's choice across navigation and reloads. Theme changes must not tint image/logo files.
- Warm Paper is the default. The appearance toggle persists the user's choice across navigation and reloads. Theme changes must not tint image/logo files. The saved surface is restored before first paint by a blocking inline script in the document head that sets `data-surface` on `<html>`; the toggle updates the same attribute. Never restore the theme in a post-paint effect only. The toggle's accessible name describes the action (`Switch to … appearance`), not the current state.
- Use Georgia/Times New Roman for editorial headings and Arial/Helvetica for body, controls and publication dates. Omit decorative monospaced captions and eyebrow labels from production and matching playground content. Local review controls also use the regular font. These are local font choices, not a claim about Claude's proprietary typography.
- Retain generous whitespace, warm surfaces, thin borders, orange framing and clear section hierarchy. Avoid introducing unrelated gradients, glass effects or a new font system without an explicit design decision.
- Share tokens and general styles in `web/styles/claude.css`; production page styles live in `web/styles/site.css`. Avoid duplicate component-specific palettes and scattered inline visual settings.
Expand All @@ -65,12 +65,13 @@ For a fix that preserves the rules, add a change record explaining the regressio

## Navigation and interactions

- Main navigation is About, Explore, Projects, Calendar, Community and Journal, with a persistent Join action. Keep About in the footer as well. Preserve the existing destination URLs and active-page indication. Production navigation uses the existing menu pattern at 1100px and below so the expanded set of destinations never collides with the logo or appearance control.
- Main navigation is About, Explore, Projects, Calendar, Community and Journal, with a persistent Join action. The set is content-driven: `web/content/data/menus.yml` `main` entries render in weight order, and entries marked `header: false` (Committees, Contact) stay out of the header while remaining valid destinations. The footer link set likewise comes from the `footer` list in `menus.yml`. Keep About in the footer as well. Preserve the existing destination URLs and active-page indication. Production navigation uses the existing menu pattern at 1100px and below so the expanded set of destinations never collides with the logo or appearance control.
- While the mobile menu is open, the page content and footer are inert to keyboard and pointer focus, the menu closes on outside pointer down and on focus leaving the header, and Escape still returns focus to the toggle. Resizing above the mobile-menu breakpoint dismisses it and restores page interaction.
- Logo navigation returns home. Internal destinations go through `url()`; canonical URLs use `absoluteUrl()`.
- Join, Discord and application actions use their real configured URLs. External tabs use `rel="noopener noreferrer"`. Keep visible action labels explicit about their purpose.
- A whole activity/member/story card is one clear link. Avoid nested links/buttons, duplicate tab stops and decorative elements that intercept clicks.
- A whole activity/member/story card is one clear link with a concise accessible name (the card title via `aria-label`); the long description and pseudo-link text inside are not read as part of the link name. Keep card headings, summaries, roles and publication dates available to screen-reader browsing. Avoid nested links/buttons, duplicate tab stops and decorative elements that intercept clicks.
- Mobile navigation opens from a labeled toggle, exposes its expanded state, closes on Escape and navigation, and returns focus to the toggle on Escape. It must not cover or block controls when closed.
- Filters show the current selection with a filled surface and text emphasis, retain context and offer an understandable empty state. Keep hover and keyboard feedback visible in both themes. Do not make filtering dependent on hover.
- Filters use radio semantics (`radiogroup`/`radio` with `aria-checked`), support arrow-key selection with a single roving tab stop, show the current selection with a filled surface and text emphasis, retain context and offer an understandable empty state. Only the result count is announced to assistive technology on change, not the whole card grid. Keep hover and keyboard feedback visible in both themes. Do not make filtering dependent on hover.
- Preserve standard browser Back behavior, link destinations and anchor navigation. Do not hijack scrolling, add autoplay video or make interactions depend on a pointer.

## Content and page behavior
Expand All @@ -87,9 +88,10 @@ For a fix that preserves the rules, add a change record explaining the regressio
- Calendar is an ongoing main page, never an archive-only destination. Its existing data, dates, times, venues and cancellation records remain intact unless the owner requests a schedule change.
- Do not add a summary row above the calendar grid: omit total/month session counts and the redundant `Club Calendar` badge. Retain month navigation, session names, details and the session list.
- Calendar opens on the current Cambridge date (Europe/London) at runtime, independently of the static build date or available event records. Previous/next controls move through consecutive months, including empty months and year boundaries; Current month returns to the live month. Keep the selected event within the visible month, with useful empty states. Default to the nearest event today or in the future; otherwise select the most recent past event. Prefer non-cancelled records for automatic selection, retaining explicit user selections and cancellation labels. Empty months have no selection. Omit the redundant Select an event for details sentence; retain only the functional mobile scrolling hint. Calendar weeks start on Monday, mark today separately from the selected event, and show session names with explicit cancelled labels. Each session is individually selectable, including multiple events on one date. Pair the grid with selected details first and a compact chronological event list beneath them in one coordinated layout. Long lists scroll in a keyboard-reachable region with a visible hint; show type and status separately. Multi-day events have a dated record for each day, retaining their daily time and venue.
- On narrow screens, the calendar dates region may scroll horizontally with a visible hint; the document itself must not overflow. Keep names readable instead of hiding them or replacing them with counts. The region must be keyboard reachable.
- On narrow screens, the calendar dates region may scroll horizontally with a visible hint; the document itself must not overflow. Keep names readable instead of hiding them or replacing them with counts. The region is keyboard reachable only while it can actually scroll (no dead tab stop at wide widths). The calendar switches to its single-column layout at 1000px and below so the grid never squeezes event names into unreadable slivers at intermediate widths. Changing the month announces the new month label; the event detail region announces only after an explicit user selection, not on automatic defaults. Without JavaScript the calendar shows a static notice instead of a perpetual loading message.
- Unknown URLs render a branded 404 page (`web/app/not-found.tsx`) inside the standard shell with a link home, never the framework default page. The common application root layout supplies its document and styles; the playground retains its own local surface controls.
- Keep the Welcome section About link available at desktop, intermediate and mobile widths; place it below the copy when space is limited.
- Reading pages use one primary heading, a comfortable prose width and useful return links. Preserve existing routes, canonical metadata, sitemap/robots and legacy redirect stubs.
- Reading pages use one primary heading, a comfortable prose width and useful return links. Preserve existing routes, canonical metadata, sitemap/robots and legacy redirect stubs. Every index and detail page carries a meta description (page front matter or the entry's first paragraph). Member detail pages whose records set `promoted: false` keep their URLs but stay out of the sitemap until they are listed on Community.

## Accessibility and responsive acceptance

Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ The reports below retain their original QA results, screenshots and limitations.
| [Label/hero QA](design/remove-labels-qa.md) | Final coordinated hero and earlier superseded collaboration revisions |
| [Calendar QA](design/calendar-qa.md) | Runtime London date, consecutive navigation, fair records, default selection and manual contrast review |
| [Page-title QA](design/page-titles-qa.md) | Shared plain h1 typography, natural wrapping and route coverage |
| [Code-quality and UX follow-up](design/code-quality-review-2026-10-19.md) | Review of the inherited branch, corrected regressions and dated local verification |

Asset provenance: [official Claude sources](design/claude-brand-sources.md), [authored activity illustrations](design/activity-artwork.md), [unused generated concept](design/generated-artwork.md). Programme/asset-source checks retain their original dates; reverify factual claims before changing or republishing them. Team portrait framing, optimization and publication are recorded in the [design change record](design/change-record.md#9-october-2026--publication-receipt-for-the-team-portrait-change) with evidence in [the portrait folder](design/team-portraits-2026-10-09/). The inactive compact-card portrait variant still needs a design decision before use.

Expand Down
22 changes: 22 additions & 0 deletions docs/design/change-record.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,25 @@ Each entry describes its own review checkpoint. Later revisions supersede earlie

- Owner tested the port-4102 preview and asked to merge; the change squash-merged into `main` as [PR #32](https://github.com/Cambridge-AI-Build-Club/Cambridge-AI-Build-Club.github.io/pull/32) at `2f2a27f`. The PR `build` check passed and the `Deploy Next.js site to Pages` run ([38230306949](https://github.com/Cambridge-AI-Build-Club/Cambridge-AI-Build-Club.github.io/actions/runs/38230306949)) completed successfully on the merge commit.
- Live checks against the organisation root with cache-busting queries: Home, About, Community, Calendar, Committees and the playground returned HTTP 200; the shared recruitment summary renders on Committees; the playground payload carries the shared copy (`Stay curious. Keep building.`); `/images/team/andrew_choi.jpg` and the retained `/images/social/facebook.svg` served; the `/CUABC-Web/` legacy redirect stub resolves.

### 16 October 2026 — code quality and UI/UX review fixes

- Request: implement the full set of findings from a two-part codebase review (code quality and UI/UX), keeping the approved design intact.
- Surfaces: content loaders and build tooling (`web/lib/*`, `web/scripts/*`), shared shell (`SiteFrame`, `SiteDocument`, `Shell`), calendar, activity/member/story cards, filters, navigation and footer data (`menus.yml`), activity card labels (`features.json`), interface copy (`ui.yml`), page metadata, sitemap, the calendar intermediate-width breakpoint, and a new branded 404 route.
- Implementation intent:
- Code quality: memoize all build-time content loaders (content is immutable during a build); add path-contextual error reporting and required-key shape assertions at the loader boundary; type the page/collection front matter actually consumed instead of `String()`/`as` casts; remove dead helpers (`markdownifyStripTruncate`, `excerptHtmlTruncate`, `truncate`); guard the collection sort comparator against non-numeric weights; share one `SiteData` type between `lib/site.ts` and `SiteFrame`; pair activity artwork via a prebuilt map with the plural display title supplying the card link label; validate calendar statuses at load; scan `styles/` (including `.css`) in the image-reference check; harden the preview server's path resolution; consolidate the thirteen identical root layouts into one shared route-group layout; extract a shared `JournalCard`; reformat single-line page JSX for readability.
- UI/UX: restore the saved theme before first paint via a blocking inline head script (ending the per-navigation flash, since every navigation is a full page load); add a branded `not-found.tsx`; move the calendar single-column breakpoint from 900px to 1000px; make the open mobile menu inert the content/footer and close on outside pointer down and focus leaving the header; give whole-card links concise `aria-label` names; switch activity filters to radio semantics and announce only the result count; make the calendar dates region keyboard-focusable only when it can scroll; keep `promoted: false` member pages out of the sitemap; add meta descriptions to member/activity/story detail and Contact; label the theme toggle with the action it performs; source header/footer links from `menus.yml` with a `header: false` opt-out; move "open seats", calendar aria labels and the card link label pattern into `ui.yml`; add a no-JavaScript calendar notice; announce event details only after explicit selection. The desktop brand mark keeps its approved cropped presentation; swapping in a wide-format logo asset is recorded as an open item requiring an owner artwork decision.
- Acceptance: `npm run build` (design guard, extended image-reference check, calendar tests, TypeScript, static export) passes; rendered copy unchanged except the items above; fresh 1440px/375px screenshots in both themes plus the 761–1000px calendar range; keyboard walk of the mobile menu, filters and calendar; no console, hydration or overflow regressions; the 404 route renders the site chrome.
- Status at the recorded review: implemented and verified locally. Design guard, the extended image-reference check (now including `styles/*.css`), eleven calendar tests, TypeScript and the static export passed (25 routes plus the branded `/_not-found`, 21 legacy redirect stubs). Export spot-checks: every page HTML carries the pre-paint surface script and `data-surface="paper"` default; `404.html` renders the site chrome; the sitemap excludes the four `promoted: false` member pages; member, activity, story and Contact pages emit meta descriptions; the events listing uses `radiogroup` semantics. The port-4102 preview returns 200 for all fifteen routes checked, 404 with the branded page for unknown URLs, and resolves the `/CUABC-Web/` redirect stubs; a Windows path-resolution regression introduced in the serve.mjs hardening was caught by this smoke check and fixed before review. Screenshot review of both themes and the 761-1000px calendar range is pending on the owner preview. Not published.
- Open item: the desktop header logo still centre-crops the square source image at render time; replacing it with a true wide-format asset needs an owner artwork decision.

### 19 October 2026 — follow-up review of the code-quality and UX branch

- Request: review commits `f627812` and `47792a1`, improve concrete findings, prepare a PR and merge after the required implementation preview approval.
- Intended fixes: preserve live content editing in development while retaining production build caches; dismiss the mobile menu above 1100px so content cannot remain inert; complete radio-filter keyboard navigation in production and the playground; keep card headings, summaries, roles and dates exposed to screen readers while retaining concise link names; acknowledge the intentional pre-paint theme attribute during hydration; avoid repeating the deployment base path in the Home social image URL.
- Acceptance: full static build, focused regression checks, fresh 1440px and 375px screenshots in both themes and intermediate calendar widths; manual menu/resize/Escape, filters, theme persistence, calendar selection/empty months, images, links and targeted accessibility checks. CI, owner approval and publication are separate gates.
- Status: review in progress; no verification or publication claimed yet.

- Additional reproduced finding: the inherited multi-root layout export emits the branded 404 without any stylesheet, giving an unstyled 600px logo and mobile overflow. Fix intent recorded before implementation: move SiteDocument to a real application root layout, let the 404 inherit it, and scope the saved production theme to `.lab.site` so the playground keeps independent surface controls.

- Local result on 19 October: full build, eleven calendar tests, three content-loader tests and two post-export checks passed. Browser checks captured 36 screenshots; 24 targeted axe scans reported no violations, with mobile-calendar contrast incompletes retained honestly. Menu/resize/Escape, radio filters, theme persistence, calendar selection/empty months/scrolling and no-JavaScript fallback passed. See the [review and verification record](code-quality-review-2026-10-19.md) for findings, screenshots and limitations. PR CI, owner preview approval and publication remain pending.
Loading
Loading