Skip to content

An honest, deployable landing page - #34

Merged
ARCoder181105 merged 9 commits into
mainfrom
honest-showcase
Aug 29, 2026
Merged

An honest, deployable landing page#34
ARCoder181105 merged 9 commits into
mainfrom
honest-showcase

Conversation

@ARCoder181105

@ARCoder181105 ARCoder181105 commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added authenticated explorer routing with loading, signed-out, and unavailable states.
    • Added showcase-mode landing links and a supported-language marquee.
    • Added descriptive page metadata, favicon support, and Vercel deployment configuration.
  • Improvements
    • Refreshed landing-page typography, colors, animations, and interactive file-row styling.
    • Clarified self-hosted setup, supported languages, repository safety limits, authentication, and deployment guidance.
  • Bug Fixes
    • Improved session loading behavior and accessibility for asynchronous application startup.
  • Documentation
    • Clarified parser safety protections and the current scope of isolation.

`repos/register.ts` runs the parser with execFile from the queue worker. It is
a plain child process carrying the worker's network, filesystem and user.
`--network none`, the read-only rootfs and the dropped capabilities apply under
`make parser-isolated` and nowhere else.

Five documents said otherwise. docs/SECURITY.md ticked "clone/parse runs in an
isolated container" and "parser has no outbound network access" from Phase 1
onward. CLAUDE.md said isolation "was built in Phase 1, not deferred".
ARCHITECTURE.md's diagram labelled the parser box "network none". PLAN.md said
Phase 1 built it to avoid a later retrofit. The landing page told readers their
repository is cloned into a sandbox with no network and no capabilities -- and
that page is about to be deployed.

The claim is corrected rather than the code. Both fixes cost more than the gap:
shelling out to `docker run` needs the Docker socket mounted into the worker,
which grants root-equivalent host control and is a worse property than the one
it buys; namespaces, seccomp or bubblewrap avoids that but is Linux-only and a
project of its own. R38 records the choice and what would change it.

What survives is enforced on every path, because it lives in the parser rather
than around it: symlinks hard-fail, files over 1 MB are skipped, file count and
depth are capped, the clone is depth-one with credential prompts disabled, no
repo script is ever invoked, and the checkout is removed on the failure path.
The landing page now leads with the strongest claim that is actually true --
nothing in the repository is executed -- instead of the one that was not.

Two things worth keeping from how this hid for four phases. A checkbox ticked
against a harness says nothing about the product, and the harness runs with
`--no-deps`, which is also why nobody hit the `parser` service declaring both
`network_mode: none` and a `depends_on` on Postgres. And the TOCTOU deferral in
the same checklist had leaned on this claim inside its own justification, so
one false statement had already propagated into a second decision.
There is no hosted instance, so the public face is the web app on its own.
"Open the atlas" would send every visitor of that build to an error screen.

VITE_SHOWCASE flips the one component that defines the call to action:
`OpenAtlas` renders a link to the repository labelled "Run it yourself"
instead. The label changes with the destination, because a button still
reading "Open the atlas" that opened GitHub would be the same lie in a
friendlier voice. Build-time rather than a runtime probe, deliberately: the
landing page makes no request to our API, which is what lets it render when
the backend is absent, and asking whether the API is up would give that away
for a fact the build already knows.

The limits copy now says the thing that is true in both builds -- this is a
tool you run yourself, there is no instance to sign in to but your own.

The canvas route is lazy. Statically imported, React Flow and the panels sat
in the main bundle and every landing-page visitor downloaded a canvas they
never opened; on a showcase build it can never be reached at all. Splitting
`AppRoute` into its own module takes the entry chunk from 323 kB to 170 kB
gzipped and drops react-flow out of it entirely. `ResolvingSession` moves to
its own file because both sides need it and importing it from `AppRoute`
would pull that chunk straight back into the entry.

vercel.json carries the monorepo build and, more importantly, a rewrite of
everything to index.html -- without it a deep link or a refresh on /app is a
404, since there is no server-side route for it.

Verified against the built bundle under `vite preview`, which is the only
local thing with the same fallback behaviour: all three calls to action read
"Run it yourself" and point at the repository, and /app answers 200 and
renders the unreachable-API screen rather than a 404.

Three things left unverified in #33 are now measured rather than assumed. The
draw animation runs -- the mask transform steps -374px, -62px, -5.7px, then is
removed, with node opacities staggering 0.32, 0.81, 1 behind it. The
breakpoints hold: 375px is single column with no horizontal overflow and the
header's second call to action correctly hidden, 768px shows it. The earlier
"requestAnimationFrame is dead" reading was a stale tab, not the page.
Two faults in one row. Selecting a function swapped the background with no
transition, so it read as a repaint rather than as an answer to the click --
everything else on this canvas moves under one.

The second was hiding inside the first. The line-number badge is `variant
="outline"`, bordered with `--border`, and `--accent` resolves to the same
token; on the selected row the pill's edge was drawn in exactly the colour of
the row beneath it and disappeared. Every other row had a pill and the
selected one did not, which read as the badge being removed on selection. It
keeps its own ground there now.

Both transitions are under `motion-safe:`.

No test: this is two class strings, and asserting the class names back would
be a change detector rather than a check. Verified in a browser against
pmndrs/zustand.
⌘K marks a result with `bg-accent` and `ring-1 ring-primary/40`. The card's
rows had the accent ground and no ring, so the same object -- a function you
can pick -- looked like two different things depending on which surface you
found it on. They match now, with a lighter ring on hover so the row answers
the pointer before it is clicked.

box-shadow is named in the transition because that is what a ring is;
`transition-colors` alone eased the fill and snapped the outline.
It was stale in ways that would waste a new contributor's afternoon. The
phase table said Phase 5 "not started"; it merged in 4e240ed with eight
languages. "How it works" said `.ts`/`.tsx` only. And the setup instructions
told people to sign in with "Continue as a local dev user" and to POST to
`/auth/dev-login` -- a route deleted in Phase 4 (R30). Following the README as
written got you a 404 and a login screen with no such button.

Rewritten around the reader who has just cloned it and wants it running.
The confidence tiers are the first thing on the page, with a table of what
each one means, because that is the product rather than a detail of it. The
GitHub OAuth app now has its three exact field values written out, since that
is the one step nothing can do for you, along with why the scope is
`read:user` and why that limits it to public repositories.

A "what it does not do" section states the limits in the README instead of
leaving them to be discovered: public repositories only, no hosted instance,
the incremental re-parse that is only incremental in its write (R35), and the
parser sandbox being a harness rather than the running path (R38). The
`docker compose up` gap is called out as not working rather than quietly
omitted, since it is the next piece of work.

Every link in the document was checked to resolve.
Splitting `/app` behind React.lazy made its tests wait on a dynamic import
that really does pull React Flow and the rest of the canvas. Alone that lands
well inside Testing Library's 1s default; in a full run, with eighteen other
files competing for the same threads, it does not, and the route test failed
intermittently.

A longer ceiling for this file rather than a mock of the lazy boundary: the
wait is a real property of the route, and every assertion still fails if it
never renders. Confirmed over three consecutive full runs.

`configure` is imported from @testing-library/react, not @testing-library/dom
-- the latter is only a transitive dependency and does not resolve from this
package.
Three complaints, one cause: the page was flat. Two hues across three thousand
pixels, 30px headings sitting too close to 16px body for the eye to rank them,
and eight languages listed as text.

**A third ink.** `spot` -- #2ad4c4 dark, #0b7268 light. Named for what it is
rather than as a tier, because it is the only colour in tokens.ts that carries
no canvas meaning. A map is drawn in three inks and two of ours were already
spoken for. It sits at 174°, 53° off `exact` and 153° off `name`, so it cannot
be misread as either, and it never appears on the canvas -- there a colour
meaning nothing would compete with three that mean something. Eyebrows,
section detail, hover. Light is #0b7268 rather than the #0d7d72 that reads
better, because that one measured 4.48:1 on paper and text wants 4.5.

Worth recording: the palette database consulted for this returns slate plus
#22C55E for every developer tool in it, which is UI_GUIDE §7's second cluster
verbatim. It confirmed the default rather than escaping it, so its colour
answer was not taken.

**A type scale.** Section headings 40-48px against 18px ledes, and Bricolage's
weight axis driven to 560 on headings against 400 in prose -- the axis was the
reason the face was chosen and it had been sitting unused.

**A language strip.** Eight marks drifting behind a mask that fades both ends,
a CSS keyframe over `transform` with the set held twice and translated by
exactly half, so the loop closes on itself. Reduced motion gets the same strip
standing still, because the content is the point and the drift is decoration.
The cards below keep the honest distinction and lose their logos: repeating
all eight on one screen said it twice, and the cards carry the caveat rather
than the names. Their language lists take the tier colour each group actually
produces across files.

Marks are vendored from simple-icons (CC0) rather than imported -- the package
has no subpath exports, so using it means pulling three thousand icons to keep
seven. Java is drawn here instead: Oracle's cup is a trademark simple-icons
does not ship, OpenJDK's duke is legally clean but reads as nothing, so this
is a plain coffee cup and a copy of no one's logo.

A favicon, finally, which the app never had: the product's own notation at
16px, one caller reaching three callees along a solid, a dashed and a dotted
edge, the last of them hollow.
The strip visibly restarted once a cycle. `gap-14` puts space *between*
items, so a 16-item track carries 15 gaps: half its width is one set plus
seven and a half gaps, while a seamless loop needs one set plus a whole one.
Translating -50% therefore landed 28px short -- half a gap -- and the jump
back was the reset.

Each item carries its own trailing space now, so the two halves measure
identically and -50% is exactly one set. Verified rather than eyeballed: both
halves 1072.8px of a 2145.6px track, drift 0.
It points at two screenshots that do not exist and nothing renders it. Dead
code should not merge, and rebuilding it is ten lines once there is an image
to put in it -- `git show c9ad0a2` has the version with the reasoning in it.
@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Free

Run ID: 7dfe37d2-0787-44bc-8069-295a9e2fd27c

📥 Commits

Reviewing files that changed from the base of the PR and between 28e8363 and e5cc795.

⛔ Files ignored due to path filters (1)
  • apps/web/public/favicon.svg is excluded by !**/*.svg
📒 Files selected for processing (29)
  • CLAUDE.md
  • PLAN.md
  • README.md
  • apps/web/index.html
  • apps/web/src/App.test.tsx
  • apps/web/src/App.tsx
  • apps/web/src/AppRoute.tsx
  • apps/web/src/components/FileCard.tsx
  • apps/web/src/components/ResolvingSession.tsx
  • apps/web/src/components/landing/ClosingCta.tsx
  • apps/web/src/components/landing/Hero.tsx
  • apps/web/src/components/landing/HowItWorks.tsx
  • apps/web/src/components/landing/LanguageMarquee.tsx
  • apps/web/src/components/landing/Languages.tsx
  • apps/web/src/components/landing/OpenAtlas.test.tsx
  • apps/web/src/components/landing/OpenAtlas.tsx
  • apps/web/src/components/landing/Section.tsx
  • apps/web/src/components/landing/Tiers.tsx
  • apps/web/src/index.css
  • apps/web/src/lib/constants.ts
  • apps/web/src/lib/language-marks.ts
  • apps/web/src/lib/tokens.ts
  • apps/web/src/vite-env.d.ts
  • apps/web/tailwind.config.ts
  • docs/ARCHITECTURE.md
  • docs/RISKS.md
  • docs/SECURITY.md
  • docs/UI_GUIDE.md
  • vercel.json

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The changes correct parser isolation documentation and update the web application with lazy route loading, session states, landing-page content, showcase behavior, theme tokens, tests, and Vercel deployment configuration.

Changes

Product documentation and parser isolation

Layer / File(s) Summary
Parser isolation scope and security records
CLAUDE.md, PLAN.md, docs/ARCHITECTURE.md, docs/RISKS.md, docs/SECURITY.md
The documentation distinguishes the make parser-isolated harness from the unsandboxed product parser path. Parser safeguards and the remaining R38 work are recorded.
Current product workflow and setup
README.md
The README documents current graph behavior, supported languages, setup, authentication, repository limits, architecture, commands, and documentation links.

Web application routing and presentation

Layer / File(s) Summary
Lazy application route and session states
apps/web/index.html, apps/web/src/App.tsx, apps/web/src/AppRoute.tsx, apps/web/src/components/ResolvingSession.tsx, apps/web/src/App.test.tsx
The root app lazy-loads AppRoute. The route handles session states and renders the authenticated explorer. Loading UI and async test configuration were added.
Landing page content and interaction updates
apps/web/src/components/landing/*, apps/web/src/components/FileCard.tsx
Landing content now describes self-hosting, language coverage, confidence tiers, and showcase links. Language marquee, motion-aware cards, typography, and selected-row styling were added or updated.
Web build, theme, and deployment foundations
apps/web/src/lib/*, apps/web/src/index.css, apps/web/src/vite-env.d.ts, apps/web/tailwind.config.ts, vercel.json
The web app adds language mark data, the VITE_SHOWCASE flag, spot theme tokens, marquee animation styles, and Vercel SPA configuration.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to e5cc7

This PR updates the web landing page and related documentation without introducing an actionable merge-blocking risk; it is merge-ready after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant App
  participant AppRoute
  participant Explorer
  Browser->>App: Request /app
  App->>AppRoute: Lazy-load application route
  App->>AppRoute: Render ResolvingSession during session resolution
  AppRoute->>Explorer: Render authenticated explorer layout
Loading

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/web/src/App.test.tsx

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

apps/web/src/App.tsx

ESLint skipped: the matched ESLint configuration already failed (missing-dependency).

apps/web/src/AppRoute.tsx

ESLint skipped: the matched ESLint configuration already failed (missing-dependency).

  • 17 others

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

@ARCoder181105
ARCoder181105 merged commit f179e55 into main Aug 29, 2026
4 checks passed
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