SPEC_ANSWERHUB_CRAFT.md

AnswerHub — navigation, craft, and the features that never landed — spec

What this covers: giving AnswerHub a navigation it does not currently have, executing its existing visual language properly instead of crudely, and finishing three features that were migrated as shells.

For what is actually built, deployed or reachable, see ClaudeDocs/HANDOFF.md — status deliberately does not live here.

This spec does not change the family's visual direction. ClaudeDesign/APP_FAMILY.md stands unamended: same tokens, same radius, same paper/ink and sage green, same Notion/Linear restraint. That was established during the interview and is worth stating twice, because the owner's complaint sounded like a design-direction problem and was not one. See Further Notes.

It follows SPEC_ANSWERHUB_SHELL.md, which built the page frame this one navigates between, and sits alongside SPEC_ANSWERHUB_LIVE.md, whose browser walk is now partly done — sign-in works.

No issue tracker exists for this project, so this is filed as a ClaudeDocs/SPEC_* document, the same precedent SPEC_APPS.md set.

Problem Statement

The owner opened the deployed product and said three things: the interface still looks dated, most pages do not really work, and moving between pages is a problem. Investigating each turned up something different from what the words suggested.

There is almost no navigation. Crawling the deployed site, every link reachable from every page resolves to exactly two destinations: the homepage and sign-in. Search, settings, bulk upload and the moderation queue have no entry point anywhere in the product. They answer 200 if you type the URL, and there is no way to type it unless you already know it. This is why the owner said those pages "aren't live" — from inside the product, they are not. It is also a defect that page-by-page review cannot catch: each page is individually fine.

Three features were migrated as shells. The profile page is seventy-seven lines and never queries the submissions belonging to the person whose profile it is — so "我的解答" leads to a bio and three links. The old app's equivalent was two hundred and eleven lines with a paginated list of that person's answers and a small set of counts. Search works, but has no in-progress state, no result count and an empty state that says nothing and offers nothing. Listing cards show a title, a description and a like count while the database holds the language, the comment count and a view count for each submission.

The view count is a field nobody writes to. It exists on three models and no code path anywhere increments it.

The interface is badly executed, not badly directed. This is the part that took a wrong turn during the interview and needs stating plainly. "太方太平" — too boxy, too flat — reads as a complaint about the visual language, and the interview initially treated it as one, to the point of preparing to change shared tokens and drag SiaoHub along. The owner corrected it: the tone is the same, what is written now is just badly done. SiaoHub uses the same tokens and the same radius and draws no complaint. What is wrong is spacing chosen ad hoc rather than on a scale, a type hierarchy where headings and body read at nearly the same weight, uniform density regardless of what a region contains, and hover states that only change a border colour. Notion and Linear are not flat and boxy; restraint was implemented as absence.

Solution

Three separate pieces of work, none of which touches the design reference.

Give the product a navigation. A horizontal bar: the product name, then home, search and new answer; on the right, the theme control and a user menu holding my answers, settings, moderation (for administrators) and sign out. It collapses to a single control at phone width. Every destination in the product acquires an entry point, and a structural test fails if a future page does not — the same shape of guard this project already uses for content visibility, because this is the same class of bug: invisible in review, obvious in use.

Make transitions not jar. Both halves of what the owner meant by "跳轉問題": having somewhere to go, and getting there without flicker, white flashes or the layout jumping.

Execute the existing tone properly. A spacing scale instead of ad-hoc values, a type hierarchy with real contrast between levels, density considered per region, and hover and focus states that were decided rather than defaulted. Tokens, radius, colours and the design reference are untouched.

Finish the three shells, using the old application's field list as the reference the owner asked for. The profile page gets its owner's answers, paginated, with the counts that can be computed honestly. Search gets an in-progress state, a result count and an empty state that offers a way forward. Listing cards show the fields the database actually holds. The view count starts being written, so the number it displays means something.

The old application's trust badge is deliberately not carried over: it rendered "已驗證 / 請謹慎參考" from a field that does not exist in either schema. It was decoration shaped like information.

User Stories

Getting around

  1. As a visitor, I want a navigation bar on every page, so that I can reach the product's features without knowing their URLs.
  2. As a visitor, I want to reach search from anywhere, so that looking something up does not require going back to the homepage first.
  3. As a visitor, I want to reach the upload page from anywhere, so that contributing is always one click away.
  4. As a signed-in user, I want a menu holding my own things — my answers, my settings — so that account actions are grouped and predictable.
  5. As an administrator, I want the moderation queue in that menu, so that I do not have to remember its address.
  6. As a signed-in user, I want bulk upload to be reachable, so that a feature that exists is a feature I can find.
  7. As a visitor on a phone, I want the same destinations behind one control, so that the product is not desktop-only.
  8. As a visitor, I want the current section indicated in the navigation, so that I know where I am.
  9. As a developer adding a page later, I want the test suite to fail if it has no entry point, so that the product cannot grow another unreachable corner.
  10. As the owner, I want deliberate exceptions — blog and knowledge base are hidden on purpose — to be stated rather than to look like the same bug.

Moving between pages

  1. As a visitor, I want the page not to flash white when I navigate, so that the product feels like one application.
  2. As a visitor, I want the layout not to jump as content arrives, so that I do not lose my place or misclick.
  3. As a visitor, I want navigation to acknowledge my click immediately, so that I do not press again.
  4. As a visitor who prefers reduced motion, I want transitions to respect that, so that the interface does not make me unwell.

How it reads

  1. As a visitor, I want headings to look like headings, so that I can scan a page instead of reading it.
  2. As a visitor, I want related things grouped closely and unrelated things separated, so that the layout tells me the structure.
  3. As a visitor, I want dense regions to be dense and airy regions to be airy, so that a list of twenty items and a single form do not get the same treatment.
  4. As a visitor, I want hovering something clickable to feel like more than a border changing colour, so that the product feels responsive.
  5. As a keyboard user, I want focus to be clearly visible everywhere, so that I can see where I am.
  6. As the owner, I want the product to stop reading as dated without the palette or the radius changing, so that the family stays one family.

My profile

  1. As a signed-in user, I want my profile to list the answers I have posted, so that "我的解答" leads to my answers.
  2. As a visitor, I want anybody's profile to list their answers, so that I can see what a contributor has produced.
  3. As a visitor, I want that list paginated, so that a prolific contributor's profile stays usable.
  4. As a visitor, I want to see how many answers somebody has posted and how many likes they have received, so that I have some sense of them.
  5. As a visitor, I want those numbers to be real, so that the profile is not decorated with figures nobody computes.
  6. As a visitor to an empty profile, I want it to say so, so that a blank area is not mistaken for a failure.

Finding things

  1. As a visitor searching, I want to see that a search is running, so that I do not think nothing happened.
  2. As a visitor searching, I want to know how many results there are, so that I can judge whether to refine.
  3. As a visitor whose search found nothing, I want to be offered something to do next, so that a dead end is not the end.
  4. As a visitor, I want each result to show enough to choose between them — language, engagement, author — so that I do not open five pages to find one.

What a card says

  1. As a visitor, I want a listing card to show the language, so that I can skip answers in a language I do not use.
  2. As a visitor, I want to see likes, comments and views on a card, so that I can tell what other people found useful.
  3. As a visitor, I want those numbers to reflect reality, so that they are worth reading.
  4. As a visitor, I want the same card everywhere it appears — homepage, search, profile — so that I learn to read it once.
  5. As the owner, I do not want a badge that renders a field the schema does not have, so that the interface does not imply verification nobody performs.

Views

  1. As a contributor, I want a view counted when somebody opens my answer, so that the number on my profile means something.
  2. As the owner, I want that write to be cheap and non-blocking, so that counting views does not slow down reading them.
  3. As the owner, I want it clear that this adds a write on a path that previously only read, so that the change is not discovered later.

Implementation Decisions

Testing Decisions

Out of Scope

Further Notes