Source for aixgo.dev — the marketing and documentation site for the Aixgo AI agent framework.
Looking to use Aixgo? Visit aixgo.dev or the framework repo at github.com/aixgo-dev/aixgo. This repo is for contributors to the website itself.
# One-time
brew install hugo # or: see gohugo.io/installation
make lint-install # npm ci -- the pinned markdownlint-cli2 + htmlhint
# Daily
make dev # http://localhost:1313 with live reload
make build # production build → public/
make lint # markdown + html lintThe lint toolchain is pinned in package.json at exact versions, with package-lock.json holding the full tree. make lint-install runs npm ci, and both lint targets run the local binaries through the lint:md / lint:html npm scripts — the same commands CI runs. Nothing installs these tools globally, so the linter grading a PR is never whatever npm served that morning. make check-lint-pins asserts the declaration is still exact and that no global install has crept back; it runs pre-merge in lint.yml.
The Hugo version is pinned in .hugo-version, which is the canonical value: CI builds with it, and local builds should match it (hugo version).
Cloudflare Pages cannot read that file — Pages supports no version file for Hugo, only the HUGO_VERSION project env var. So the dashboard value is a hand-maintained copy that must be updated to match whenever .hugo-version changes, in both the Production and Preview environments.
hugo-pin.yml runs daily and on any push that moves the pin, and fails when either environment has drifted. Run the pieces locally with make check-hugo (pin vs the hugo on your PATH) and make check-hugo-drift (the Cloudflare comparison against saved fixtures, no token needed).
config/_default/ # Hugo configuration (hugo.toml, params.toml, menus, ...)
content/ # Markdown content
├── guides/ # Technical guides
├── blog/ # Blog and release announcements
└── examples/ # YAML configuration examples
layouts/ # Hugo templates
├── _default/ # baseof.html, list.html, single.html
├── partials/ # Reusable components (head, header, footer, seo, posthog)
└── shortcodes/ # Markdown components (feature-card, status-badge, ...)
data/ # YAML data files driving content
├── features.yaml # Feature matrix (status indicators)
├── release.json # Homepage release fact (owned by the release-sync loop)
└── version.yaml # Site version metadata
static/ # Assets (css, js, favicon, _headers, CNAME)
archetypes/ # Hugo archetypes (templates for `hugo new`)
.markdownlint.json # Markdownlint config
.htmlhintrc # HTMLhint config
package.json # Pinned lint toolchain + the lint:md / lint:html scripts
The site is a mix of Markdown content and YAML data files. Most updates are to the YAML data files, not the templates. Examples:
- Adding a feature to the matrix → edit
data/features.yaml, no code or template change. - The homepage release fact updates itself (
release-sync.yml); never editdata/release.jsonby hand. - Tweaking the homepage tagline → edit
data/version.yaml.
Anything that's prose for users (guides, blog posts) lives in content/ as Markdown.
-
Create
content/guides/my-guide.md. -
Add front matter:
--- title: "My Guide" description: "What this guide teaches in one line." weight: 50 ---
-
Write the content in Markdown. Use language tags on every code fence.
-
Run
make lintto confirm markdownlint passes. -
Run
make devand check the rendered page locally.
- Create
content/blog/2026-mm-dd-slug.md. - Add front matter with
title,description,date, andtags. - Write the content. Open a PR.
Edit data/features.yaml. The status field uses complete / in_progress / roadmap and renders as a status badge. Do not hardcode features into templates — the YAML is the source of truth.
The homepage release line reads data/release.json, which .github/workflows/release-sync.yml maintains from the GitHub API. If it is wrong, check the latest release-sync run rather than editing the file.
- Create
layouts/shortcodes/my-shortcode.html. - Use it in Markdown via
{{</* my-shortcode arg="value" */>}}. - Document it in this README's
## Shortcodessection if it becomes load-bearing.
The site is deployed to Cloudflare Pages with PostHog analytics. Cloudflare's GitHub app watches this repository and rebuilds on every push:
- Push to
main→ Cloudflare Pages builds withhugo --minify --environment production→ deploys to aixgo.dev. - Open a PR → Cloudflare Pages builds a preview at
<branch>.aixgo-web.pages.dev(URL pattern depends on Cloudflare Pages project settings; the preview link is posted as a check on the PR).
These are set in the Cloudflare Pages project settings (not in this repo). For local builds, copy .env.example to .env and populate.
| Variable | Purpose |
|---|---|
HUGO_VERSION |
Hugo version (must be set by hand to match .hugo-version) |
HUGO_POSTHOG_KEY |
PostHog Project API Key (phc_...); analytics gated on this being set |
HUGO_POSTHOG_HOST |
Optional, defaults to https://us.i.posthog.com |
HUGO_POSTHOG_KEY=phc_xxx HUGO_POSTHOG_HOST=https://us.i.posthog.com make build
# Output in public/- File naming:
kebab-case.md(e.g.provider-integration.md). - Lists: use
1.for every numbered list item (markdownlint enforces). - Code fences: always specify language for syntax highlighting (
bash,go,yaml,text). - Internal links: use Hugo's
refshortcode ({{</* ref "/guides/quick-start" */>}}) so they survive renames. - Data files first: prefer YAML data updates over hardcoded content in templates.
Open a PR. Cloudflare will build a preview within ~2 minutes; the link is posted as a check. Good first contributions: typo fixes, missing examples, broken links, new guides for under-documented framework features.
For framework documentation (API reference, ADRs), contribute to the aixgo repo instead — the website embeds those rather than duplicating them.
MIT.
aixgo.dev builds agents. Aixgate keeps them in their lane.