Skip to content

refactor(projects): the project page was a wall of text — mostly a layout bug - #468

Merged
github-actions[bot] merged 1 commit into
mainfrom
feat/project-page-redesign
Sep 3, 2026
Merged

refactor(projects): the project page was a wall of text — mostly a layout bug#468
github-actions[bot] merged 1 commit into
mainfrom
feat/project-page-redesign

Conversation

@catomean

@catomean catomean commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Reported: the project page is ugly, a wall of text, terrible hierarchy — and "I went there to place the widget on FleetCrown itself, but there is no widget."

Both were true from where the operator was standing. Measured on the live page before changing anything:

2,698 words · 17 sections · 8 h2s
Visitor feedback 1,054w · Activity 847w · Report 844w
Agent context: 37 buttons in 397 words

The biggest cause was layout, not word count

On a 1680px window the header was a justify-between row whose links column was shrink-0:

Element Width of 960px
Project name + description 333px
Six ghost links (Live / Repository / Published / …) 607px — 63%

Navigation to elsewhere outranked the project's own identity. A 202-word description then wrapped into a twenty-line ribbon with two thirds of the screen empty beside it. That ribbon is what reads as a wall of text.

Three changes, in the order they matter

1. Identity outranks navigation. Destinations move to a quiet row below the name and description, which now get the full measure.

2. The description is clamped to three lines, with a toggle, and only when there is enough text to be worth hiding. A description should say what a project is; these have grown into whole briefs — fleetcrown's names every route, integration and monetisation rail — and printing all of it under the title pushed every control below the fold.

3. Seventeen sections become six tabs. Ten of those sections answered variations of one question: Overview, Status quo, What happens next, Purpose, Product, Reach, Build contract, Resources, Plan and finish line, Next action, Completion contract.

A jump-nav already existed and indexed 6 of the 17 — which its own comment named as the failure mode: a nav that knows about some sections teaches the reader the others are not there. Anchors could not fix it either; scrolling into a wall leaves the other 2,400 words underneath. A tab removes them.

Why the widget looked missing

It wasn't. FleetCrown's project has had an active token the whole time, and the page reads Live · fleetcrown.orangecat.ch — but only after you click an unlabelled "Widget" toggle buried inside the 1,054-word feedback section. Someone looking for it did not find it and concluded the feature did not exist.

It has its own tab now.

The controls were verified end-to-end through the real UI on the live site during this investigation: clicked Bottom left → Save position, confirmed {"corner":"bottom-left"} from /api/widget-boot, then set it back to bottom-right. Adding and positioning genuinely works — it was undiscoverable, which for product purposes is nearly as bad.

Tab behaviour worth knowing

  • Deep links preserved. #feedback is what ControlInbox links to; the tablist reads the hash on mount and on hashchange, so every existing link still lands correctly.
  • Real tablist. role=tablist/tab/tabpanel, roving tabindex, arrow-key navigation.
  • Panels stay mounted while hidden. They hold unsaved drafts and poll while work is in flight — unmounting would discard a half-typed brief the moment someone checked another tab. hidden keeps them out of the a11y tree without destroying state.
  • replaceState, not location.hash — assigning the hash would scroll to a now-nonexistent anchor and stack a history entry per tab click, so Back would walk tabs instead of leaving the page.

Verification

npm run verify exits 0.

Also verified with a real npx next build (exit 0), because this moves JSX across a server/client boundary and verify deliberately excludes the build — it could not have caught an RSC serialization fault. An earlier red build turned out to be the missing local database, not this change: rebuilding with a placeholder DATABASE_URL succeeds, which is the discriminating test.

Note for anyone repeating that: use npx next build. Plain npm run build has a postbuild hook that runs deploy-local.sh and ships your current branch.

…yout bug

Reported as ugly with terrible hierarchy, and as "there is no widget" on a
project that has had a live widget the whole time. Both were true from
where the operator was standing. Measured on the live page before
changing anything:

  2,698 words · 17 sections · 8 h2s
  Visitor feedback 1,054w · Activity 847w · Report 844w
  Agent context: 37 buttons in 397 words

But the biggest cause was not the word count. On a 1680px window the
header was a `justify-between` row whose links column was `shrink-0`, so
six ghost links to ELSEWHERE took 607px of 960px — 63% — and squeezed the
project's own name and description into 333px. A 202-word description then
wrapped into a twenty-line ribbon with two thirds of the screen empty
beside it. That ribbon is what reads as a wall of text.

Three changes, in the order they matter:

1. Identity outranks navigation. Destinations move to a quiet row BELOW
   the name and description, which now get the full measure.

2. The description is clamped to three lines with a toggle. A description
   should say what a project IS; these have grown into whole briefs
   (fleetcrown's names every route, integration and monetisation rail),
   and printing all of it under the title pushed every control below the
   fold. Only offered when there is actually enough text to hide.

3. Seventeen sections become six tabs. Ten of those sections answered
   variations of one question — Overview, Status quo, What happens next,
   Purpose, Product, Reach, Build contract, Resources, Plan and finish
   line, Next action, Completion contract. A jump-nav already existed and
   indexed 6 of the 17, which its own comment named as the failure mode: a
   nav that knows about some sections teaches the reader the others are
   not there. Anchors could not fix that — scrolling into a wall leaves
   the other 2,400 words underneath. A tab removes them.

Why the widget looked missing: its setup sits inside the 1,054-word
feedback section, behind an unlabelled "Widget" toggle. Someone looking
for it did not find it and concluded the feature did not exist. It has its
own tab now.

Tabs preserve existing deep links (#feedback is what ControlInbox links
to), are arrow-key navigable as a real tablist, and keep every panel
MOUNTED while hidden — these panels hold unsaved drafts and poll while
work is in flight, so unmounting would discard a half-typed brief the
moment someone looked at another tab.

Verified with a real `next build`, not just verify: this moves JSX across
a server/client boundary and `npm run verify` deliberately excludes the
build, so it could not have caught an RSC serialization fault.
(Note for anyone repeating that: use `npx next build`. `npm run build`
has a postbuild hook that deploys.)
@github-actions
github-actions Bot merged commit a553146 into main Sep 3, 2026
3 checks passed
@github-actions
github-actions Bot deleted the feat/project-page-redesign branch September 3, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant