CTAO Science Portal: static Astro site with git-based CMS (Sveltia + Gitea)
Portal code only; editorial content lives in the ctao/content repo on the demo machine's Gitea and is overlaid at build time (see README.md and deploy/README.md). Live demo: https://astro.isl-dev.grid.cyfronet.pl
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
# Sveltia CMS config — backend: Gitea behind the Cyfronet ingress (HTTPS
|
||||
# vhost). Editors log in via Gitea OAuth (PKCE, no client secret); edits are
|
||||
# committed to the ctao/content repo. Gitea's ROOT_URL and CORS are pinned to
|
||||
# these origins in deploy/ctao-demo-gitea.container.
|
||||
backend:
|
||||
name: gitea
|
||||
# Content lives in its OWN repo (editorial history separate from code —
|
||||
# the build overlays it onto the portal code, see deploy/build.sh).
|
||||
repo: ctao/content
|
||||
branch: main
|
||||
base_url: https://astro-git.isl-dev.grid.cyfronet.pl
|
||||
api_root: https://astro-git.isl-dev.grid.cyfronet.pl/api/v1
|
||||
app_id: cf1c44ac-ebe6-4a97-bf2f-f7f26ef1126c
|
||||
# OAuth only — hides the "access token" sign-in option (documented
|
||||
# auth_methods). The "Work with Local Repository" button needs no config:
|
||||
# it renders only on localhost (source-verified), so it vanishes once the
|
||||
# portal is served from a real domain.
|
||||
auth_methods: [oauth]
|
||||
|
||||
# CTAO branding on the sign-in screen and browser tab (documented Sveltia
|
||||
# options: app_title replaces the "Sveltia CMS" label; logo.src is the
|
||||
# current form of the deprecated logo_url).
|
||||
app_title: CTAO Content Editor
|
||||
logo:
|
||||
src: /brand/CTAO_Logo_login.svg
|
||||
|
||||
media_folder: "uploads"
|
||||
public_folder: "/uploads"
|
||||
|
||||
# Keep the git repo lean: images are stored as plain git blobs (no LFS), so
|
||||
# every upload is converted client-side to WebP q85 and capped at 2048px
|
||||
# (documented media_libraries transformations). A phone photo lands in the
|
||||
# repo as ~100-300 KB instead of 5-10 MB.
|
||||
media_libraries:
|
||||
default:
|
||||
config:
|
||||
slugify_filename: true
|
||||
transformations:
|
||||
raster_image:
|
||||
format: webp
|
||||
quality: 85
|
||||
width: 2048
|
||||
height: 2048
|
||||
svg:
|
||||
optimize: true
|
||||
|
||||
collections:
|
||||
- name: news
|
||||
label: "News"
|
||||
label_singular: "Article"
|
||||
folder: "news"
|
||||
create: true
|
||||
slug: "{{slug}}"
|
||||
extension: md
|
||||
format: frontmatter
|
||||
summary: "{{title}} · {{date}}"
|
||||
fields:
|
||||
- { name: title, label: "Title", widget: string }
|
||||
- { name: description, label: "Short description", widget: text }
|
||||
- { name: date, label: "Date", widget: datetime, date_format: "YYYY-MM-DD", time_format: false }
|
||||
- { name: category, label: "Category", widget: string, default: "news" }
|
||||
- { name: author, label: "Author", widget: string, default: "CTAO" }
|
||||
- { name: cover, label: "Cover image", widget: image, required: false }
|
||||
- { name: lang, label: "Language (if not English, e.g. pl)", widget: string, required: false }
|
||||
- { name: draft, label: "Draft (unpublished)", widget: boolean, default: false }
|
||||
- { name: body, label: "Body", widget: markdown }
|
||||
|
||||
- name: pages
|
||||
label: "Pages"
|
||||
label_singular: "Page"
|
||||
folder: "pages"
|
||||
create: true
|
||||
slug: "{{slug}}"
|
||||
extension: md
|
||||
format: frontmatter
|
||||
summary: "{{title}}"
|
||||
fields:
|
||||
- { name: title, label: "Title", widget: string }
|
||||
- { name: description, label: "Description", widget: text, required: false }
|
||||
- { name: body, label: "Body", widget: markdown }
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Entry-preview styles for the Sveltia editor, registered via the documented
|
||||
CMS.registerPreviewStyle API (bare element selectors, per the official docs
|
||||
example). This file MIRRORS the article styles 1:1 — the design tokens from
|
||||
:root and the `.prose` block in src/styles/global.css — with `.prose`
|
||||
dropped from selectors (the preview pane has no such wrapper).
|
||||
KEEP IN SYNC: when you touch `.prose` or the tokens in global.css, update
|
||||
the corresponding value here (a matching reminder sits next to `.prose`).
|
||||
Fonts: same self-hosted woff2 files the site uses, same origin. (The
|
||||
Sveltia bundle still loads its own UI fonts from jsDelivr — only the
|
||||
PREVIEW pane is CDN-free.) */
|
||||
@font-face {
|
||||
font-family: "Inter"; font-weight: 400 700; font-display: swap;
|
||||
src: url("/fonts/inter-latin.woff2") format("woff2");
|
||||
}
|
||||
@font-face {
|
||||
font-family: "Space Grotesk"; font-weight: 500 700; font-display: swap;
|
||||
src: url("/fonts/space-grotesk-latin.woff2") format("woff2");
|
||||
}
|
||||
|
||||
:root {
|
||||
/* tokens copied from global.css :root */
|
||||
--galaxy: #00004a;
|
||||
--moon: #f5f5f5;
|
||||
--text: #101228;
|
||||
--muted: #46536a;
|
||||
--border: #e2e5ee;
|
||||
--link: #0057c2;
|
||||
--font-body: "Inter", Arial, system-ui, sans-serif;
|
||||
--font-display: "Space Grotesk", var(--font-body);
|
||||
--fs-s: 0.9rem;
|
||||
--fs-l: 1.125rem;
|
||||
--fs-xl: 1.5rem;
|
||||
--fs-h2: clamp(1.75rem, 3.5vw, 2.5rem);
|
||||
--radius: 16px;
|
||||
}
|
||||
|
||||
/* preview shell ≈ article column */
|
||||
body {
|
||||
font-family: var(--font-body);
|
||||
color: var(--text);
|
||||
max-width: 70ch;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
/* = global.css base heading/link rules = */
|
||||
h1, h2 { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.025em; line-height: 1.1; }
|
||||
h3 { font-weight: 600; }
|
||||
h1, h2, h3 { overflow-wrap: break-word; text-wrap: balance; }
|
||||
a { color: var(--link); text-decoration: underline; text-underline-offset: 3px; }
|
||||
|
||||
/* = global.css `.prose` rules, selectors unwrapped = */
|
||||
body { line-height: 1.65; overflow-wrap: break-word; }
|
||||
a { overflow-wrap: anywhere; }
|
||||
h1 { color: var(--galaxy); font-size: var(--fs-h2); } /* mirrors `.article h1` */
|
||||
h2 { color: var(--galaxy); margin: 44px 0 12px; font-size: var(--fs-xl); }
|
||||
h3 { color: var(--galaxy); margin: 30px 0 8px; font-size: var(--fs-l); }
|
||||
p { margin: 0 0 16px; text-wrap: pretty; }
|
||||
ul, ol { margin: 0 0 16px; padding-left: 22px; }
|
||||
li { margin: 6px 0; }
|
||||
blockquote {
|
||||
margin: 22px 0; padding: 12px 20px; border-left: 3px solid var(--galaxy);
|
||||
background: var(--moon); color: var(--text);
|
||||
}
|
||||
img { display: block; max-width: 100%; height: auto; border: 1px solid var(--border); border-radius: var(--radius); }
|
||||
img + em, p > em:only-child { color: var(--muted); font-size: var(--fs-s); }
|
||||
hr { border: 0; border-top: 1px solid var(--border); margin: 32px 0; }
|
||||
table { display: block; width: 100%; overflow-x: auto; border-collapse: collapse; margin: 0 0 16px; font-size: var(--fs-s); }
|
||||
th { text-align: left; font-weight: 600; color: var(--galaxy); }
|
||||
th, td { padding: 10px 12px; border-bottom: 1px solid var(--border); }
|
||||
thead th { border-bottom: 2px solid var(--galaxy); }
|
||||
Reference in New Issue
Block a user