From 35c0b727e7d5fadd5f01eb5b1ef8dc9f9181a3aa Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 8 May 2026 15:29:54 +0000 Subject: [PATCH 1/8] Rename website/ directory to app/ https://claude.ai/code/session_01MqEqGhP1guGx5VuFsLaws2 --- {website => app}/assets/fonts/.gitkeep | 0 {website => app}/assets/images/.gitkeep | 0 {website => app}/config.yml | 0 {website => app}/index.html | 0 {website => app}/nav.yml | 0 {website => app}/pages/home.md | 0 {website => app}/posts/.gitkeep | 0 {website => app}/search.json | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename {website => app}/assets/fonts/.gitkeep (100%) rename {website => app}/assets/images/.gitkeep (100%) rename {website => app}/config.yml (100%) rename {website => app}/index.html (100%) rename {website => app}/nav.yml (100%) rename {website => app}/pages/home.md (100%) rename {website => app}/posts/.gitkeep (100%) rename {website => app}/search.json (100%) diff --git a/website/assets/fonts/.gitkeep b/app/assets/fonts/.gitkeep similarity index 100% rename from website/assets/fonts/.gitkeep rename to app/assets/fonts/.gitkeep diff --git a/website/assets/images/.gitkeep b/app/assets/images/.gitkeep similarity index 100% rename from website/assets/images/.gitkeep rename to app/assets/images/.gitkeep diff --git a/website/config.yml b/app/config.yml similarity index 100% rename from website/config.yml rename to app/config.yml diff --git a/website/index.html b/app/index.html similarity index 100% rename from website/index.html rename to app/index.html diff --git a/website/nav.yml b/app/nav.yml similarity index 100% rename from website/nav.yml rename to app/nav.yml diff --git a/website/pages/home.md b/app/pages/home.md similarity index 100% rename from website/pages/home.md rename to app/pages/home.md diff --git a/website/posts/.gitkeep b/app/posts/.gitkeep similarity index 100% rename from website/posts/.gitkeep rename to app/posts/.gitkeep diff --git a/website/search.json b/app/search.json similarity index 100% rename from website/search.json rename to app/search.json From 24670a66dd60f5f07fdfd91eaa785fbbda94beea Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 8 May 2026 16:05:04 +0000 Subject: [PATCH 2/8] Rebuild mdcms as proper CLI tool (v0.3) - Replace interactive TUI with click-based subcommands: register, delete, view, build - build accepts NAME (registry), --path, or CWD for GitHub Actions use - Switch to PyYAML for frontmatter and nav.yml parsing - Add pyproject.toml with click + PyYAML deps and mdcms entry point - Add v0.3 version marker to app/config.yml and app/index.html - Registry moves to ~/.config/mdcms/sites.json (XDG-compliant) - Project root is now the directory containing index.html (no website/ subdir) - register auto-downloads template from GitHub if no site found https://claude.ai/code/session_01MqEqGhP1guGx5VuFsLaws2 --- app/config.yml | 3 +- app/index.html | 3 +- mdcms.py | 1470 +++++++++++++----------------------------------- pyproject.toml | 26 + 4 files changed, 413 insertions(+), 1089 deletions(-) create mode 100644 pyproject.toml diff --git a/app/config.yml b/app/config.yml index 6c32f19..86727da 100644 --- a/app/config.yml +++ b/app/config.yml @@ -1,4 +1,5 @@ -# MD-CMS v0.2 — Site configuration +# mdcms v0.3 | DO NOT REMOVE THIS COMMENT +# MD-CMS v0.3 — Site configuration # # Only `sitename` and `navigation` are required. Uncomment and edit the rest # as needed. See https://kbenestad.codeberg.page/md-cms for the full reference. diff --git a/app/index.html b/app/index.html index ec16766..a80ba18 100644 --- a/app/index.html +++ b/app/index.html @@ -1,5 +1,6 @@ + ` + +`register` and `build` both read the marker from `config.yml` to detect and validate the site. Sites with no marker are not recognised as mdcms sites. Sites below `MIN_SUPPORTED_VERSION` are rejected. + +There are two distinct version numbers: +- **CLI version** (`CLI_VERSION` in `mdcms.py`, `version` in `pyproject.toml`) — bumped with every release. +- **Site format version** (markers in `config.yml` and `index.html`) — only bumped when the site file format has a breaking change. Many CLI releases may share the same site format version. + +## Site structure + +The registered path points directly to the directory containing `index.html` (the site root). There is no `website/` subdirectory. ``` -website/ - index.html ← renderer (edit to change site behaviour) +/ + index.html ← renderer config.yml ← required: sitename, navigation; rest optional - nav.yml ← generated; manual edits to section metadata are preserved on rebuild + nav.yml ← generated; manual edits to section metadata are preserved search.json ← generated pages/ home.md ← default landing page - about.md ← default variant + about.md about.nb.md ← Norwegian variant (category suffix = nb) posts/ 2025-01-01-my-first-post.md @@ -113,15 +150,35 @@ paginate: yes Reliable tags (others are known-broken): `posts-datetime-chronological-byyearmonth`, `posts-datetime-reversechronological`. Use `datetime` frontmatter (format: `YYYY-MM-DD HH:MM`) for posts — `date` alone does not work reliably. +## Release workflow + +`.github/workflows/release.yml` triggers on version tags (`v*`). Uses a matrix of three runners: + +| Runner | Output | +|---|---| +| `ubuntu-latest` | `mdcms-linux-amd64` binary + `mdcms__amd64.deb` (via PyInstaller + fpm) | +| `macos-latest` | `mdcms-macos-arm64` binary | +| `windows-latest` | `mdcms-windows-amd64.exe` | + +All artifacts are attached to the GitHub release using `gh release create`. + +**Release checklist** — before tagging: +1. Update `CLI_VERSION` in `mdcms.py` +2. Update `version` in `pyproject.toml` +3. Update site format markers in `app/config.yml` and `app/index.html` only if the site format changed + +Then: `git tag v0.3.1 && git push origin v0.3.1` + ## Known limitations -- `mdcms.py` always expects the deployable site in a `website/` subdirectory of the registered project path. - Most `posts-*` tag variants are broken. Only `posts-datetime-chronological-byyearmonth` and `posts-datetime-reversechronological` reliably work. - Section headings in the nav are non-clickable (sections-sitemap is not yet implemented). ## Key implementation details -- `parse_nav_yml()` and `parse_config_categories()` are **not** general YAML parsers — they only handle the exact indentation/format that `mdcms.py` itself produces. Do not assume they handle arbitrary YAML. +- `generate_nav_yml()` emits a fixed-format YAML subset. It is **not** a general YAML emitter — do not assume it handles arbitrary structures. +- `yaml.safe_load()` is used for all YAML reading (config.yml, nav.yml, frontmatter). The nav.yml parser depends on PyYAML, not a hand-rolled parser. - Category code validation uses `CATEGORY_CODE_RE = re.compile(r"^[a-zA-Z0-9\-]+$")` — codes must match this. +- `scan_and_categorize()` takes both `directory` and `site_root` — paths in records are always relative to `site_root`. - The `samplesite/` directory is a reference implementation with multi-language categories (English, Norwegian, Arabic including RTL). It is not deployed; it exists for reference and testing. -- `website/` in the repo root is a minimal starter template (single page, no categories). +- Template download uses `urllib` (stdlib) only — no `requests` dependency. From 0d0dfa7268f9badfc10b6582caf1a8ea3827f92c Mon Sep 17 00:00:00 2001 From: kbenestad Date: Fri, 8 May 2026 23:34:06 +0700 Subject: [PATCH 7/8] Add release guide for mdcms This guide provides detailed steps for releasing a new version of mdcms, including prerequisites, setup, version bumping, tagging, and monitoring the build process. --- docs/release.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 docs/release.md diff --git a/docs/release.md b/docs/release.md new file mode 100644 index 0000000..baceab2 --- /dev/null +++ b/docs/release.md @@ -0,0 +1,92 @@ +# Releasing a new version of mdcms + +This guide covers publishing a new mdcms release — producing binaries, a `.deb` package, and a GitHub release with all artifacts attached. + +## Prerequisites + +- Push access to `kbenestad/mdcms` on GitHub +- GitHub Actions enabled on the repository (it is by default on new repos) + +## One-time GitHub setup + +### Enable workflow write permissions + +The release workflow creates a GitHub release using the built-in `GITHUB_TOKEN`. You need to confirm it has write access: + +1. Go to your repository on GitHub +2. **Settings → Actions → General** +3. Scroll to **Workflow permissions** +4. Select **Read and write permissions** +5. Click **Save** + +That's the only setup required. No secrets, no tokens, no third-party services. + +## The release checklist + +Before tagging a release, update the version number in two places: + +**`mdcms.py`** — find this line near the top and bump it: +```python +CLI_VERSION = "0.3.1" +``` + +**`pyproject.toml`** — bump the matching line: +```toml +version = "0.3.1" +``` + +> **Site format version** — the markers in `app/config.yml` and `app/index.html` (`# mdcms v0.3`) are separate from the CLI version. Only update them if the site file format has a breaking change that requires users to re-download the template. Most releases do not touch these. + +Commit the version bump: +```bash +git add mdcms.py pyproject.toml +git commit -m "Bump version to 0.3.1" +git push origin main +``` + +## Tagging the release + +Push a version tag to trigger the workflow: +```bash +git tag v0.3.1 +git push origin v0.3.1 +``` + +The tag must start with `v`. The workflow triggers immediately. + +> **Pre-releases** — if the tag contains a hyphen (e.g. `v0.4.0-beta.1`), the GitHub release is automatically marked as pre-release. + +## What the workflow does + +The workflow (`.github/workflows/release.yml`) runs three parallel jobs: + +| Runner | Output | +|---|---| +| `ubuntu-latest` | `mdcms-linux-amd64` (standalone binary) + `mdcms_0.3.1_amd64.deb` | +| `macos-latest` | `mdcms-macos-arm64` (standalone binary) | +| `windows-latest` | `mdcms-windows-amd64.exe` | + +Each binary is built with PyInstaller — Python is bundled inside, so end users need nothing pre-installed. The `.deb` is built with `fpm` and installs mdcms to `/usr/local/bin`. + +A final job collects all artifacts and creates the GitHub release with auto-generated release notes. + +## Monitoring the build + +1. Go to **Actions** on the repository +2. Click the workflow run triggered by your tag +3. Each platform job takes roughly 3–5 minutes + +If a job fails, the release is not created. Fix the issue, delete the tag, and re-push: +```bash +git tag -d v0.3.1 +git push origin --delete v0.3.1 +# fix the issue, then re-tag +git tag v0.3.1 +git push origin v0.3.1 +``` + +## The finished release + +Once all jobs pass, the release appears under **Releases** on the repository with: +- Auto-generated changelog (commits since the last tag) +- All four artifacts attached for download From 01341db24bb700fb90eff63318a72d7b2590de6b Mon Sep 17 00:00:00 2001 From: kbenestad Date: Fri, 8 May 2026 23:34:34 +0700 Subject: [PATCH 8/8] Add installation and setup guide for mdcms This guide details the installation of mdcms, site registration, local builds, and GitHub Actions setup for automatic updates. --- docs/install.md | 161 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 docs/install.md diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 0000000..294ccf6 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,161 @@ +# Setting up mdcms for your site + +This guide walks through installing mdcms, registering your site, and setting up automatic builds on GitHub so that `nav.yml` and `search.json` are always up to date when you push content. + +## 1. Install mdcms + +Choose one method: + +**Standalone binary (no Python required — recommended for most users)** + +Download the binary for your platform from the [latest release](https://github.com/kbenestad/mdcms/releases/latest): + +- **Linux:** `mdcms-linux-amd64` → move to `/usr/local/bin/mdcms` and `chmod +x` +- **Linux (deb):** `mdcms__amd64.deb` → `sudo dpkg -i mdcms__amd64.deb` +- **macOS:** `mdcms-macos-arm64` → move to `/usr/local/bin/mdcms` and `chmod +x` +- **Windows:** `mdcms-windows-amd64.exe` → rename to `mdcms.exe` and place it somewhere on your PATH + +**Via pipx (Python users)** +```bash +pipx install mdcms +``` + +Verify the installation: +```bash +mdcms --version +``` + +--- + +## 2. Register your site + +Navigate to your site directory (where `index.html` lives) and register it: + +```bash +cd /path/to/your/site +mdcms register mysite +``` + +Or pass the path explicitly: +```bash +mdcms register mysite /path/to/your/site +``` + +**If no mdcms site exists at that path**, mdcms will download the starter template from GitHub automatically — `index.html`, `config.yml`, `pages/`, `posts/`, and `assets/` will be created for you. + +**If a site already exists** (you cloned an existing mdcms repo), mdcms will detect the version marker in `config.yml` and register it as-is. + +--- + +## 3. Edit your config + +Open `config.yml` in your site directory and set at minimum: + +```yaml +sitename: Your Site Name +navigation: topbar # or: sidebar +``` + +--- + +## 4. Build locally + +Run a build to generate `nav.yml` and `search.json` from your content: + +```bash +mdcms build mysite +``` + +Check your site by starting a local server: +```bash +cd /path/to/your/site +python3 -m http.server 8800 +``` + +Then open `http://localhost:8800` in your browser. + +--- + +## 5. Set up automatic builds on GitHub + +When you push new pages or posts to GitHub, you'll want `nav.yml` and `search.json` rebuilt automatically. This is done with a simple GitHub Actions workflow. + +### One-time GitHub setup + +1. Go to your site repository on GitHub +2. **Settings → Actions → General** +3. Under **Workflow permissions**, select **Read and write permissions** +4. Click **Save** + +This allows the workflow to commit the rebuilt files back to your repository. + +### Add the workflow file + +Create `.github/workflows/build.yml` in your site repository with this content: + +```yaml +name: Build + +on: + push: + branches: + - main + paths: + - "pages/**" + - "posts/**" + - "config.yml" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Install mdcms + run: pip install mdcms + + - name: Build + run: mdcms build + + - name: Commit updated files + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add nav.yml search.json + git diff --staged --quiet || git commit -m "Build: update nav.yml and search.json" + git push +``` + +Commit and push this file to your repository. From that point on, every push that touches `pages/`, `posts/`, or `config.yml` will automatically rebuild and commit `nav.yml` and `search.json`. + +> The workflow only commits if the files actually changed — `git diff --staged --quiet` skips the commit if nothing is different. + +--- + +## Day-to-day workflow + +1. Write or edit a page in `pages/` or a post in `posts/` +2. Commit and push to `main` +3. GitHub Actions rebuilds `nav.yml` and `search.json` automatically (~30 seconds) +4. Your deployed site picks up the changes immediately + +To build locally at any time (without pushing): +```bash +mdcms build mysite +``` + +--- + +## Useful commands + +```bash +mdcms view # list all registered sites +mdcms view mysite # show details for a site +mdcms build mysite # build nav.yml + search.json +mdcms build --path . # build from current directory (no registry needed) +mdcms delete mysite # remove a site from the local registry +```