CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this repo is

This is the documentation site source for docs.fluxzy.io — not the Fluxzy .NET SDK itself. It produces a DocFX static site combining hand-written conceptual docs (documentation/, index.md) with auto-generated .NET API reference pulled from the fluxzy.core git submodule (https://github.com/haga-rak/fluxzy.core).

The product source code lives in the submodule. Changes to API docs almost always belong in fluxzy.core, not here.

Architecture / pipeline

The build is a three-stage pipeline orchestrated by docfx:

  1. Submodule syncfluxzy.core/ must be initialized and on the desired branch. The Dockerfile / docker-entrypoint.sh always pulls latest main; locally you control the ref via git submodule update.
  2. Samples build — projects under samples/ (samples.sln) are restored and built. DocFX pulls code excerpts from these into the conceptual docs, so they must compile against the current submodule state. Samples reference projects inside fluxzy.core/.
  3. DocFX builddocfx.json defines two metadata sources (Fluxzy.Coreapi/, Fluxzy.Core.Pcapapipcap/) targeting net10.0. Conceptual content is **/*.{md,yml} excluding _site/** and fluxzy.core/**. Output goes to _site/. Theme overrides live in fluxzy_template/ (layered after default + modern).

The top-level toc.yml wires the three sections together: Quick start (documentation/), API reference (api/), and Pcap API reference (apipcap/). documentation/toc.yml orders the conceptual pages.

Common commands

The Bullseye-based build runner in build/build/Program.cs is the canonical entry point used by CI:

./build.sh generate-site         # full pipeline: install docfx, sync submodule, build samples, run docfx
./build.sh build-samples         # just compile samples/
./build.sh refresh-sub-modules   # git submodule update --init --recursive

Useful env vars for generate-site: OUT (output dir, default _artefacts) and DOCFX_PATH (default docfx). The GitHub Actions workflow (.github/workflows/dotnet.yml) uses OUT=/var/docs.fluxzy/trunk.

For iterating locally:

dotnet tool install -g docfx                      # one-time
rm -rf _site api apipcap && docfx docfx.json      # build
docfx docfx.json --serve                          # build + local preview server

Note: _site is the docfx-default output; _artefacts is what the Bullseye target uses. Both are gitignored.

Submodule workflow

The submodule pin in this repo determines which version of fluxzy.core the API reference reflects.

Important: the submodule tracks a commit, not a branch. Even though .gitmodules declares branch = main (implicitly via the default), git submodule update --init will check out the exact commit recorded in this repo's tree, not the current tip of main. To actually advance to upstream's latest, you must use --remote. The pin can — and historically did — drift years behind upstream while everyone assumed "it tracks main."

This drift is invisible in production: docker-entrypoint.sh does its own git clone --branch main every start, so the deployed site is always built against the latest. Only local builds and CI hit the stale pin. If you see the docs build break locally with errors that "shouldn't be there" (missing types, TFM mismatches, samples referencing removed APIs), check the pin first:

git submodule status                                     # shows the pinned commit
git -C fluxzy.core log -1 --format='%h %ci %s'           # date of pinned commit
git -C fluxzy.core fetch origin main                     # see how far behind
git -C fluxzy.core log --oneline HEAD..origin/main | wc -l

Common operations:

git submodule update --init --recursive                  # first checkout (uses pinned commit)
git submodule update --remote --merge                    # advance to submodule's origin/main tip
git -C fluxzy.core checkout <branch-or-sha>              # pin a specific ref (e.g. preview a docs branch)
git add fluxzy.core && git commit                        # *record* a new pin in this repo

The last step is essential and easy to forget: changing the submodule's HEAD locally only updates your working tree. Without git add fluxzy.core + commit in the parent repo, no one else (and no CI) will see the bump.

After changing the submodule ref, rebuild samples and docs — sample code references types from the submodule and will fail to build if APIs have changed.

Docker

Dockerfile + docker-entrypoint.sh produce a self-rebuilding nginx container: on each start it re-clones fluxzy.core at main, rebuilds samples, regenerates the site, and copies _site/ into nginx's webroot. nginx.conf sets cache headers (1d for assets, no-cache for HTML) and the SPA-ish try_files $uri $uri/ $uri.html =404 fallback. docker-compose.yml attaches to an external tetezana network — there is no host port mapping, so it expects to sit behind a reverse proxy on that network.

Things to keep in mind

  • fluxzy.core/** is excluded from the DocFX content glob — putting markdown there has no effect on the generated site.
  • The TargetFramework override in docfx.json must be one the submodule projects actually declare (currently net8.0;net10.0). Picking anything else silently produces a broken compilation: MSBuild generates obj/Release/<tfm>/ files but no framework references resolve, leading to a flood of CS0246 / CS0518 errors against System.String, System.Net.*, InternalsVisibleToAttribute, etc. A stale submodule pin is a common cause of this — see the Submodule workflow section above before chasing TFM theories.
  • samples/ is a real solution that must build cleanly; broken samples break the docs build.