# 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: ยท Gitea on the demo machine: ## 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.