CTAO Science Portal — static site + git-based CMS

Public portal for CTAO news, built as a fully static site. Editors get a browser WYSIWYG editor (Sveltia CMS) that commits Markdown to a Gitea repo; a build job turns commits into static HTML. No application or database runs on the public path.

Live demo: https://astro.isl-dev.grid.cyfronet.pl · Gitea on the demo machine: https://astro-git.isl-dev.grid.cyfronet.pl

Repository layout & deployment

Code and content are SEPARATE repositories, so editorial commits never mix with development:

Repo Holds Source of truth Who commits
ctao-portal (this one, Bitbucket) Templates, CSS, deploy development the team
ctao/content (Gitea on the demo machine) news/, pages/, uploads/ editorial Sveltia CMS / editors

The demo machine polls ITS Gitea (ctao/portal mirror + ctao/content) and republishes on a push to either — so a push to Bitbucket does NOT deploy; deploying code = pushing it to the machine's Gitea (a deliberate step). The build overlays content onto code (deploy/build.sh); the content paths are gitignored here.

Stack

  • Astro (static output). Pages are .astro templates (plain HTML with a JS frontmatter block). No React/Vue/Svelte components, no client-side framework.
  • Plain CSS — everything lives in src/styles/global.css as design tokens (custom properties) + rules. No Tailwind, no preprocessor. The design system (tokens, type scale, spacing, motion policy) is documented in DESIGN.md — read it before touching styles.
  • Sveltia CMS — a single prebuilt JS bundle, vendored in public/vendor/sveltia-cms.js and loaded on /admin/ (src/pages/admin/index.astro), configured by public/admin/config.yml. It runs entirely in the editor's browser and talks to the Gitea API (OAuth PKCE). There is no CMS server. To update it: curl -sL https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js -o public/vendor/sveltia-cms.js
  • Runtime dependencies: none beyond Astro. This is deliberate — keep it that way.

Develop

Prerequisites: Node 22.19 or newer (the machine builds on Node 24), and network access to the demo machine's Gitea (Cyfronet network / VPN) for the content clone below. Without content the site still builds, but with no articles and npm run check reports the footer's page links as broken.

npm ci
git clone https://astro-git.isl-dev.grid.cyfronet.pl/ctao/content.git ../ctao-content
./scripts/link-content.sh   # copies news/pages/uploads into the dev tree
npm run dev        # http://localhost:4321
npm run build      # static output in dist/
npm run check      # deterministic gate: astro check (types) + build + internal-link check

tsconfig.json excludes public/ on purpose: the vendored CMS bundle there is 2 MB of minified JS and would make astro check run out of memory.

Layout

Path What
src/pages/ Routes (.astro templates), incl. news/, search, RSS/sitemap
src/layouts/Base.astro HTML shell: head, header/nav, footer
src/content/news/*.md Articles (from the content repo — gitignored here; schema in src/content.config.ts)
src/styles/global.css All CSS: tokens + components + prose
DESIGN.md Design handoff: where the tokens live, brand basics, practical notes
public/admin/ CMS config (config.yml) + editor preview styles (preview.css)
public/uploads/ Editor-uploaded media (from the content repo — gitignored here)
deploy/ Runbook + container/systemd units for the demo machine — see deploy/README.md

Editing content

Editors use /admin/ (link in the footer) and sign in with a Gitea account. Saving commits to main; the machine polls and republishes automatically (seconds). Full history/rollback = git history in Gitea. Articles with draft: true are excluded from the build.

Note for styling work: public/admin/preview.css mirrors the .prose rules from global.css so the editor preview matches the site 1:1 — keep them in sync (both files carry a KEEP IN SYNC comment).

Upgrading

Versions are pinned exactly; an upgrade is a deliberate change, never a side effect of npm install. Astro ships security fixes only for the current and one previous major, so plan one upgrade per major rather than skipping several.

npx @astrojs/upgrade      # moves astro and official integrations together
npm run check             # types + build + links must pass
npm run preview           # verify the real dist/ output, not the dev server

No experimental flags in astro.config.mjs: they can change in minor releases.

S
Description
No description provided
Readme
106 MiB
Languages
CSS 43.8%
Astro 25.8%
JavaScript 16.6%
Shell 12%
TypeScript 1.8%