feat: course website (Astro Starlight)
Pages (index, disclaimer, about), lockfile, root test:site script, fix for Starlight 0.42 sidebar config and <details> rendering in generated MDX. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d41496655e
commit
699d038d1c
+2
-1
@@ -5,6 +5,7 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test:tools": "node --test tools/test/*.test.mjs",
|
||||
"check": "node tools/sync-check.mjs"
|
||||
"check": "node tools/sync-check.mjs",
|
||||
"test:site": "node --test site/scripts/*.test.mjs"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export default defineConfig({
|
||||
],
|
||||
sidebar: [
|
||||
{ label: "Start here", items: ["disclaimer", "about"] },
|
||||
{ label: "Modules", autogenerate: { directory: "course" } },
|
||||
{ label: "Modules", items: [{ autogenerate: { directory: "course" } }] },
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
||||
Generated
+5139
File diff suppressed because it is too large
Load Diff
@@ -131,6 +131,10 @@ export function mdxSafeProse(prose) {
|
||||
let s = p.s.replace(/<!--[\s\S]*?-->/g, "");
|
||||
s = s.replace(/[{}]/g, (c) => `\\${c}`);
|
||||
s = s.replace(/<(?!\/?(?:details|summary)\s*>)/g, "<");
|
||||
// Put each details/summary tag on its own line with blank lines around it, so the
|
||||
// markdown inside <details> is parsed as markdown rather than as JSX text.
|
||||
s = s.replace(/[ \t]*(<details>|<\/details>|<summary>[^\n]*?<\/summary>)[ \t]*/g, "\n\n$1\n\n");
|
||||
s = s.replace(/\n{3,}/g, "\n\n");
|
||||
return s;
|
||||
})
|
||||
.join("");
|
||||
|
||||
@@ -79,7 +79,7 @@ test("sync_pairs_code_tabs", () => {
|
||||
test("sync_strips_comments_and_escapes_mdx", () => {
|
||||
const out = mdxSafeProse("a <!-- Task 17: re-verify --> b {x} and `{kept}` <details><summary>S</summary> 1 < 2");
|
||||
assert.doesNotMatch(out, /<!--/);
|
||||
assert.match(out, /a b \\\{x\\\} and `\{kept\}` <details><summary>S<\/summary> 1 < 2/);
|
||||
assert.match(out, /a b \\\{x\\\} and `\{kept\}`\n\n<details>\n\n<summary>S<\/summary>\n\n1 < 2/);
|
||||
const root = fixture({ "01-a": `# A\n\n<!-- hidden -->\n\n${FENCE}rust\nif a < b { <!-- keep --> }\n${FENCE}\n` });
|
||||
const page = run(root)("01-a.mdx");
|
||||
assert.doesNotMatch(page, /hidden/);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: About
|
||||
description: Licence, source repository and how to report errors.
|
||||
sidebar:
|
||||
order: 2
|
||||
---
|
||||
|
||||
A free course on extensible systemic game design, in Rust and TypeScript.
|
||||
|
||||
- **Licence**: MIT. Copy, adapt and teach from it. See the [LICENSE](https://gitea.lucaswinther.info/lucasw89/systemic-game-design-course/src/branch/main/LICENSE).
|
||||
- **Source**: [gitea.lucaswinther.info/lucasw89/systemic-game-design-course](https://gitea.lucaswinther.info/lucasw89/systemic-game-design-course). The lessons on this site are generated from the `course/` directory of that repository.
|
||||
- **Found an error?** Open an issue in the [Gitea issue tracker](https://gitea.lucaswinther.info/lucasw89/systemic-game-design-course/issues) with the page and what is wrong (a wrong prediction, a test that fails against a correct solution, a dead link).
|
||||
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Disclaimer
|
||||
description: Trademarks, quoted card text and licensing.
|
||||
sidebar:
|
||||
order: 1
|
||||
---
|
||||
|
||||
This course is an independent, non-commercial educational project.
|
||||
|
||||
- It is **not affiliated with or endorsed by Blizzard Entertainment or Hempuli**. Hearthstone is a trademark of Blizzard Entertainment. Baba Is You is a creation of Hempuli. All trademarks and game names belong to their respective owners.
|
||||
- Short card and rule texts are quoted for **educational commentary** on game design. No game assets, code or data from those games are included.
|
||||
- SpellGrid and all other course content are original.
|
||||
- The course is **free**, and released under the MIT license.
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Systemic Design Course
|
||||
description: A free, hands-on course on extensible systemic game design, in Rust and TypeScript.
|
||||
template: splash
|
||||
hero:
|
||||
tagline: Rebuild the rules machinery of Hearthstone and Baba Is You, then prove your design by adding content without touching the engine.
|
||||
actions:
|
||||
- text: Start with Module 0
|
||||
link: /course/00-rewrite-trap/
|
||||
icon: right-arrow
|
||||
- text: Source on Gitea
|
||||
link: https://gitea.lucaswinther.info/lucasw89/systemic-game-design-course
|
||||
variant: minimal
|
||||
---
|
||||
|
||||
import { Card, CardGrid } from "@astrojs/starlight/components";
|
||||
|
||||
## What this is
|
||||
|
||||
A free course on **systemic game design**. You learn by rebuilding the rules machinery of two games, then extending it:
|
||||
|
||||
- **Part I: Hearthstone**: cards, zones, triggers, death phases, auras, text assembly.
|
||||
- **Part II: Baba Is You**: rules as pushable text, parsing, movement, win and lose.
|
||||
- **Part III: SpellGrid**: a small original game that combines both systems.
|
||||
|
||||
Every module follows the same beats: Observe, Predict, Spec, Build, Name it, Expansion Drop, Further reading. The Expansion Drop is the test of your design: you add new content without touching the engine.
|
||||
|
||||
## Pick your path
|
||||
|
||||
<CardGrid>
|
||||
<Card title="Solo" icon="open-book">
|
||||
Read the lessons and scenarios, predict outcomes, and reason about the design (designer path), or also make the tests pass in your own engine (builder path).
|
||||
</Card>
|
||||
<Card title="With an AI mentor" icon="rocket">
|
||||
Install the [mentor skill](https://gitea.lucaswinther.info/lucasw89/systemic-game-design-course/src/branch/main/mentor/README.md). Your agent asks, you build: it never writes your engine or content and releases hints one tier at a time.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
## Two tracks
|
||||
|
||||
Every code sample and exercise exists in **Rust** and **TypeScript**. Pick one and stay with it; the language tabs in the lessons remember your choice.
|
||||
|
||||
## Modules
|
||||
|
||||
- [Module 0: The Rewrite Trap](/course/00-rewrite-trap/)
|
||||
- [Module 1: Handles and order of play](/course/01-handles/)
|
||||
- [Module 2: The action queue, depth-first](/course/02-action-queue/)
|
||||
- [Module 3: Deferred death](/course/03-death-step/)
|
||||
- [Module 4: Interceptors and "trigger twice"](/course/04-interceptors/)
|
||||
- [Module 5: Behavior as data and Assemble](/course/05-assemble/)
|
||||
- [Module 6: Grid, lexer and parser](/course/06-parser/)
|
||||
- [Module 7: Resolving rules: NOT, identity, meta-nouns](/course/07-rule-resolution/)
|
||||
- [Module 8: Push chains: validate, then commit](/course/08-push-chains/)
|
||||
- [Module 9: The turn pipeline](/course/09-turn-pipeline/)
|
||||
- [Module 10: SpellGrid](/course/10-spellgrid/)
|
||||
- [Harness contract](/course/harness/) (reference)
|
||||
|
||||
See also the [disclaimer](/disclaimer/) and [about](/about/) pages.
|
||||
Reference in New Issue
Block a user