skill(astro-wiki-deploy): full deploy flow + 6 pitfalls from live deployment
Captures the wiki.clawdie.si deployment experience (26.jun.2026): Pitfalls documented: 1. const declarations outside function scope fail in Astro SSR 2. YAML frontmatter with unquoted colons breaks content parsing 3. SL content auto-generates stale routes (explicit sl/ routes needed) 4. Stale dist cache preserves old route generation (rm -rf dist) 5. import.meta.url path resolution fails in Astro SSR 6. H1 fallback for pages without YAML frontmatter 7. Nginx SSL cert placeholder (referenced, in nginx skill) Full deploy flow: stage → jail → build → deploy → verify. First-time setup instructions for CMS jail.
This commit is contained in:
parent
834197e2ae
commit
1793ea0a75
1 changed files with 195 additions and 0 deletions
195
.agent/skills/astro-wiki-deploy/SKILL.md
Normal file
195
.agent/skills/astro-wiki-deploy/SKILL.md
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
---
|
||||
name: astro-wiki-deploy
|
||||
description: Deploy the Colibri wiki (astro/wiki/) to wiki.clawdie.si via the CMS jail. Plain Astro — no Starlight. Covers content staging, build, deploy, and the 6 pitfalls discovered during the initial deployment (26.jun.2026).
|
||||
---
|
||||
|
||||
# Astro Wiki Deploy
|
||||
|
||||
Deploy the plain-Astro Colibri wiki to `https://wiki.clawdie.si`.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
colibri/
|
||||
docs/wiki/ ← canonical content (23 EN + 23 SL .md files)
|
||||
astro/wiki/ ← Astro build pipeline (minimal, no Starlight)
|
||||
src/pages/
|
||||
index.astro — EN landing (flat list)
|
||||
[...slug].astro — EN dynamic route (reads src/content/*.md)
|
||||
sl/index.astro — SL landing
|
||||
sl/[...slug].astro — SL dynamic route (reads src/content/sl/*.md)
|
||||
```
|
||||
|
||||
CMS jail builds the site, host nginx serves it. Same pattern as docs.clawdie.si.
|
||||
|
||||
## Full deploy flow
|
||||
|
||||
```sh
|
||||
# 1. Stage content into Astro project (source of truth → build input)
|
||||
cd /home/clawdie/ai/colibri
|
||||
rm -rf astro/wiki/src/content
|
||||
cp -r docs/wiki astro/wiki/src/content
|
||||
|
||||
# 2. Copy source into CMS jail
|
||||
sudo cp -r astro/wiki/src \
|
||||
/usr/local/bastille/jails/cms/root/usr/home/clawdie/clawdie-wiki/
|
||||
|
||||
# 3. Build inside jail (rm -rf dist for clean state — see pitfall #4)
|
||||
sudo bastille cmd cms sh -c '
|
||||
cd /usr/home/clawdie/clawdie-wiki &&
|
||||
rm -rf dist node_modules/.astro &&
|
||||
ASTRO_SITE_URL="https://wiki.clawdie.si" npm run build'
|
||||
|
||||
# 4. Deploy to jail webroot
|
||||
sudo bastille cmd cms sh -c '
|
||||
rm -rf /usr/local/www/wiki.clawdie.si &&
|
||||
mkdir -p /usr/local/www/wiki.clawdie.si &&
|
||||
cp -r /usr/home/clawdie/clawdie-wiki/dist/* /usr/local/www/wiki.clawdie.si/'
|
||||
|
||||
# 5. Cross jail boundary to host webroot (tar is the reliable bridge)
|
||||
sudo bastille cmd cms sh -c \
|
||||
'tar -czf /tmp/wiki-dist.tar.gz -C /usr/local/www/wiki.clawdie.si .'
|
||||
sudo cp /usr/local/bastille/jails/cms/root/tmp/wiki-dist.tar.gz /tmp/
|
||||
sudo rm -rf /usr/local/www/wiki.clawdie.si
|
||||
sudo mkdir -p /usr/local/www/wiki.clawdie.si
|
||||
sudo tar -xzf /tmp/wiki-dist.tar.gz -C /usr/local/www/wiki.clawdie.si/
|
||||
sudo chown -R clawdie:clawdie /usr/local/www/wiki.clawdie.si
|
||||
|
||||
# 6. Verify
|
||||
curl -sk --resolve wiki.clawdie.si:443:127.0.0.1 https://wiki.clawdie.si/ | head -5
|
||||
curl -sk --resolve wiki.clawdie.si:443:127.0.0.1 https://wiki.clawdie.si/sl/ | head -5
|
||||
```
|
||||
|
||||
## First-time setup (CMS jail)
|
||||
|
||||
```sh
|
||||
# Stage the Astro project into the jail once
|
||||
sudo mkdir -p /usr/local/bastille/jails/cms/root/usr/home/clawdie/clawdie-wiki
|
||||
sudo cp -r astro/wiki/package.json astro/wiki/astro.config.mjs \
|
||||
/usr/local/bastille/jails/cms/root/usr/home/clawdie/clawdie-wiki/
|
||||
|
||||
# Install dependencies inside jail
|
||||
sudo bastille cmd cms sh -c 'cd /usr/home/clawdie/clawdie-wiki && npm install'
|
||||
```
|
||||
|
||||
## Pitfalls
|
||||
|
||||
### 1. `const` declarations outside function scope fail in Astro SSR
|
||||
|
||||
**Symptom:** `WIKI_DIR is not defined` at build time, but the variable is
|
||||
clearly declared.
|
||||
|
||||
**Cause:** Astro's frontmatter script compilation scopes top-level `const`
|
||||
differently in SSR context. Variables declared outside `getStaticPaths()` or
|
||||
the template function may not be accessible.
|
||||
|
||||
**Fix:** Move all `const` declarations that are needed in `getStaticPaths()`
|
||||
inside the function body. For variables needed in the template (after
|
||||
frontmatter), declare them at module level but only those that Astro's
|
||||
compiler can reach — simple string literals and path.resolve calls work.
|
||||
|
||||
```js
|
||||
// ❌ BROKEN — WIKI_DIR is undefined in compiled output
|
||||
const WIKI_DIR = path.resolve("src/content");
|
||||
export function getStaticPaths() { ... }
|
||||
|
||||
// ✅ WORKS — declared inside function scope
|
||||
export function getStaticPaths() {
|
||||
const WIKI_DIR = path.resolve("src/content");
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### 2. YAML frontmatter with unquoted colons breaks content parsing
|
||||
|
||||
**Symptom:** `bad indentation of a mapping entry` at line N:XX during build.
|
||||
|
||||
**Cause:** Slovenian (and English) titles/descriptions often contain colons
|
||||
(`:`). YAML interprets unquoted colons as key-value separators. This breaks
|
||||
Astro's content collection parsing.
|
||||
|
||||
**Fix:** Quote ALL frontmatter values that contain colons, double-quotes,
|
||||
or special characters:
|
||||
|
||||
```yaml
|
||||
# ❌ BROKEN
|
||||
title: Agentska oprema: zot + Colibri
|
||||
|
||||
# ✅ WORKS
|
||||
title: "Agentska vprega: pi, zot & Colibri"
|
||||
```
|
||||
|
||||
Also: descriptions with nested double-quotes need single-quote wrappers:
|
||||
|
||||
```yaml
|
||||
# ❌ BROKEN — inner quotes terminate the string
|
||||
description: "Sprememba ni "končana" brez..."
|
||||
|
||||
# ✅ WORKS — single-quote wrapper, inner double-quotes preserved
|
||||
description: 'Sprememba ni "končana" brez...'
|
||||
```
|
||||
|
||||
### 3. SL content auto-generates stale routes
|
||||
|
||||
**Symptom:** `src/pages/sl/index.astro` appears in the build output with
|
||||
hardcoded paths like `scandir '/usr/docs/wiki'` even after removing
|
||||
`src/content/sl/`.
|
||||
|
||||
**Cause:** Astro's content collection auto-generation creates `sl/` routes
|
||||
from `src/content/sl/`. These auto-generated routes use different path
|
||||
resolution and can persist in the dist cache between builds.
|
||||
|
||||
**Fix:**
|
||||
1. Create explicit `src/pages/sl/index.astro` and `src/pages/sl/[...slug].astro`
|
||||
routes that read from `src/content/sl/` directly.
|
||||
2. Remove any auto-generated `sl/` directory from `src/pages/sl/` if it
|
||||
appears.
|
||||
3. ALWAYS `rm -rf dist node_modules/.astro` between builds (see pitfall #4).
|
||||
|
||||
### 4. Stale dist cache preserves old route generation
|
||||
|
||||
**Symptom:** Fixed source code, but the same error persists after rebuild.
|
||||
|
||||
**Cause:** Astro caches compiled routes in `dist/` and `.astro/`. A previous
|
||||
failed build can leave stale compiled `.mjs` files that shadow the fixed
|
||||
source.
|
||||
|
||||
**Fix:** Always clean before rebuilding:
|
||||
```sh
|
||||
rm -rf dist node_modules/.astro && npm run build
|
||||
```
|
||||
|
||||
### 5. `import.meta.url` path resolution fails in Astro SSR
|
||||
|
||||
**Symptom:** Paths resolved via `fileURLToPath(import.meta.url)` point to
|
||||
compiled `.mjs` files in `dist/`, not the source `.astro` files.
|
||||
|
||||
**Cause:** Astro compiles `.astro` to `.mjs` and runs from `dist/`. The
|
||||
`import.meta.url` in the compiled module points to the compiled path, not
|
||||
the project root.
|
||||
|
||||
**Fix:** Use `path.resolve("src/content")` — `process.cwd()` during build
|
||||
is the project root (`astro/wiki/`), so relative paths work correctly.
|
||||
Do not use `import.meta.url` for content path resolution.
|
||||
|
||||
### 6. H1 fallback for pages without YAML frontmatter
|
||||
|
||||
**Symptom:** Page `<title>` shows the slug (e.g., "agent-harness") instead
|
||||
of the actual heading ("Agent harness: pi, zot & Colibri").
|
||||
|
||||
**Cause:** The title extraction only checks `frontmatter.title`, falling back
|
||||
to the URL slug. Pages with only a markdown H1 (`# Title`) and no YAML
|
||||
frontmatter get slug-based titles.
|
||||
|
||||
**Fix:** Add H1 regex extraction as a third fallback:
|
||||
```js
|
||||
const title = (frontmatter.title || content.match(/^#\s+(.+)$/m)?.[1] || slug)
|
||||
.replace(/^["']|["']$/g, "");
|
||||
```
|
||||
|
||||
### 7. Nginx: missing SSL cert blocks startup (see nginx skill)
|
||||
|
||||
Before the first deploy, nginx needs a placeholder cert to start. See the
|
||||
**nginx** skill §"Adding a new public static HTTPS site — full flow" and
|
||||
§Troubleshooting "BIO_new_file() failed". The wiki deployment follows the
|
||||
same pattern: placeholder cert → ACME challenge → real cert.
|
||||
Loading…
Add table
Reference in a new issue