Article
Building Shipslecky: a static site with release discipline
How a small Astro website became a governed publishing system with strict content contracts, browser testing and a reversible deployment pipeline.
Shipslecky began with a straightforward idea: technical work becomes more useful when the decisions, failed approaches and repeatable steps are written down. The website needed to hold that material without turning publishing into a second software product to operate.
The result is deliberately small: Markdown content, Astro templates, native CSS and static files. The interesting part is not the number of moving pieces. It is the discipline around them. Content is validated before it can become a page, public output is inspected by automated tests, and a release is not accepted until the live website proves that it is serving the intended commit.
This case study explains that system using facts recorded in the repository, its decision log, commit history, test configuration and production release evidence.
What the site is for
The product vision describes Shipslecky as a durable home for practical technical knowledge, documented projects and resources worth keeping. That gives the site three jobs:
- explain technical subjects clearly enough to be useful;
- show the path through a project, not just its final state;
- keep published claims separate from drafts and unsupported material.
Those jobs shaped the information architecture. Articles hold durable explanations. Projects keep a status and an evidence-led build record. Resources are typed as links, downloads, images, videos or collections. Topic pages connect material across those sections. Search operates over the same published set.
The first edition remains intentionally compact. A small library with honest empty states is more useful than placeholder content presented as finished work.
Architecture: static by default
Shipslecky uses Astro in static-output mode. At build time it turns repository-owned Markdown and Astro components into plain HTML, CSS, XML and text files. The hosting account does not need an application server, database or content-management runtime.
That choice is recorded in the first architecture decision. It keeps the deployment artifact portable and makes the public reading experience resilient: every core route works without client-side JavaScript. The one interactive feature, search, is a progressive enhancement over a pre-rendered list of published links.
Astro’s content collections provide the organizing layer. Articles, projects and resources each have a strict schema. A published entry must have a publication date. Topics must produce safe, unique URL slugs. Images need dimensions and useful alternative text. Download metadata must match the repository file’s byte size and SHA-256 checksum. Video embeds are restricted to an allowlisted HTTPS host and require a direct fallback.
Drafts use the same schemas but never enter public routes, search, feeds, topic pages or the sitemap. This is a useful distinction: authoring flexibility remains, while publication stays fail-closed.
A small search with a clear boundary
Search was added as the first progressive enhancement. The page contains every published result as ordinary HTML, so it remains browsable if JavaScript is unavailable. A small inline module filters titles, summaries, topics, content types and status values in the browser.
The query is reflected in the URL, the result count is announced through a polite live region, and the form is usable from the keyboard. Draft metadata is excluded by reusing the same publication predicate as the rest of the site. The generated search script also has a compressed size budget, which prevents a modest feature from quietly becoming a large client-side application.
Publishing as a contract
A static build can still publish broken or misleading output. Shipslecky therefore tests the generated website rather than treating a successful template compilation as sufficient.
The repository checks that:
- expected routes, feeds and crawler files exist;
- every HTML page has a language, title, description, main landmark, skip target and single first-level heading;
- internal links and assets resolve;
- drafts and placeholder text do not leak into output;
- unsafe URL schemes never reach generated attributes;
- the custom 404 remains non-indexable and has no canonical URL;
- core pages contain no executable client-side script;
- compressed HTML, CSS and search JavaScript remain within recorded budgets.
This first-edition work adds another layer: complete Open Graph and social-card metadata, Schema.org structured data for pages, technical articles and project records, and focused tests that parse the generated JSON-LD. Canonical links, the RSS feed, robots policy and the Astro sitemap integration all derive from the configured site origin.
Local builds deliberately identify themselves as non-public and emit noindex. A canonical production build switches to indexable metadata. That prevents a preview or accidental host from presenting itself to crawlers as the real website.
Quality controls before release
One command runs the repository’s complete quality sequence. It combines formatting, Astro diagnostics, the static build, Node contract tests, browser tests, Lighthouse and a dependency audit.
The browser suite covers desktop and mobile Chromium plus desktop Firefox locally. The main-branch workflow also runs desktop WebKit in GitHub’s supported environment. The same behaviour suite checks keyboard navigation, responsive overflow, search and automated WCAG A/AA rules. The accessibility checks follow the pattern documented in Playwright’s accessibility testing guide: they make automated violations visible while not pretending to replace manual assistive-technology testing.
Lighthouse runs against the home page, this project’s build record and search. The repository enforces category and lab-metric budgets rather than merely saving a report. Lighthouse is useful here as a repeatable regression signal; it is not presented as field performance data.
At the first production release, both the deployment workflow and a separate Quality workflow passed the full suite for the same commit. Production audits then scored 100 for performance, accessibility, best practices and SEO on all three representative routes. Those results are release evidence for that build, not a promise that future changes are automatically safe.
The deployment pipeline
Production deployment to Hostilica starts only from main. GitHub Actions deployment controls provide a named production environment and a concurrency boundary so two releases cannot write at once.
The workflow follows an ordered contract:
- check out the exact event commit;
- validate that project-scoped authentication is usable without exposing key material;
- verify the expected remote identity and fixed filesystem boundary before any write;
- install locked dependencies, run the complete quality suite and create the canonical production build;
- package a deterministic artifact carrying the full commit marker and record its SHA-256 checksum;
- verify HTTPS before enabling a strict transport policy;
- upload the artifact, create and compare a complete off-document-root backup, then stage the release;
- replace project-owned files while preserving hosting-managed validation files and unmanaged server rules;
- compare normalized staged and live tree digests and write a deployment receipt;
- verify the public website and run production Lighthouse budgets.
If a post-deployment check fails, the workflow uses the recorded backup path and checksum to restore the previous document root. The release process is therefore designed to leave evidence for both success and failure.
What the first deployment taught
The first production path did not work in one uninterrupted attempt, and that became useful design evidence.
First, authentication values that look structurally plausible may still be unusable in unattended automation. The workflow gained a local, non-disclosing format check so an unsuitable value fails before a network connection.
Second, the shared hosting environment did not provide rsync. Instead of changing unrelated infrastructure, the deployment switched to standard archive and filesystem tools already available at the verified boundary. Cleanup remains fixed to the checked document root, the backup happens before mutation, and normalized tree hashes prove the copied project files match the artifact.
Third, an existing server-rules file lacked a final line terminator. The preservation comparison caught the difference, rejected the deployment and automatically restored the verified backup. The next revision normalized only that required terminator while preserving every unmanaged line. The failed deployment exercised automatic restoration, and the newline fix was applied before the next production attempt.
The lesson was not that failures are desirable. It was that a good release system makes each failure bounded, diagnosable and reversible.
Decisions that held up
Several early decisions remained useful all the way to production:
- Static output kept operations simple. The artifact is ordinary web content and can move between compatible hosts.
- One publication predicate prevented drift. Routes, search, topics, feeds and sitemaps agree about what is public.
- Generated-output tests caught integration errors. They inspect what a browser or crawler receives, not just source types.
- Performance budgets protected the design. The bold visual system did not require a framework in the browser.
- Rollback was part of deployment, not a later note. The first rejected write demonstrated why that matters.
- Records were part of the release. Commits, artifacts, backups, receipts, checks and review outcomes can be matched without publishing operational secrets.
Where the first edition ends
The foundation is now doing real work: it serves a case study, a project record, searchable topic pages, RSS, sitemap and production metadata from a verified static release. The content library can grow without inventing a new publishing path for each format.
There are still honest gaps. Manual assistive-technology checks and representative editorial media remain open in the acceptance record. Future features should earn their place through the same standard: a clear reader need, a small maintainable implementation and evidence at the boundary where failure would matter.
Open the project build record for the dated milestones, decisions and current status behind this case study. The structured-data vocabulary used for this page is documented publicly as Schema.org TechArticle.