Astro static site that publishes the workshop lessons from ODrive-Custom to GitHub Pages.
thomasiverson/ODrive-Custom (fork — syncs with upstream)
├── lessons/ ← source of truth for content
└── .github/workflows/
└── trigger-site-rebuild.yml ← auto-triggers site rebuild on lesson changes
thomasiverson/odrive-workshop-site (this repo — Astro site)
├── scripts/sync-content.mjs ← copies lessons at build time
├── src/ ← Astro layouts, pages, content config
└── .github/workflows/
└── deploy.yml ← builds and deploys to GitHub Pages
- Node.js 18+
- Both repos cloned side by side:
repos/
├── ODrive-Custom/
└── odrive-workshop-site/
cd odrive-workshop-site
npm installnpm run sync # copies lessons from ../ODrive-Custom
npx astro dev # starts dev server at http://localhost:4321Open http://localhost:4321/odrive-workshop-site/ in your browser.
npm run build:local # syncs from local ODrive-Custom + builds
npx astro preview # preview the built site| Script | Description |
|---|---|
npm run sync |
Copy lessons from local ../ODrive-Custom into Astro content directory |
npm run sync:remote |
Clone lessons from GitHub repo (used in CI) |
npm run dev |
Start Astro dev server (run sync first) |
npm run build |
CI build: sync from GitHub + Astro build |
npm run build:local |
Local build: sync from local path + Astro build |
npm run preview |
Preview the built dist/ folder |
git add .
git commit -m "Initial Astro site for workshop lessons"
git push -u origin main- Go to https://github.com/thomasiverson/odrive-workshop-site/settings/pages
- Under Source, select GitHub Actions
The workflow at .github/workflows/deploy.yml triggers on every push to main and deploys automatically.
Live URL: https://thomasiverson.github.io/odrive-workshop-site/
A workflow in ODrive-Custom (.github/workflows/trigger-site-rebuild.yml) sends a repository_dispatch event to this repo whenever lessons/** changes on the main branch.
To set this up:
- Create a fine-grained personal access token:
- Go to https://github.com/settings/tokens?type=beta
- Name:
site-deploy-trigger - Repository access: Select
odrive-workshop-siteonly - Permissions: Contents → Read, Actions → Write
- Add the token as a secret in ODrive-Custom:
- Go to https://github.com/thomasiverson/ODrive-Custom/settings/secrets/actions
- Name:
SITE_DEPLOY_TOKEN - Value: the token from step 1
You can trigger a rebuild anytime from the GitHub Actions tab:
- Go to https://github.com/thomasiverson/odrive-workshop-site/actions
- Select Deploy to GitHub Pages
- Click Run workflow
Sync fork (GitHub UI or git pull upstream)
↓
ODrive-Custom/lessons/** changes land on main
↓
trigger-site-rebuild.yml fires → sends repository_dispatch
↓
odrive-workshop-site deploy.yml runs:
1. Clones ODrive-Custom (shallow, lessons/ only)
2. Runs sync-content.mjs (injects frontmatter, rewrites images)
3. Builds Astro
4. Deploys to GitHub Pages
↓
Live at thomasiverson.github.io/odrive-workshop-site/
The scripts/sync-content.mjs script:
- Copies all
lessons/**/*.mdfiles intosrc/content/lessons/ - Copies
lessons/**/images/intopublic/images/lessons/ - Auto-generates YAML frontmatter (title, order, type, slug) from folder names and first H1
- Rewrites relative image paths (
images/foo.png→/odrive-workshop-site/images/lessons/<slug>/foo.png) - Replaces broken image references with text placeholders
Content in src/content/lessons/ and public/images/lessons/ is gitignored — it's regenerated on every sync.
Open ODrive-Custom/odrive-workshop.code-workspace in VS Code to work on both repos side by side:
code ODrive-Custom/odrive-workshop.code-workspace| Issue | Solution |
|---|---|
npm run sync fails with "lessons/ not found" |
Make sure ODrive-Custom is cloned next to this repo |
| Dev server shows empty cards | Run npm run sync before npx astro dev |
| Images not loading | Run sync again — images are copied to public/images/lessons/ |
| GitHub Pages 404 | Verify Pages source is set to GitHub Actions in repo settings |
| Cross-repo trigger not firing | Check SITE_DEPLOY_TOKEN secret exists in ODrive-Custom with correct permissions |
| Build fails with ImageNotFound | A lesson references a missing image — sync script should replace it with a placeholder automatically |