spinagram

Development

Work on spinagram itself.

git clone https://github.com/dangerousplay/spinagram && cd spinagram
uv sync --all-extras && uv run pytest
uv run ruff check src tests examples
node tests/js/figma_mock.mjs out/figma/<slug>-01.js     # dry-run a Figma script on a mock Plugin API

Feature specs live in .specs/ (spec-driven: project, then spec, design and tasks per feature).

Live UI frontend

Source is in web/ (React + TypeScript + Vite + Tailwind CSS v4, built with bun):

cd web
bun install && bun run dev      # proxies /api to `spinagram serve --port 8765`
bun run build                   # rewrites src/spinagram/ui/static/

CI fails if the committed bundle is stale. Build with the bun version CI pins (BUN_VERSION in .github/workflows/ci.yml) and bun install --frozen-lockfile: an older bun ignores the lockfile, resolves other versions and produces a different bundle. Without upgrading bun: bunx bun@1.4.2 install --frozen-lockfile then bunx bun@1.4.2 run build.

Docs

This site is a Fumadocs app in docs/ (Next.js, static export). The search index is built at export time, so search works on GitHub Pages without a server. Every push to main deploys it.

cd docs
bun install && bun run dev      # http://localhost:3000
bun run build                   # static site in docs/out/

Pages are MDX files in docs/content/docs/; meta.json sets the sidebar order. Code samples are pulled from examples/ with <include>, so they always match the files that the tests run.

The diagrams on these pages are rendered by spinagram itself:

spinagram render docs/diagrams/ examples/quickstart.py -f svg -o out/
cp out/S00-spinagram.svg docs/public/assets/overview.svg
cp out/Q01-web-app-on-aws.svg docs/public/assets/quickstart.svg

Releasing

Commits follow Conventional Commits: feat, fix, docs, test, refactor, perf, build, ci, chore. git-cliff turns them into CHANGELOG.md (configuration in cliff.toml).

uv version --bump minor
uvx git-cliff --tag "v$(uv version --short)" -o CHANGELOG.md
git commit -am "chore(release): v$(uv version --short)"
git tag "v$(uv version --short)" && git push --follow-tags

The tag triggers CI, publishes to PyPI with trusted publishing and creates a GitHub release whose notes come from git-cliff (uvx git-cliff --latest --strip header).

On this page