Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions scripts/site.sh
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,26 @@ if [[ -d "$ASSETS" ]]; then
cp -R "$ASSETS/." "$STAGED/assets/"
fi

# The landing page is not a file anyone writes directly. Helium takes the content
# of site/src/landing-page.md, lifts that document out of the tree and re-inserts
# it as the root directory's *title document* — and a title document is what
# renders to index.html.
#
# So a root index.md or README.md is not merely redundant, it is a second writer
# to index.html. Laika renders documents in parallel, and nothing in Laika or in
# this script arbitrates between them: whichever finishes last wins, and if they
# overlap the file ends up holding both. That is not hypothetical. The published
# site once served an index.html that was the landing page written over the first
# half of a second, differently-templated copy of the same page — closing
# </body></html> in the middle, the sidebar's link list dumped into the body
# below it. Both builds exited 0.
#
# Fail here instead, naming the file and where its content belongs.
for collision in index.md README.md; do
[[ -f "$STAGED/$collision" ]] || continue
die "site/src/$collision renders to index.html, and so does the generated landing page. Two writers, one file, no arbitration — see the note above homeLink in site/build/laika.scala. Put the front page's prose in site/src/landing-page.md instead."
done

# MEASURED, NOT ASSUMED: Laika 1.3.2 does not resolve a link target written
# `./sibling.md` — it reads `.` as a path segment and reports "unresolved
# internal reference". `sibling.md` resolves; `../other/page.md` resolves.
Expand Down
2 changes: 1 addition & 1 deletion site/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ scripts/site.sh --help # the pipeline, step by step

| Path | What it is | Owner |
| --- | --- | --- |
| `src/index.md` | The landing page. | this directory |
| `src/landing-page.md` | The prose of the front page, rendered below the header and the teasers. The filename is fixed by Helium, and `src/` must hold no `index.md` or `README.md` — see the note above `homeLink` in `build/laika.scala`. | this directory |
| `src/getting-started.md` | Install, first request, error rails, pagination. | this directory |
| `src/examples.md` | The `modules/examples` programs. Its table is generated at build time. | this directory |
| `src/directory.conf` | Laika configuration for the content tree: title and sidebar order. | this directory |
Expand Down
22 changes: 21 additions & 1 deletion site/build/laika.scala
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,24 @@ object Site:
.favIcons(Favicon.internal(Root / "assets" / "favicon.svg", sizes = "32x32"))
.site
.topNavigationBar(
homeLink = IconLink.internal(Root / "index.md", HeliumIcon.home),
// `Root / "README"`, with no `.md` and no such file in site/src, is not a typo.
//
// MEASURED, NOT ASSUMED. The landing page configured below is not a page anyone writes directly. Helium takes
// the content of `site/src/landing-page.md`, lifts that document out of the content tree, and re-inserts it as
// the *title document* of the root directory — at the suffix-less path `/README`, because `README` is Laika's
// default title-document input name. A directory's title document is what renders to `index.html`, which is how
// the landing page comes to be the site's front page.
//
// So this is the only path that resolves to the front page. `Root / "landing-page.md"` fails link validation,
// because by the time links are resolved that document is gone from the tree. `Root / "README.md"` fails too:
// the re-inserted document carries no suffix.
//
// The consequence to keep in mind is that site/src must contain no `index.md` and no `README.md`. Either one
// would also render to `index.html`, and Laika renders documents in parallel — so the two writers race for the
// same file. That is not hypothetical: it is what produced a published `index.html` holding the landing page
// spliced on top of the tail of a second, differently-templated copy of the same page. scripts/site.sh fails
// the build if either file reappears.
Comment on lines +214 to +218

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Scope the collision rule to the root of site/src.

The implementation rejects only root index.md and README.md files. The current wording can be read recursively and can incorrectly prohibit valid nested README title documents.

  • site/build/laika.scala#L214-L218: state that only the root of site/src is reserved.
  • site/README.md#L19-L19: state that only the root of src/ may not contain index.md or README.md.
Proposed wording
-        // site/src must contain no `index.md` and no `README.md`.
+        // The root of site/src must contain no `index.md` and no `README.md`.
📍 Affects 2 files
  • site/build/laika.scala#L214-L218 (this comment)
  • site/README.md#L19-L19
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@site/build/laika.scala` around lines 214 - 218, Clarify the collision
documentation in site/build/laika.scala at lines 214-218 to state that only the
root of site/src is reserved; nested index.md and README.md files remain valid.
Apply the same root-only wording in site/README.md at line 19 for src/, with no
other changes.

homeLink = IconLink.internal(Root / "README", HeliumIcon.home),
navLinks = Seq(
TextLink.internal(Root / "getting-started.md", "Getting Started"),
TextLink.internal(Root / "examples.md", "Examples"),
Expand All @@ -212,6 +229,9 @@ object Site:
.site
.pageNavigation(depth = 3)

// Everything below the header and the teaser rows is the prose of `site/src/landing-page.md`. That file has no
// top-level heading of its own on purpose: `title` here already renders "codeberg4s" at 48px directly above it,
// and a second `<h1>codeberg4s</h1>` under it said the same word twice.
withChrome.site
.landingPage(
title = Some(SiteInfo.title),
Expand Down
5 changes: 4 additions & 1 deletion site/src/directory.conf
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ laika.title = codeberg4s
# scripts/site.sh. If one of them is missing, Laika ignores the entry rather
# than failing, and scripts/site.sh prints a warning naming what it generated in
# its place.
#
# `landing-page.md` is deliberately absent from this list. Helium lifts that file
# out of the content tree and renders it as the site's landing page, so it is not
# a sidebar entry — see the note above `homeLink` in site/build/laika.scala.
laika.navigationOrder = [
index.md
getting-started.md
guides
reference
Expand Down
2 changes: 0 additions & 2 deletions site/src/index.md → site/src/landing-page.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# codeberg4s

A Scala 3 client for the [Codeberg](https://codeberg.org) and
[Forgejo](https://forgejo.org) REST API v1. All 439 in-scope operations are
implemented, on both error rails, against models built from captured responses
Expand Down