diff --git a/src/pages/models.astro b/src/pages/models.astro
index d910e47..041166f 100644
--- a/src/pages/models.astro
+++ b/src/pages/models.astro
@@ -8,8 +8,22 @@ import { getEntry } from 'astro:content';
import ChapterLayout from '../layouts/ChapterLayout.astro';
import ChapterHero from '../components/blocks/ChapterHero.astro';
+// Required-field guard. The chapters schema marks section eyebrow /
+// panelLabel / panelCode / steps / copy as optional because the schema
+// does not know which page consumes which shape. These four pages do
+// consume them — fail loudly here rather than rendering a blank section.
+function requireField
(value: T | undefined, name: string): T {
+ if (value === undefined) {
+ throw new Error(`models chapter: missing required field "${name}"`);
+ }
+ return value;
+}
+
const base = import.meta.env.BASE_URL;
const chapter = await getEntry('chapters', 'models');
+if (!chapter) {
+ throw new Error('models chapter: missing collection entry');
+}
const lede = chapter.data.lede.en;
const title = chapter.data.title.en;
const eyebrow = chapter.data.eyebrow.en;
@@ -18,6 +32,17 @@ const sections = chapter.data.sections ?? [];
// First section carries the routing-rule panel, second carries the steps.
const ruleSection = sections[0];
const sequenceSection = sections[1];
+if (!ruleSection) {
+ throw new Error('models chapter: missing sections[0]');
+}
+if (!sequenceSection) {
+ throw new Error('models chapter: missing sections[1]');
+}
+const ruleEyebrow = requireField(ruleSection.eyebrow, 'sections[0].eyebrow');
+const rulePanelLabel = requireField(ruleSection.panelLabel, 'sections[0].panelLabel');
+const rulePanelCode = requireField(ruleSection.panelCode, 'sections[0].panelCode');
+const sequenceEyebrow = requireField(sequenceSection.eyebrow, 'sections[1].eyebrow');
+const sequenceSteps = requireField(sequenceSection.steps, 'sections[1].steps');
---
]+>/g, '')}>
@@ -44,23 +69,23 @@ const sequenceSection = sections[1];
-
{ruleSection.eyebrow.en}
+
{ruleEyebrow.en}
- {ruleSection.panelLabel.en}
- {ruleSection.panelCode.en}
+ {rulePanelLabel.en}
+ {rulePanelCode.en}
-
{sequenceSection.eyebrow.en}
+
{sequenceEyebrow.en}
{
- sequenceSection.steps.map((step, index) => (
+ sequenceSteps.map((step, index) => (
{String(index + 1).padStart(2, '0')}
diff --git a/src/pages/skills.astro b/src/pages/skills.astro
index a31fdf2..9e9518b 100644
--- a/src/pages/skills.astro
+++ b/src/pages/skills.astro
@@ -10,14 +10,38 @@ import ChapterHero from '../components/blocks/ChapterHero.astro';
import SkillPackageExplorer from '../components/islands/SkillPackageExplorer.astro';
import skillsStylesheet from '../../skills/styles.css?url';
+// Required-field guard. The chapters schema marks section eyebrow /
+// panelLabel / panelCode / steps / copy as optional because the schema
+// does not know which page consumes which shape. These four pages do
+// consume them — fail loudly here rather than rendering a blank section.
+function requireField
(value: T | undefined, name: string): T {
+ if (value === undefined) {
+ throw new Error(`skills chapter: missing required field "${name}"`);
+ }
+ return value;
+}
+
const base = import.meta.env.BASE_URL;
const chapter = await getEntry('chapters', 'skills');
+if (!chapter) {
+ throw new Error('skills chapter: missing collection entry');
+}
const lede = chapter.data.lede.en;
const title = chapter.data.title.en;
const eyebrow = chapter.data.eyebrow.en;
const sections = chapter.data.sections ?? [];
const anatomySection = sections[0];
const createSection = sections[1];
+if (!anatomySection) {
+ throw new Error('skills chapter: missing sections[0]');
+}
+if (!createSection) {
+ throw new Error('skills chapter: missing sections[1]');
+}
+const anatomyEyebrow = requireField(anatomySection.eyebrow, 'sections[0].eyebrow');
+const anatomyCopy = requireField(anatomySection.copy, 'sections[0].copy');
+const createEyebrow = requireField(createSection.eyebrow, 'sections[1].eyebrow');
+const createSteps = requireField(createSection.steps, 'sections[1].steps');
---
]+>/g, '')}>
@@ -33,21 +57,21 @@ const createSection = sections[1];
-
{anatomySection.eyebrow.en}
+
{anatomyEyebrow.en}
-
{anatomySection.copy.en}
+
{anatomyCopy.en}
-
{createSection.eyebrow.en}
+
{createEyebrow.en}
{
- createSection.steps.map((step, index) => (
+ createSteps.map((step, index) => (
{String(index + 1).padStart(2, '0')}