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
53 changes: 53 additions & 0 deletions docs/decisions/0001-record-architecture-decisions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 1. Record architecture decisions

- Status: accepted
- Date: 2026-09-01

## Context and Problem Statement

Several things about this repository look like mistakes to anyone who did not
watch them being decided. Documentation sources live in `docs/` while several
Markdown files stay in the root. The docs workflow calls an action directly
rather than the shorter reusable workflow that exists for the purpose.

Each is the survivor of an alternative that was tried or costed and rejected,
and the reasoning lived in a pull request description, which stops being read
the moment it merges. The next person to look — human or LLM — sees
only the surviving design and is free to "simplify" it back into the thing that
already did not work.

## Decision

Record architecturally significant decisions as ADRs in `docs/decisions/`,
following [MADR](https://adr.github.io/madr/), matching the conventions already
in use in `caltechlibrary/alchemist` and `caltechlibrary/workflows`. The format
originates with Michael Nygard's [Documenting Architecture
Decisions](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions).

Conventions:

- One file per decision, `NNNN-title-in-kebab-case.md`, numbered sequentially
in the order recorded (not the order decided).
- Each has a status: `proposed`, `accepted`, `rejected`, `deprecated`, or
`superseded by ADR-NNNN`.
- **ADRs are immutable once accepted.** A decision that changes is not edited;
a new ADR supersedes it, and the old one is marked as superseded.
- Corrections of *fact* about what shipped are fine to amend in place, dated
and noted. Changes of *decision* get a new ADR.
- Record the rejected options and why. That is usually the most valuable part
and the part that cannot be recovered from the code.

## Consequences

Decisions with consequences outliving the change that introduced them get a
stable home, and pull request descriptions stop being load-bearing.

These are **not** rendered into the published site, even though they sit under
`docs/`. The build globs `docs/*.md` and does not recurse, so the directory is
carried in the repository and read on GitHub. That suits the audience: ADRs are
for people changing this repository, not for people using the components. If
they should be published later, the build takes an `extra-sources` glob.

The cost is discipline. An ADR nobody writes is worthless, and one nobody
supersedes when the decision changes is worse than worthless. Routine changes —
a new component, a documentation fix, a dependency bump — do not need one.
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# 2. Build the documentation site rather than publishing the repository

- Status: accepted
- Date: 2026-09-01

## Context and Problem Statement

Documentation used to reach the web through `make website`, `./publish.bash`
and a merge into a `gh-pages` branch. That was replaced by `static.yml`, the
stock GitHub "Deploy static content to Pages" template, which uploads the
repository as the site:

```yaml
- uses: actions/upload-pages-artifact@v3
with:
path: '.'
```

That removed the `gh-pages` branch, which was worth doing, but it published
more rather than less. Two consequences, both observed on the live site before
this change:

- **Repository internals were served publicly.** `Makefile`, `codemeta.json`,
`deno.json` and `page.tmpl` all returned 200 from
`software.library.caltech.edu/CL-web-components/`.
- **The site was whatever HTML happened to be committed.** Nothing rendered the
Markdown, so a documentation change only reached the site if someone
remembered to run `make website` and commit the output. Commit 7f20bdd
updated the hostname in `INSTALL.md` and `README.md`; the committed HTML was
never regenerated, so the published pages still showed the old hostname.

## Decision Drivers

- Publishing should not depend on anyone remembering a manual step.
- Only the documentation should be published.
- The build should not be another thing this repository has to maintain.

## Considered Options

1. Keep `static.yml`, and remember to regenerate the HTML
2. Keep `static.yml`, but narrow `path:` to a built directory
3. Build in a workflow owned by this repository
4. Build by referencing `caltechlibrary/workflows`

## Decision Outcome

**Chosen: option 4.** The docs workflow calls
`caltechlibrary/workflows/.github/actions/build-pandoc@v1`, which renders the
Markdown, and `deploy-site@v1`, which uploads the result.

### Option 1: remember to regenerate — rejected

This was the status quo, and it had already failed. The hostname change is the
evidence: the source was updated, the output was not, and nothing detected it.

### Option 2: narrow the `path:` — rejected

Would have fixed the leak but not the staleness. The site would still have been
committed HTML, just less of it.

### Option 3: our own build workflow — rejected

This was built first and worked — the resulting site was byte-identical to what
was published. It was rejected because it is a copy. Every other Caltech
Library site needs the same 127 lines, and copies drift: `codemeta2cff.yml`
exists in fourteen repositories in five distinct versions, two of them still
pinning `actions/checkout@v2`.

### Option 4: reference the shared repository — chosen

The build lives in one place and this repository names a version. A fix there
arrives on the next run; a breaking change requires moving from `@v1`
deliberately.

## Consequences

Good:

- Publishing a documentation change is `git push`. There is no output to
regenerate and no step to forget.
- Only rendered documentation and its declared assets are published.
- Pull requests build the site without deploying it, so a change that breaks
the docs fails in review.
- Improvements to the shared build — accessibility fixes, a Pandoc upgrade —
arrive without editing this repository.

Bad, and accepted:

- A dependency on another repository. Mitigated by the version contract: `@v1`
moves only for backward-compatible changes, and pinning a tag or SHA is
available if this repository ever needs to freeze.
- Debugging gains one indirection. `bin/build-pandoc.sh` in the shared
repository runs locally with no GitHub context, so a failing build can be
reproduced on a laptop.

### Why the action and not the reusable workflow

`caltechlibrary/workflows` also offers `docs-pandoc.yml`, which would reduce
this repository's workflow to about ten lines. It is not usable here.

The site publishes compiled component bundles, so `deno task build` must run
before rendering, which needs `denoland/setup-deno` first. **A caller cannot
add steps to a job it did not write.** Using the action inside our own job
costs roughly fifty lines and keeps everything else shared: the Pandoc
invocation, both Lua filters, the theme handling and the Pages plumbing.

This is the two-tier design working as intended, not a workaround. See
`caltechlibrary/workflows` ADR-0004.

## More Information

- caltechlibrary/CL-web-components#46 — the change, with the page-by-page verification
- `caltechlibrary/workflows` ADR-0002 — why shared logic is referenced, not copied
- [ADR-0003](0003-separate-sources-from-generated-files.md) — the layout this depends on
103 changes: 103 additions & 0 deletions docs/decisions/0003-separate-sources-from-generated-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# 3. Keep sources and generated files in separate namespaces

- Status: accepted
- Date: 2026-09-01

## Context and Problem Statement

The repository root held around a hundred entries with no separation between
things a person writes and things a tool produces: Markdown sources beside
their rendered HTML, component sources in `src/` beside bundles of the same
name in the root, the Pandoc theme, build scripts, and a committed search
index.

That arrangement caused real failures, not untidiness:

- **Ten filenames existed in both `/` and `src/`** — `textarea-csv.js`,
`card-layout.js` and eight others. One of each pair was build output and
could be stale, with nothing indicating which.
- **`add-col-scope.lua` was referenced by `website.mak` but never committed**,
so `make website` failed on the first Markdown file for three months. The
file was invisible among the other root entries; it existed only on the
`gh-pages` branch, where it had been published.
- **Generated HTML drifted from its Markdown.** Commit 7f20bdd changed a
hostname in the sources; the committed pages kept the old one and were
served that way.

Each of those had the same root cause: authored and generated files sharing one
namespace, so nothing about a file's location said whether editing it meant
anything.

## Decision

```
docs/ Markdown sources, demo and test pages
pandoc/ the Pandoc template
src/ component sources
/ only what has to be there
```

Build output is not committed. The site is assembled into `_site/` by CI and
uploaded as an artifact; bundles go to `dist/`, which is gitignored.

**Some Markdown stays in the root:** `README.md`, `INSTALL.md` and the
`INSTALL_NOTES_*` pair. Not by preference — `cmt` writes them there and can
only write there. Its generator registry keys on the exact output filename, so
`cmt codemeta.json docs/about.md` exits with `unsupported format`. The build
renders them with `extra-sources: "*.md"`, so they are published exactly as
before.

## Considered Options

1. Leave the layout flat and be more careful
2. Move everything into `docs/`, including what `cmt` generates
3. Move what can move; render the rest from where `cmt` puts it

## Decision Outcome

**Chosen: option 3.**

### Option 1: be more careful — rejected

Three months of a broken build, ten shadowed filenames and a stale published
site were the result of being careful. The layout is what made those failures
possible and hard to see.

### Option 2: move everything — rejected

Would require either patching `cmt` to accept subdirectory output, or accepting
that a `cmt` run silently reverts the layout. Neither is this repository's
decision to make unilaterally, and the second is worse than the problem.

### Option 3: move what can move — chosen

Documentation sources leave the root, which is what allows the build to stop
looking there. The files `cmt` owns stay where it puts them and are rendered
explicitly, so the constraint is visible in the workflow rather than implied.

## Consequences

Good:

- A file's location says whether editing it means anything. Everything in
`docs/` and `src/` is authored; nothing generated is committed except what
`cmt` writes to the root.
- Generated output cannot go stale, because it no longer exists between builds.
- The generated HTML still committed in the root became unused the moment the
build stopped looking there, so removing it is a separate, purely subtractive
change.

Bad, and accepted:

- The root is not uniform. Some Markdown sits outside `docs/` for a reason
that is not obvious from looking, which is why it is written down here and
commented in the workflow.
- `extra-sources: "*.md"` publishes every root Markdown file, including any
`cmt` adds later. That reproduces the previous behaviour exactly, but it is
a glob rather than a list, so a new root file appears on the site without
anyone choosing that.

## More Information

- caltechlibrary/CL-web-components#46 — the move, with page-by-page verification
- [ADR-0002](0002-build-the-site-rather-than-publishing-the-repository.md) — the build this enables