Skip to content

Commit bd61dff

Browse files
committed
ProstDev site — Astro 5 static site (initial public history)
MuleSoft video tutorials + AI-friendly blog posts. Migrated off Wix. Builds + deploys to GitHub Pages via .github/workflows/deploy.yml. Internal Claude Code tooling + CLAUDE.md live in the private ProstDev/prostdev-internal repo, mounted at .claude/ as a submodule; root CLAUDE.md is a symlink into it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0 parents  commit bd61dff

1,491 files changed

Lines changed: 43349 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude‎

Submodule .claude added at a16c7a7
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
name: Check DataWeave version
2+
3+
# Watches the LIVE MuleSoft docs for a newer DataWeave version (or newly added
4+
# dw::Core functions) than the cheatsheet records, and opens/updates ONE tracking
5+
# issue when the article is out of date. It NEVER edits the article — the verbatim
6+
# sync is a human/`dataweave-reference-syncer` job (see CLAUDE.md).
7+
#
8+
# Trigger: weekly cron + manual. (MuleSoft publishes no RSS feed for releases, and
9+
# the version source is external to this repo, so a schedule is the right shape —
10+
# `push` would mostly re-check after unrelated commits. Run "Run workflow" anytime.)
11+
12+
on:
13+
schedule:
14+
- cron: '0 13 * * 1' # every Monday 13:00 UTC
15+
workflow_dispatch:
16+
17+
permissions:
18+
contents: read
19+
issues: write
20+
21+
concurrency:
22+
group: check-dataweave-version
23+
cancel-in-progress: false
24+
25+
jobs:
26+
check:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout
30+
uses: actions/checkout@v4
31+
32+
- name: Set up Node
33+
uses: actions/setup-node@v4
34+
with:
35+
node-version: 20
36+
37+
- name: Check cheatsheet vs. live DataWeave docs
38+
id: check
39+
run: node scripts/check-dataweave-version.mjs
40+
41+
- name: Open / update tracking issue
42+
if: steps.check.outputs.outdated == 'true'
43+
uses: actions/github-script@v7
44+
env:
45+
ISSUE_TITLE: ${{ steps.check.outputs.issue_title }}
46+
ISSUE_BODY: ${{ steps.check.outputs.issue_body }}
47+
LIVE_VERSION: ${{ steps.check.outputs.live_version }}
48+
with:
49+
script: |
50+
const { ISSUE_TITLE, ISSUE_BODY, LIVE_VERSION } = process.env;
51+
const label = 'dataweave-version';
52+
53+
// Ensure the label exists (ignore "already exists").
54+
try {
55+
await github.rest.issues.createLabel({
56+
owner: context.repo.owner, repo: context.repo.repo,
57+
name: label, color: '0e8a16',
58+
description: 'DataWeave cheatsheet out of date vs. the live docs',
59+
});
60+
} catch (e) { if (e.status !== 422) throw e; }
61+
62+
// Reuse the existing open tracking issue if there is one (don't spam a
63+
// new issue every week — update the body and ping instead).
64+
const existing = await github.paginate(github.rest.issues.listForRepo, {
65+
owner: context.repo.owner, repo: context.repo.repo,
66+
state: 'open', labels: label, per_page: 100,
67+
});
68+
69+
if (existing.length) {
70+
const issue = existing[0];
71+
await github.rest.issues.update({
72+
owner: context.repo.owner, repo: context.repo.repo,
73+
issue_number: issue.number, title: ISSUE_TITLE, body: ISSUE_BODY,
74+
});
75+
await github.rest.issues.createComment({
76+
owner: context.repo.owner, repo: context.repo.repo,
77+
issue_number: issue.number,
78+
body: `🔁 Re-checked: docs \`latest\` is at **${LIVE_VERSION}**. Details updated above.`,
79+
});
80+
core.info(`Updated existing issue #${issue.number}`);
81+
} else {
82+
const created = await github.rest.issues.create({
83+
owner: context.repo.owner, repo: context.repo.repo,
84+
title: ISSUE_TITLE, body: ISSUE_BODY, labels: [label],
85+
});
86+
core.info(`Opened issue #${created.data.number}`);
87+
}

‎.github/workflows/deploy.yml‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Deploy to GitHub Pages
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
pages: write
11+
id-token: write
12+
13+
# Allow one concurrent deployment, cancel in-progress runs on new pushes.
14+
concurrency:
15+
group: pages
16+
cancel-in-progress: true
17+
18+
jobs:
19+
build:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
- name: Install, build, and upload
25+
uses: withastro/action@v4
26+
# withastro/action runs `npm ci && npm run build` (which also runs
27+
# `pagefind --site dist`) and uploads ./dist as the Pages artifact.
28+
29+
deploy:
30+
needs: build
31+
runs-on: ubuntu-latest
32+
environment:
33+
name: github-pages
34+
url: ${{ steps.deployment.outputs.page_url }}
35+
steps:
36+
- name: Deploy to GitHub Pages
37+
id: deployment
38+
uses: actions/deploy-pages@v4

‎.gitignore‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# build output
2+
dist/
3+
# generated types
4+
.astro/
5+
# dependencies
6+
node_modules/
7+
# logs
8+
npm-debug.log*
9+
yarn-debug.log*
10+
yarn-error.log*
11+
pnpm-debug.log*
12+
# environment variables
13+
.env
14+
.env.production
15+
# macOS
16+
.DS_Store
17+
# jetbrains setting folder
18+
.idea/
19+
# gist-recovery scratch (regenerable; see scripts/recover-gists.mjs)
20+
gist-cache.json
21+
gist-recovery-proposals.json

‎.gitmodules‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule ".claude"]
2+
path = .claude
3+
url = https://github.com/ProstDev/prostdev-internal.git

‎CLAUDE.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.claude/CLAUDE.md

‎README.md‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# ProstDev
2+
3+
The ProstDev website — MuleSoft video tutorials and AI-friendly blog posts. Built with
4+
[Astro](https://astro.build), hosted free on GitHub Pages.
5+
6+
Replaces the previous Wix site. **Primary focus: YouTube videos.** Secondary focus:
7+
SEO/AEO-optimized blog posts that AI and search engines can read.
8+
9+
## Develop
10+
11+
```bash
12+
npm install
13+
npm run dev # http://localhost:4321
14+
```
15+
16+
```bash
17+
npm run build # astro build + pagefind (search index)
18+
npm run preview # serve the production build locally (search works here)
19+
```
20+
21+
> Search (Pagefind) only works against a built site — use `npm run build && npm run preview`,
22+
> not `npm run dev`.
23+
24+
## Add a new video
25+
26+
Edit [`src/data/videos.ts`](src/data/videos.ts):
27+
28+
1. Add a `Video` entry near the **top** of the `VIDEOS` array (newest first) with a unique
29+
`slug`, the `youtubeId`, title, description, and which `playlists` it belongs to.
30+
2. (Optional but recommended) Add a transcript at
31+
`src/content/transcripts/<youtubeId>.md` so the video is AI-readable and searchable.
32+
3. Commit & push — GitHub Actions rebuilds and deploys automatically.
33+
34+
Each video gets a page at `/video/<slug>`, a raw-markdown version at `/video/<slug>.md`, and
35+
is included in `/llms.txt` + `/llms-full.txt`.
36+
37+
## Add a blog post
38+
39+
Create `src/content/blog/<slug>.mdx` with frontmatter:
40+
41+
```yaml
42+
---
43+
title: 'Your title'
44+
description: 'One-sentence summary (used for SEO + cards).'
45+
pubDate: 2026-01-15
46+
category: Tutorials # Challenges | Tutorials | Guides | Opinion | News
47+
tags: [MuleSoft, DataWeave]
48+
youtubeId: abc123 # optional — embeds the video at the top
49+
heroImage: ./cover.png # optional
50+
draft: false # drafts are hidden in production
51+
---
52+
```
53+
54+
Posts render at `/post/<slug>` with an auto "On this page" nav, a Copy/View-as-Markdown menu,
55+
and `/post/<slug>.md` raw markdown.
56+
57+
## Machine-readable / AEO endpoints
58+
59+
- `/llms.txt` — curated index of all videos + posts ([llmstxt.org](https://llmstxt.org) format)
60+
- `/llms-full.txt` — every post body + video transcript concatenated
61+
- `/post/<slug>.md`, `/video/<slug>.md` — raw markdown per page
62+
- `/rss.xml`, `/sitemap-index.xml`, `/robots.txt`
63+
64+
## Deploy / DNS cutover
65+
66+
Pushing to `main` triggers `.github/workflows/deploy.yml`, which builds and deploys to
67+
GitHub Pages. The custom domain is set via [`public/CNAME`](public/CNAME) (`prostdev.com`).
68+
69+
**One-time setup:**
70+
71+
1. In the GitHub repo: **Settings → Pages → Source → GitHub Actions**.
72+
2. Verify the site works at the temporary `*.github.io` URL.
73+
3. **Then** update DNS at your registrar (away from Wix):
74+
- Apex `prostdev.com`: A records to GitHub Pages IPs
75+
`185.199.108.153`, `185.199.109.153`, `185.199.110.153`, `185.199.111.153`
76+
(and AAAA records for IPv6 if desired).
77+
- `www`: CNAME → `<github-username>.github.io`.
78+
4. In Settings → Pages, set the custom domain to `prostdev.com` and enable **Enforce HTTPS**.
79+
80+
Keep Wix live until the new site is verified, to avoid downtime.

‎astro.config.mjs‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// @ts-check
2+
import { defineConfig } from 'astro/config';
3+
import mdx from '@astrojs/mdx';
4+
import sitemap from '@astrojs/sitemap';
5+
import tailwindcss from '@tailwindcss/vite';
6+
import remarkCallouts from './src/lib/remark-callouts.mjs';
7+
import rehypeTables from './src/lib/rehype-tables.mjs';
8+
import shikiCodeTitle from './src/lib/shiki-code-title.mjs';
9+
10+
// https://astro.build/config
11+
export default defineConfig({
12+
site: 'https://prostdev.com',
13+
trailingSlash: 'ignore',
14+
// This post was first migrated under a SHORTENED slug that never existed on Wix
15+
// (the live URL is the long one). Redirect the old short path to the canonical
16+
// live slug so any stale internal/SEO link doesn't 404.
17+
redirects: {
18+
'/post/getting-started-with-anypoint-code-builder':
19+
'/post/getting-started-with-anypoint-code-builder-in-vs-code-beginner-guide',
20+
},
21+
integrations: [mdx(), sitemap()],
22+
vite: {
23+
plugins: [tailwindcss()],
24+
},
25+
markdown: {
26+
// Transform GitHub alert blockquotes (`> [!NOTE]`) into styled callout boxes at build time.
27+
// See src/lib/remark-callouts.mjs + the `.callout*` styles in src/styles/global.css.
28+
remarkPlugins: [remarkCallouts],
29+
// Wrap GFM tables in a responsive scroll container + add scope="col" to headers.
30+
// See src/lib/rehype-tables.mjs + the `.table-wrap` / `.prose table` styles in global.css.
31+
rehypePlugins: [rehypeTables],
32+
shikiConfig: {
33+
themes: {
34+
light: 'github-light',
35+
dark: 'github-dark',
36+
},
37+
// DataWeave has no built-in Shiki grammar; alias to Scala for decent
38+
// highlighting of its functional/typed syntax.
39+
langAlias: {
40+
dataweave: 'scala',
41+
dwl: 'scala',
42+
},
43+
// Lift an optional `title="file.ext"` from a fence's meta onto a
44+
// `data-title` attr; CodeBlockEnhancer renders it in the header bar.
45+
transformers: [shikiCodeTitle()],
46+
wrap: true,
47+
},
48+
},
49+
});

0 commit comments

Comments
 (0)