skills/pages/SKILL.md
Scaffold and maintain a GitHub Pages site. Buildless in browser (webjsx + rippleui via CDN), flatspace for content aggregation built during GH Actions. Use when user wants to create or update a GH Pages site.
npx skillsauth add anentrypoint/gm-cc pagesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Scaffold a complete GH Pages site with no local build step. Content via flatspace flat-file CMS, UI via webjsx + rippleui CDN, GH Actions builds and deploys. Follow the full chain: planning → gm-execute → gm-emit → gm-complete → update-docs.
| Layer | Tool | How |
|---|---|---|
| UI rendering | webjsx | ES module via importmap, applyDiff for DOM updates |
| Styling | rippleui | CDN <link> — Tailwind-based component classes |
| Content CMS | flatspace | Aggregates content/ → docs/data/*.json at build time |
| Build | GH Actions | npx flatspace runs in CI, commits output to docs/ |
| Hosting | GitHub Pages | Source set to "GitHub Actions" |
<project>/
content/
pages/
posts/
data/
docs/
index.html # committed, never regenerated
app.js # committed
data/ # flatspace output, gitignored
.github/workflows/pages.yml
flatspace.config.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{SITE_TITLE}}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/styles.css">
<script type="importmap">
{
"imports": {
"webjsx": "https://cdn.jsdelivr.net/npm/[email protected]/dist/index.js",
"webjsx/jsx-runtime": "https://cdn.jsdelivr.net/npm/[email protected]/dist/jsx-runtime.js"
}
}
</script>
<script type="module" src="./app.js"></script>
</head>
<body class="bg-backgroundPrimary text-content1 min-h-screen">
<div id="root"></div>
</body>
</html>
import { applyDiff } from 'webjsx';
const h = (tag, props, ...children) => ({ tag, props: props || {}, children });
const state = { page: null, data: {} };
async function loadData(path) { return (await fetch(path)).json(); }
function render() { applyDiff(document.getElementById('root'), App(state)); }
function App(s) {
if (!s.page) return h('div', { class: 'flex justify-center p-8' }, h('span', { class: 'spinner' }));
return h('div', { class: 'max-w-4xl mx-auto p-4' },
h('nav', { class: 'navbar bg-backgroundSecondary mb-6' },
h('span', { class: 'navbar-brand text-xl font-bold' }, s.page.title)
),
h('main', {}, ...s.page.sections.map(Section))
);
}
function Section(section) {
return h('section', { class: 'card mb-4 p-6' },
h('h2', { class: 'text-2xl font-bold mb-2' }, section.title),
h('p', { class: 'text-content2' }, section.body)
);
}
async function main() { state.page = await loadData('./data/index.json'); render(); }
main();
module.exports = {
input: './content',
output: './docs/data',
collections: {
pages: { dir: 'pages', format: 'markdown' },
posts: { dir: 'posts', format: 'markdown', sortBy: 'date', order: 'desc' },
data: { dir: 'data', format: 'json' }
}
};
name: Deploy GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '20' }
- name: Build content with flatspace
run: npx flatspace
- name: Commit built data
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/data/
git diff --staged --quiet || git commit -m "chore: build content [skip ci]"
git push
- uses: actions/upload-pages-artifact@v3
with: { path: docs/ }
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
Read existing docs/ and content/ if present — never clobber existing content. Create the directory structure. Write docs/index.html, docs/app.js, flatspace.config.js, .github/workflows/pages.yml, content/pages/index.md with minimal frontmatter (title, sections array). Add docs/data/ to .gitignore. Verify GH Pages setting is "GitHub Actions" in repo Settings — remind the user if you can't verify.
| Component | Class |
|---|---|
| Button | btn btn-primary, btn btn-secondary, btn btn-ghost |
| Card | card p-4 |
| Input | input input-primary |
| Navbar | navbar + navbar-brand |
| Badge | badge badge-primary |
| Alert | alert alert-success, alert alert-error |
| Spinner | spinner |
| Divider | divider |
Background bg-backgroundPrimary, bg-backgroundSecondary. Text text-content1, text-content2. rippleui CSS color vars (e.g. --gray-2) are raw space-separated RGB tuples — invalid in rgb() directly. Use the component classes instead.
No JSX transpile needed. Use the h() factory in .js files served directly. .jsx with native importmap requires the server to set the correct MIME type, which GH Pages does not — stay in .js + h().
applyDiff(domNode, vnodeOrArray) — never pass a string. State updates mutate state and call render(); no reactive system.
Markdown with YAML frontmatter:
---
title: Home
sections:
- title: Welcome
body: Hello world
---
# Home
Full markdown body here.
Output docs/data/pages/index.json:
{ "title": "Home", "sections": [...], "body": "<p>Full markdown body here.</p>", "slug": "index" }
GH Pages must be set to "GitHub Actions" in Settings → Pages. "Deploy from branch" ignores the deploy-pages action.
docs/data/ is gitignored; docs/index.html and docs/app.js are not — they are the committed source files.
npx flatspace cold-start is ~10s on first CI run; subsequent runs use the actions/setup-node cache.
Pin the webjsx CDN version in importmap (e.g. @0.0.42) — @latest breaks silently on upstream updates.
data-ai
AI-native software engineering via skill-driven orchestration on zed; bootstraps plugkit for task execution and session isolation
development
AI-native software engineering via skill-driven orchestration on vscode; bootstraps plugkit for task execution and session isolation
data-ai
AI-native software engineering via skill-driven orchestration on oc; bootstraps plugkit for task execution and session isolation
data-ai
AI-native software engineering via skill-driven orchestration on kilo; bootstraps plugkit for task execution and session isolation