Spec: Astro landing page¶
Requirements for the workshop website. To be built in web/ in this repo.
Superseded: the page copy is English
This note originally specified Norwegian page copy. That decision was reversed on 2026-09-03: all material is English, including the rendered site, even though the workshop is still delivered in Norwegian. The Norwegian drafts below are kept as a record of the original intent — the built site does not use them.
Two further changes since this spec was written:
- The route is
/prepare, not/forbered. - The visual direction comes from the design canvas, not from this document. Where the two disagree, the canvas wins for layout and the repo wins for anything a participant would actually type.
Sections 1 and 4.1's preparation, not registration rule still stand, and the built site honours them.
1 · Purpose¶
The landing page has one job: make sure participants show up with a prepared laptop.
Everything else — marketing, speaker bios, the agenda — is secondary. The key conversion on
this page is not registration (the conference owns that). It's someone actually running
make preflight at home. See P1 and P2.
Success criteria¶
| Goal | Measure |
|---|---|
| Participants did the prep | Share arriving with a green preflight (show of hands) |
| Nobody arrives without a laptop | Informal count in the room |
| The content outlives the day | Traffic to /docs after the conference |
2 · Architecture: two sites, one domain¶
Recommendation
Astro at root, the MkDocs documentation under /docs/, one GitHub Pages deploy.
We already have a MkDocs Material site holding the lab content. The options:
| Option | Assessment |
|---|---|
Astro at root + MkDocs at /docs/ |
✅ Chosen. Marketing and docs each get their own form. One deploy. |
| Astro Starlight for everything | Means rewriting the labs. Much work, little gain now. |
| MkDocs only | Works, but a docs homepage doesn't sell a workshop. |
| Two separate domains | Two deploys, split link graph, confused participants. No. |
In practice: the workflow builds Astro to dist/ and MkDocs to dist/docs/, then publishes
dist/ as one artifact. mkdocs.yml gets site_url: https://<domain>/docs/.
3 · Site map¶
| Route | Content | Priority |
|---|---|---|
/ |
Landing page — the whole story on one page | Must |
/forbered |
The preparation instructions, as a shareable URL | Must |
/docs/ |
The MkDocs documentation (built separately) | Must |
/404 |
Simple, links to / and /docs/ |
Should |
One page plus one subpage. Don't build more.
4 · Sections on /¶
The order is deliberate: what → for whom → prepare → what we do → who we are. Preparation comes before the agenda, because it's the most important action.
4.1 Hero¶
- Eyebrow:
Cloud Native Days Norway 2026 · Bergen · 26.–27. oktober - H1:
Agentic Cloud Ops - Subtitle:
Praktisk AI-drevet Kubernetes-drift - Lede (draft, Norwegian):
Fra Infrastructure as Code til Infrastructure as Agents. To timer der vi slipper AI-agenter løs på et ekte Kubernetes-cluster — og finner ut hva som faktisk skal til for å tørre det i produksjon.
(From Infrastructure as Code to Infrastructure as Agents. Two hours turning AI agents
loose on a real Kubernetes cluster — and working out what it actually takes to dare do
this in production.)
- Metadata chips: Workshop · 2 timer · Norsk · Intermediate · Hands-on
- Primary CTA: Forbered laptopen din → (Prepare your laptop) → /forbered
- Secondary CTA: Se innholdet (See the content) → /docs/
Critical detail
The primary CTA is not "register". The conference owns registration. Our CTA is preparation, and it must be the most prominent element above the fold.
4.2 Warning banner — "bring a laptop"¶
A visually distinct strip directly under the hero. Impossible to miss.
Dette er en hands-on workshop. Du trenger en laptop med Docker og ~10 GB ledig disk, og du må gjøre forarbeidet hjemme. Konferanse-wifi er ikke et byggesystem.
(This is a hands-on workshop. You need a laptop with Docker and ~10 GB of free disk, and you must do the prep at home. Conference Wi-Fi is not a build system.)
4.3 Takeaways¶
Three cards, taken verbatim from the proposal:
- Agentic vs. GitOps — understand what's genuinely new, and what's just hype.
- Hands-on experience — deployment, debugging and security hardening with agents in K8s.
- Risk management — the success criteria for autonomous systems in production.
4.4 "Is this for me?"¶
Two columns, honest in both directions. Undersell rather than oversell.
| Yes, if you… | No, if you… |
|---|---|
use kubectl daily |
have never seen a Kubernetes manifest |
| want to watch agents make real changes | want an overview presentation |
| are curious where the limits are | can't bring a laptop |
| are a developer, architect or SRE | expect finished product recommendations |
State explicitly that no ML background is needed.
4.5 Preparation (short version)¶
Three steps with a copyable command. Links onward to /forbered.
Every line must say OK. Its own component, with a copy button.
4.6 Schedule¶
A vertical timeline of the six blocks with durations. Use the
revised schedule, not the proposal version. Each block links to
the corresponding page under /docs/.
4.7 "What we actually do"¶
Three lab cards, one concrete and honest sentence each:
- Lab 1 · Den første agenten — "Deploy en Nginx med 3 replicas." Så planter vi en feil, og lar agenten finne den selv.
- Lab 2 · Hardening — clusteret er bevisst usikkert. Agenten strammer det inn uten å brekke applikasjonen. Det er vanskeligere enn det høres ut.
- Lab 3 · Kaos — vi brekker noe. Ingen får bruke
kubectl. Agenten må finne det.
4.8 Speakers¶
Two cards: name, short bio, links. Lars Effenberger and Lars Søraas.
4.9 Footer¶
Links to the conference, the repo, /docs/, and the Code of Conduct. No newsletter.
5 · Technical stack¶
| Choice | Rationale |
|---|---|
| Astro 5, static output | No SSR need. Plain HTML to Pages. |
| No UI framework | The page is static. No React/Vue/Svelte islands. |
Tailwind via @tailwindcss/vite |
Fast iteration, no separate config file needed |
@astrojs/sitemap |
SEO |
| Content Collections | Schedule, labs and speakers as typed data |
| Fontsource, self-hosted | No third-party font requests |
TypeScript strict |
No JavaScript islands
The only interactivity is the copy button and the theme. Both are ~20 lines of inline script. If someone proposes a client component, ask why.
6 · Project structure¶
web/
├── astro.config.mjs
├── package.json
├── src/
│ ├── content.config.ts # collection schemas
│ ├── content/
│ │ ├── schedule/ # one file per block
│ │ ├── labs/ # one file per lab
│ │ └── speakers/ # one file per speaker
│ ├── layouts/
│ │ └── Base.astro # <head>, meta, theme, skip link
│ ├── components/
│ │ ├── Hero.astro
│ │ ├── LaptopBanner.astro
│ │ ├── TakeawayCards.astro
│ │ ├── FitCheck.astro
│ │ ├── PrepSteps.astro
│ │ ├── CodeBlock.astro # with copy button
│ │ ├── Timeline.astro
│ │ ├── LabCards.astro
│ │ ├── SpeakerCards.astro
│ │ └── Footer.astro
│ ├── pages/
│ │ ├── index.astro
│ │ ├── forbered.astro
│ │ └── 404.astro
│ └── styles/global.css # design tokens
└── public/
├── og.png
└── favicon.svg
7 · Content collections¶
import { defineCollection, z } from 'astro:content';
const schedule = defineCollection({
type: 'content',
schema: z.object({
order: z.number(),
title: z.string(),
minutes: z.number(),
summary: z.string(),
docsHref: z.string(), // → /docs/labs/...
format: z.enum(['presentation', 'hands-on', 'demo', 'buffer']),
}),
});
const labs = defineCollection({
type: 'content',
schema: z.object({
order: z.number(),
title: z.string(),
hook: z.string(), // one honest sentence
docsHref: z.string(),
}),
});
const speakers = defineCollection({
type: 'content',
schema: z.object({
name: z.string(),
role: z.string().optional(),
bio: z.string(),
links: z.array(z.object({ label: z.string(), href: z.string().url() })).default([]),
}),
});
export const collections = { schedule, labs, speakers };
The schedule must come from the schedule collection, not be hardcoded in markup. It will
keep changing right up to the dress rehearsal.
8 · Design¶
Tokens¶
Define the complete light palette on bare :root. Redefine only tokens under
@media (prefers-color-scheme: dark) and [data-theme="dark"]. No colour may have its only
definition inside a media query.
:root {
--bg: #fbfbfa;
--surface: #ffffff;
--border: #e4e4e1;
--text: #16161a;
--text-muted: #5f5f68;
--accent: #0f766e; /* teal — matches the MkDocs site */
--accent-contrast: #ffffff;
--warn-bg: #fff7ed; /* the laptop banner */
--warn-border: #f97316;
--code-bg: #f4f4f2;
}
- Accent: teal
#0f766e— the same as the MkDocs theme, so/and/docs/feel like one site. - Signal colour: orange, used only for the laptop banner. Used nowhere else, so it actually means something.
Typography¶
- Headings and body: one good sans (Inter or similar), self-hosted.
- Code: monospace. Commands should look like commands.
- Max measure ~68ch.
Tone¶
Restrained and technical. No gradient blobs, no AI clichés, no stock photos of robots. The audience is sceptical operations people — the page should read like something written by someone who has been up at three in the morning.
9 · Performance and accessibility¶
Non-negotiable acceptance criteria:
- No render-blocking JS. Page weight < 100 kB (excluding fonts)
- Lighthouse ≥ 95 across all four categories
- Works entirely without JavaScript (the copy button degrades to a plain code block)
- Contrast ≥ 4.5:1 in both themes
- Full keyboard navigation, visible focus ring, skip link
-
prefers-reduced-motionrespected - One
<h1>, correct heading hierarchy - No horizontal scroll at 320px width
-
lang="no"on the document (the copy is Norwegian)
10 · SEO and sharing¶
<title>Agentic Cloud Ops — Workshop, Cloud Native Days Norway 2026</title>
<meta name="description" content="Praktisk AI-drevet Kubernetes-drift. To timers hands-on workshop i Bergen, 26.–27. oktober 2026.">
- OG image 1200×630: title, subtitle, date, location. Static PNG in
public/. JSON-LDof typeEventwith date, location andperformer.sitemap.xmlandrobots.txt.
11 · Analytics¶
No cookies, no third party requiring consent. If anything is needed: a self-hosted
Plausible/Umami, or nothing at all. We don't need to know more than whether /forbered gets
read.
12 · Deployment¶
Extend .github/workflows/docs.yml to build both sites into a single artifact:
- run: pip install -r requirements.txt
- run: mkdocs build --strict # → site/
- run: npm ci --prefix web
- run: npm run build --prefix web # → web/dist/
- run: mkdir -p out && cp -r web/dist/* out/ && cp -r site out/docs
- uses: actions/upload-pages-artifact@v3
with:
path: out
Astro gets base: '/', MkDocs gets a site_url pointing at /docs/. A link check in CI is
a worthwhile addition: a broken link to the preparation page costs more than it looks.
13 · Out of scope¶
Deliberately excluded — don't build these:
- Registration or ticketing (the conference owns this)
- Newsletter, CMS, comments, blog
- i18n / an English version (the workshop is in Norwegian)
- A dark/light toggle beyond
prefers-color-scheme(only if it's free) - Animation beyond simple hover states
14 · Definition of done¶
-
/and/forbereddeployed on the same domain as/docs/ - The schedule reads from a content collection, not hardcoded
- Every acceptance criterion in §9 is green
- Tested on mobile — half the audience reads this on a phone on the way to work
- Link sent to the organisers for the conference programme listing