Self-hosted: add a Terminal layout, the Developer aesthetic as a console - #1473
Conversation
Developer was the template whose look implied a structure it did not have: dark and code-friendly, rendering the same cards as everything else. Terminal is that aesthetic as an actual layout. Its own shell (a prompt line instead of a masthead, filters as flags, no sidebar) and its own archive: a dense listing of one row per post, dates in a tabular column, no images and no cards, so a reader sees thirty titles where a feed shows five. It ships beside Developer rather than replacing it. An unknown template id clamps to the roster default, so retiring that id would silently reset an independent deployment's blog to Medium, and those cannot be surveyed.
Code Review by Qodo
1. Terminal layout test mislocated
|
|
Warning Review limit reached
Next review available in: 26 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoSelf-hosted: add Terminal layout theme (console shell + dense archive listing)
AI Description
Diagram
High-Level Assessment
Files changed (12)
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce7e88daab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| <span aria-hidden="true" className="text-theme-muted"> | ||
| {prompt} | ||
| </span>{' '} | ||
| {blogTitle || username} |
There was a problem hiding this comment.
Use the current community title in the Terminal header
When Terminal is used for a community whose on-chain title differs from the stored meta.title (for example, after the community is renamed), this renders the stale configured title or the account name. The shared BlogNavigation and the Journal/Reader shells instead load useCommunityData() and prefer community.title, so selecting Terminal changes the community's visible identity; resolve the display title through the same community-aware path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Valid, fixed at 600900d. The shell now takes communityId from useInstanceConfig() for a community prompt and prefers useCommunityData()'s community.title over the stored meta.title, matching Journal, Reader and the shared navigation. A community renamed on chain now shows its current name here too.
Worth admitting the shape of the original bug: the prompt line read isCommunityMode ? \/${username}` : `/${username}``, a ternary with identical branches. I had clearly intended to differentiate and then did not, which is exactly the kind of thing that reads as deliberate in a diff.
| <time | ||
| dateTime={entryData.created} | ||
| className="shrink-0 w-[6.5rem] text-xs text-theme-muted tabular-nums" |
There was a problem hiding this comment.
Accommodate owner-configured date formats in listing rows
When an owner selects a longer valid date format such as MMMM d, yyyy, formatDate() returns text wider than this fixed 6.5rem column. Because the <time> has neither truncation nor a no-wrap/dynamic-width strategy, the date wraps or spills toward the prompt and destroys the aligned compact listing; size the column from the configured output or constrain the rendered value safely.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Valid, fixed at 600900d, and the fix leans on the one property this theme guarantees.
The column is now measured rather than assumed: the archive formats every date in the batch, takes the longest, and sets the column to that many ch. ch is exact here because Terminal is monospace throughout, so one character is one advance width. The <time> also carries whitespace-nowrap, so an unusually long value pushes the column instead of folding onto a second line.
Verified by rendering with dateFormat: 'MMMM d, yyyy', the format you named:
- dates render as
August 12, 2026 - every date cell is exactly 108px wide (one distinct value across the listing)
- every cell is 16px tall, so nothing wrapped
- every
>prompt mark sits at the same left edge, 406px - no horizontal scroll
Code Review by Qodo
1. Terminal layout test mislocated
|
|
Both P2s are fixed at 600900d (replies on the threads). The two Qodo skill insights I am refuting, with evidence. "Test file mislocated, should be under src/specs/" and "should use .spec.ts, not .test.ts": those are the conventions of
Every existing test here is co-located and named The CLAUDE.md section those rules come from is headed "Main App (Vitest)" and describes |
Closes #1469. Takes the roster to nine templates and five layouts.
Developer was the template whose look implied a structure it did not have: dark and code-friendly, rendering the same cards as everything else. Terminal is that aesthetic as an actual layout.
~/username) instead of a masthead, the description as a#comment, filters rendered as--flagswith the active one in the accent, and no sidebar.tabular-numscolumn so they line up (proportional digits make a monospace listing ragged, which is the one thing a listing cannot be), a>prompt mark, the title truncating, read time on the right. No images, no excerpts, no cards. A reader sees thirty titles where a feed shows five.Two decisions worth stating
It ships beside Developer rather than replacing it. Replacing would keep the roster honest and no managed tenant uses Developer today, so the temptation was real. But an unknown template id clamps to the roster default, and independent deployments cannot be surveyed: retiring the id would silently reset someone's self-hosted blog to Medium. The cost of keeping a redundant skin is lower than that.
It carries no sidebar CSS. Gallery needs those rules because it keeps the shared shell and has to collapse the column that shell reserves.
TerminalShellrenders its own frame with no sidebar in it, so a rule hiding one would match nothing. I wrote them first, then removed them on reading the file back, and the guard test now asserts their absence so nobody adds them back for symmetry.The shell mounts
CreatePostButtonitself, which is the standing contract here: the default navigation is what mounts the composer entry, so a shell replacing it and forgetting silently removes the only way an owner writes a post.Verified by rendering it
Built the app and served the real
distthrough the published image's nginx, against a real account, with the hostile config:listType: grid(which is also whatapply-config-domfalls back to when the key is absent) and dark mode.The listing stays a listing under
grid, monospace resolves, and the ground is the dark token rather than an inherited one. Rendering also caught a misalignment worth fixing: the sharedBlogPagemeasure left the listing inset from the prompt line above it, so the header and body did not share a left edge. Both now sit at the same 868px.946 SPA tests and typecheck pass. Roster, editor label, token and card-treatment guards updated for the ninth template, plus a layout guard for the two CSS rules that carry weight.