Enhance browse landing page as documentation hub #15
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/pal-e-api!15
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "13-landing-page-docs-hub"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
/browse/with architecture diagram, quick-start links, and stats/browse/reposwith platform/status displayRelated Notes
plan-2026-02-24-docs-foundation— Phase 4 docs complete, this ships the landing page from earlier phasesnote-conventions— follows HTML style guideTest plan
/browse/— landing page renders with architecture diagram, project cards, SOP links/browse/repos— repos listed with platform badges and status🤖 Generated with Claude Code
PR Review — #15 Enhance browse landing page as documentation hub
Reviewer: Devy (agent)
Plan:
plan-2026-02-24-docs-foundationBLOCKERS
None. No blocking issues found.
NITS (should fix)
1. Missing
| urlencodeon tag URLs inlanding.htmlEvery other template (
note.html,tags.html,project_notes.html,tag_notes.html) uses{{ tag.name | urlencode }}in tag hrefs. The landing page omits it in all 4 documentation sections:Tag names with spaces or special characters would produce broken URLs. This is a consistency issue with the existing codebase pattern. 4 occurrences to fix.
2.
Repomodel missing fromtests/conftest.pyimportsconftest.pyimports all models so SQLAlchemy creates the tables during tests.Repois absent:Not a runtime bug today (no tests exercise repos/frontend routes), but will cause failures when someone adds repo tests. Worth fixing while touching this code.
3. Empty state handling in
landing.htmlThe Projects and Repos sections on the landing page render empty
<div class="card-grid"></div>containers when there are no items. Theprojects.htmltemplate handles this gracefully with{% else %}on the for loop:Consider adding similar empty-state messages for the Projects and Repos card grids, or wrapping them in
{% if projects %}/{% if repos %}blocks like the Documentation subsections already do.OBSERVATIONS (informational, no action required)
mode="json"fix inrepos.pyis correct and necessary. Verified thatHttpUrlobjects serialize toUrltype withoutmode="json", which would fail when passed to SQLAlchemy'sStringcolumn. Good catch in the review-fix commit.Literal types for platform/status are a good improvement. The
Literal["github", "forgejo"]andLiteral["active", "archived"]constraints prevent garbage data at the API boundary. The DB column staysStringwhich is fine — validation at the schema layer is the right place.Query consolidation in the landing route is clean. Single query for doc notes with
Tag.name.in_(doc_tags)then Python-side filtering avoids N+1 and keeps it to 3 queries total (projects, repos, doc_notes). The_has_taghelper is readable.XSS surface is safe. New templates use only
{{ variable }}(auto-escaped by Jinja2). No| safefilters. Repo URLs come from the DB (stored as plain strings from validatedHttpUrlinput), and Jinja2 auto-escapes them in href attributes. The badge CSS classes use{{ repo.platform }}and{{ repo.status }}which are constrained to Literal values at creation time.Route reorganization is clean. Moving projects list from
/browse/to/browse/projectsand adding the landing page at/browse/is a sensible restructure. All internal template links already point to/browse/projects/{{ slug }}so no broken links.Mermaid diagram is hardcoded. The architecture diagram in
landing.htmlis static HTML. This is fine for now — it's a landing page, not generated content. When the architecture changes, someone will need to update this template. Consider noting this inCLAUDE.mdor the project page so it doesn't go stale.VERDICT
Approve with nits. Fix the 4 missing
| urlencodefilters inlanding.html(nit #1), then this is good to merge. Nits #2 and #3 are nice-to-have and can be deferred.- Add | urlencode filter to all 4 tag URL references in landing.html - Import Repo model in tests/conftest.py so SQLAlchemy creates the table - Add {% else %} empty-state messages for Projects and Repos card grids Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>PR #15 Review — Enhance browse landing page as documentation hub
Reviewer: Fresh PR reviewer (no prior context)
Plan:
plan-2026-02-24-docs-foundationSummary of Changes
This PR (3 commits across the branch) adds:
/browse/) — architecture diagram (Mermaid), project cards, repo cards, and categorized documentation lists (SOPs, architecture, conventions, templates)/browse/repos) — repos grouped by project with platform/status badgesRepoCreate/RepoUpdatenow useLiteral["github", "forgejo"]for platform,Literal["active", "archived"]for status, andHttpUrlfor URL validationmode="json"added tomodel_dump()calls inrepos.pysoHttpUrlobjects serialize to plain strings for SQLAlchemy{% else %}blocks on{% for %}loops for projects and repos| urlencodeon tag names in href attributes (consistent withnote.html)Repomodel imported inconftest.pyso SQLAlchemy creates the repos tableBLOCKERS
None. The code is correct and ready to merge.
NITS
No test coverage for browse routes. The existing test suite covers only the API CRUD endpoints. There are no tests hitting
/browse/,/browse/repos, or any frontend route. This is not a blocker for this PR — the routes are simple read-only template renders — but it would be good to add at least a smoke test (assert 200 status) in a follow-up.Inline styles in
landing.html. Lines like<h3 style="margin-top: 1rem; font-size: 1rem; color: #555;">appear 4 times. These could be a CSS class inbase.html(e.g.,.doc-section-heading). Not a blocker — the pattern is contained to one file and is easy to refactor later.Documentation sections repeat the same tag-rendering pattern. The SOPs, Architecture, Conventions, and Templates blocks in
landing.html(lines 92-146) are nearly identical — only the variable name differs. A Jinja2 macro or{% include %}with a parameter could DRY this up. Low priority since the repetition is small and readable.repos.htmlhas no empty state. The landing page now has{% else %}for empty projects/repos, butrepos.htmlhas no fallback if there are zero repos. Minor inconsistency._has_taghelper is defined inside the route function. This is fine for now, but if more routes need tag filtering, consider extracting it to a utility.Security Review
Jinja2Templatessetsautoescape=Trueby default. All{{ }}expressions are HTML-escaped.| safeonly used forhtml_contentinnote.html, with an explicit security comment documenting the trust boundary. Not changed in this PR.{{ repo.url }}in href attributes — Jinja2 autoescape handles HTML entity escaping. TheHttpUrlvalidation in the schema ensures only valid HTTP(S) URLs are stored, preventingjavascript:URI injection.| urlencodeon tag names — correctly prevents broken URLs from tag names containing special characters.Edge Cases Verified
{% else %}blocks render "No projects yet." / "No repos yet." messages.{% if repo.project %}guard preventsNone.nameerrors.repos.htmlalso handles unassigned repos in a separate section.sopandconventionwill appear in both sections. This is correct behavior (not a duplicate bug).HttpUrltrailing slash — Pydantic'sHttpUrlnormalizeshttps://example.comtohttps://example.com/. This is stored in the DB and displayed as-is. Acceptable.Performance Review
doc_noteslist 4 times — negligible for the expected data volume.Verdict: APPROVED
Clean, well-structured PR. The schema hardening (
Literalenums,HttpUrl,mode="json") is a solid improvement. The landing page follows existing patterns. No blockers.The nits above are suggestions for future cleanup, not blockers for merge.