Compare commits

..
Author SHA1 Message Date
fargo f006289ddc fix(#1323): remove legacy credential read and force-merge recipe from mosaic-gitea
ci/woodpecker/pr/ci Pipeline was successful
Same defect class as the #1320 Should Fix, at the two spots the #1320 file
list missed (found by rev-security-01's review of #1322, filed as #1323):

- Setup section framed a shared-credential env read
  (~/.config/mosaic/credentials/gitea.env — no longer part of the credential
  system) as the way to enable force-merges. The credentials loader is now
  the only documented source, and the force-merge framing is gone.
- 'Force-merge bypassing branch protection' section carried the full raw
  curl + force_merge:true recipe. Replaced with the same wrapper-only
  guidance merged in #1322: protection blocks are signals to fix, never to
  bypass; exceptional cases go to the operator or coordinating seat, still
  through the wrapper.

Scan before fixing (whole shipped framework tree, three patterns — gitea.env
/ credentials/*.env reads, force_merge, raw merge curl): the two handed spots
in mosaic-gitea were the complete set; no seventh carrier. Post-fix rescan:
zero recipe matches; the only force_merge strings left are the guidance text
that forbids it. Closes #1323.
2026-08-19 17:06:28 -05:00
fargo 1bdeed62eb fix(#1320): placeholder-ize private-network topology, drop raw-curl force-merge recipe (#1322)
ci/woodpecker/push/publish Pipeline was successful
2026-08-19 21:15:54 +00:00
fargo 840c2b0d96 Merge pull request 'skills: fold agent-skills into the monorepo, single install path, promote ms-unslop (plan phase D)' (#1319) from fold-agent-skills into next
ci/woodpecker/push/publish Pipeline was successful
2026-08-19 20:08:09 +00:00
fargo 95d5cb32d4 format: cover folded skills' js/ts scripts with repo prettier
ci/woodpecker/pr/ci Pipeline was successful
The repo format:check glob covers ts/js alongside md; four non-markdown
scripts inside the folded tree were flagged after the md pass. Same pinned
prettier 3.8.1, same markup-only class (verified: node --check still passes
on the js files).
2026-08-19 14:41:18 -05:00
fargo d5f3fae896 skills: promote ms-unslop from skills-local into the package
Phase D3 of plan 2026-08-19 (decision S21): skills-local is the local test
bed; promote individually as each proves out. ms-unslop is the only one of
the seven local skills with working enforcement evidence — a checker
(tools/unslop-hook/unslop-check.js), a machine-source list (lists.json), a
19-test suite, a measured corpus, and a regression fixture.

The checker itself stays fleet-local for now (it binds to a specific
harness extension surface); this promotes the skill document only.

Gates verified on the moved file: sanitization denylist clean, prettier
3.8.1 clean (6730 chars was fred's measure at assignment; 7249 as shipped
today — both pass).
2026-08-19 14:39:46 -05:00
fargo 1556982dbc skills: single install path — canonical skills ship with the framework
Phase D2 of plan 2026-08-19: single package, single install, single command.

The framework installer already treats skills/** as a shipped, manifest-owned
framework subtree, so the folded skills now install into
$MOSAIC_HOME/skills with the rest of the framework — no second repository,
no separate sync step:

- mosaic-sync-skills (bash + powershell): the fetch machinery is gone (clone,
  pull, dirty-state migration, rsync from sources/agent-skills). The script
  now only links installed skills into runtime homes. --link-only is a compat
  no-op; --no-link exits having nothing to do.
- catalog.ts: the sources/agent-skills fallback is dead and removed.
- install.sh, launch.ts, defaults/README.md, README.md, skills/README.md:
  references to the second repo rewritten to describe the shipped path.

Verified: clean install into a fresh MOSAIC_HOME produces 102 skills with no
sources/ directory; the linker then links the selected skills into the four
runtime homes with no git involvement.
2026-08-19 14:39:28 -05:00
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00
fargo d2eeb64433 skills: sanitize operator-identity tokens from folded ops skills
Four folded skills carried operator identity tokens that the sanitization
gate (verify-sanitized.sh) forbids in the public framework package:

- kickstart: template path pointed at a private brain checkout; now uses the
  framework-shipped $MOSAIC_HOME/templates/docs/TASKS.md.template
- mosaic-deploy: dropped one estate-specific stack-name row from the example
  table
- mosaic-portainer, mosaic-woodpecker: credentials now name the framework
  credentials store (load_credentials <service>) instead of a private
  checkout path

Estate-specific values can live in a skills-local override, which the linker
applies with precedence over canonical skills.
2026-08-19 14:34:00 -05:00
fargo 5e58597dbe fold: absorb mosaicstack/agent-skills into the framework skills tree
Fold the agent-skills repository into the monorepo as the shipped canonical
skills package (plan 2026-08-19 phase D1, decision S19: single package, single
install, single command).

History is preserved by rewriting each commit's paths from skills/ to
packages/mosaic/framework/skills/ (git fast-export/import) and merging the
rewritten history with --allow-unrelated-histories, so the original commits
with their authors, dates, and messages remain reachable. Blob content is
untouched by the rewrite; tree fidelity was verified blob-sha-for-blob-sha.

This change must be merged with a real merge commit (not squash) or the
history link is destroyed.
2026-08-19 14:33:03 -05:00
jason.woltje fe4fa20309 Merge pull request 'guides: add SEAT-IDENTITY and FLEET-COMMS; harden CODE-REVIEW evidence rules' (#1313) from fred/guides-seat-identity-fleet-comms into next
ci/woodpecker/push/publish Pipeline was successful
Reviewed-on: #1313
Reviewed-by: rev-code-01 <[email protected]>
2026-08-19 15:44:57 +00:00
fred 5e93ef70bd guides: fix the cross-reference direction in SEAT-IDENTITY
ci/woodpecker/pr/ci Pipeline was successful
rev-code-01's non-blocking nit on #1313 round 2. The no-linking-step paragraph
pointed at the bridge explanation as 'described below'; it is above. Now names the
section, which survives further reordering better than a direction word does.

Text-only. Verified with the repo's PINNED prettier (3.8.1 via pnpm-lock.yaml) and
the sanitization gate, both clean.
2026-08-18 19:10:09 -05:00
fred 3884f2de4d guides: address rev-code-01's review of #1313 (B1, B2, S1, S2)
ci/woodpecker/pr/ci Pipeline was successful
All four findings reproduced before fixing. rev-code-01 was right on each.

B2 (blocker, mine). SEAT-IDENTITY provisioning step 4 said to symlink the
framework store entry to the seat slot, while the same file says those bridges
must not be recreated. The same bridge, told both ways, in one document. I
rewrote the resolution and token-location sections when the deploy made them
stale and did not carry the change into the numbered steps. Step 4 is gone and
the file now says explicitly that no provisioning step links the store to the
slot, so the omission cannot read as an oversight.

S1 (mine). The guide claimed the helper "attempts a fleet notification" on
refusal. The shipped helper does no such thing — its only reference to
notification is a comment saying an alert built on the record is best-effort, and
there is no send or wake call anywhere in the file. Now: it writes a durable
record, the record is what exists, and nobody should wait for a notification that
nothing sends. A guide that promises an alert is worse than one that promises
nothing.

S2. Estate-local content removed from files that ship to every estate: the
~/.mosaic/fleet/bin script paths (dead paths elsewhere) and the 2026-08-18 dates,
which dated a specific host's migration rather than describing behavior. The
bridge-removal passage now states the ORDERING that matters — remove bridges only
after a seat-aware helper can reach the slot, never before — which is the part
that transfers.

B1. prettier reformatted all three files. Reproduced the pipeline 2515 failure
locally before and confirmed clean after; the other three guides prettier flags
are untouched by this branch (0 changes vs origin/next) and are pre-existing.

Sanitization gate re-run and passing.

Verified for the record, since I could not verify my own work: rev-code-01
confirmed the no-fallback claim TRUE against helper content on origin/next, and
judged the evidence rules actionable on the grounds that each names an executable
replacement.
2026-08-18 18:51:15 -05:00
fred a3c50d91ca guides: genericize the operator name in SEAT-IDENTITY provisioning
ci/woodpecker/pr/ci Pipeline failed
Pipeline 2514 failed the sanitization gate on 'Jason mints the token into the
seat slot'. The denylist is jarvis|jason|woltje|... and a shipped framework file
must not carry operator identity. My mistake: I generalized the estate paths and
seat names when promoting this guide and did not check the operator name.

Now reads 'the estate operator', with the accompanying rule that an agent does
not ask another agent to mint one either.

Verified by running tools/quality/scripts/verify-sanitized.sh locally rather than
guessing at the pattern: gate passes.
2026-08-18 18:28:37 -05:00
fred 2fd102e6af guides: state the decree, drop the mechanism
ci/woodpecker/pr/ci Pipeline failed
The #1280 prohibition carried an explanation of how the tools misattribute and
why the failure is invisible from inside them. A reader who is not going to use
the tool cannot act on any of it. Same for rule 2's closing clause about what
reviews commonly miss. Both cut to the decree and the corrective action.

Rules 1 and 3-12 keep their trailing sentences: those are corrective actions or
the detail that makes the case recognizable, not justification.
2026-08-18 18:25:47 -05:00
fred efb3c3a10c guides: add SEAT-IDENTITY and FLEET-COMMS; harden CODE-REVIEW evidence rules
ci/woodpecker/pr/ci Pipeline failed
Three guides that existed only as one host's working copy, promoted to framework
templates so every estate gets them. A working copy under ~/.mosaic binds one
host; only a template here binds all of them.

SEAT-IDENTITY.md (new) documents how a seat's git credential is actually
resolved after #1311: identity from MOSAIC_GIT_IDENTITY, then
mosaic.gitIdentity, then the stdin username; host mapped to a store prefix; then
ONE of two stores chosen by whether the seat directory exists, with no
precedence and no fallback between them. A seat with a directory and an empty
slot fails closed rather than reaching the service store, and that is the point.

It also corrects how to find the helper. credential.helper commonly names an
absolute path, so `command -v git-credential-mosaic` answers a different question
than the one git asks, and the two stop agreeing the moment the PATH copy is
removed. Git also tries EVERY configured helper in order, so a fail-closed helper
in front silently hands the request to whatever is configured behind it. The
guide says to read the whole list.

FLEET-COMMS.md (new) documents agent-send.sh: the class table, the addressing
preamble, and the exit codes — including that rc=2 means the text reached the
pane as an unsubmitted draft, so retrying double-sends it. Confirm with
capture-pane instead. It also says to measure the fleet rather than trust
roster.yaml, which on a live host was simultaneously naming a socket that did not
exist, listing seats that were not running, and omitting seats that were.

CODE-REVIEW.md gains an Evidence Discipline section: a green is not a result
until you have shown it could go red, measurement and explanation are separate
sentences, verify by content on the ref that ships rather than by ancestry of a
local sha, and confidence is part of a finding. Plus four shell-measurement rules
earned on #1311, each of which produced a wrong conclusion first — `cmd | tail;
echo rc=$?` reports tail's status, a missed glob under pipefail exits 2 and kills
the run under set -e, nonzero-with-no-output is an environment question before it
is a code question, and `git -C` in a non-repo directory answers from the
enclosing repo.

The estate-specific repository exception that lived in the working copy is not
carried here. The template says an estate may document one, scoped to a named
repository and never precedent for a second.

Both new guides are added to the two routing tables that agents read.
2026-08-18 18:15:50 -05:00
Mos 4d8ddb9a0a fix: quote SKILL.md descriptions containing colons (silent skill-load failure) (#3) 2026-08-11 22:53:47 +00:00
jason.woltje 63e77887a8 feat: add mosaic-tools skill (fleet toolkit fast path) (#1) 2026-06-19 18:30:58 +00:00
Jarvis 809ca9a1d9 feat: add mosaic ops skills (portainer, gitea, woodpecker, deploy, orchestrator)
- mosaic-portainer: stack list/status/redeploy/logs via Portainer API scripts
- mosaic-gitea: PR/issue/milestone ops for git.mosaicstack.dev
- mosaic-woodpecker: pipeline status, trigger, CI wait
- mosaic-deploy: full end-to-end deploy flow (push → CI → merge → redeploy)
- mosaic-orchestrator: mission init/run/status + worker launch rules
2026-03-22 15:32:05 +00:00
Jason Woltje 57435bb879 switch skill docs to xdg mosaic config path 2026-02-17 14:12:07 -06:00
Jason Woltje 8c51bf7575 remove legacy nested skill link artifacts 2026-02-17 14:08:02 -06:00
Jason Woltje c3d2179ad8 add delegation mode fallback to matrix rail in kickstart 2026-02-17 14:05:43 -06:00
Jason Woltje b47c4024cc standardize skills to mosaic-first paths and docs 2026-02-17 13:09:06 -06:00
Jason Woltje 74d1cdc7c1 migrate kickstart skill to mosaic-first paths 2026-02-17 13:01:49 -06:00
Jason WoltjeandClaude Opus 4.6 8cae9e0883 feat: Add lint skill (zero-tolerance) + strengthen kickstart linting mandate
New skill: lint — zero-tolerance linting enforcement for all code changes.
Detects project linter, fixes ALL violations, never disables rules.

Updated kickstart: linting now explicit standing order #3 in worker template
with "NON-NEGOTIABLE" language and zero-tolerance enforcement.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 17:13:00 -06:00
Jason WoltjeandClaude Opus 4.6 2c524b6da2 feat: Add kickstart skill — orchestrator launcher via /kickstart command
/kickstart [milestone|issue|task] replaces manual orchestrator boilerplate.
Auto-discovers project context, fetches issues from Gitea/GitHub, bootstraps
tracking files, and transforms the session into an orchestrator.

Modes: milestone, issue, task ID, resume, interactive (no args)
Built-in: quality gates, Two-Phase Completion, context handoff protocol

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:59:04 -06:00
Jason WoltjeandClaude Opus 4.6 b4f2019529 security: Remove vercel-deploy (data exfiltration), annotate LD_PRELOAD shims
Security audit findings:
- CRITICAL: vercel-deploy uploaded entire project to external endpoint — REMOVED
- ANNOTATED: docx/pptx/xlsx soffice.py LD_PRELOAD shims — security warnings added
- README updated to 93 skills with full security audit section and Vue/Vite ecosystem

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:39:04 -06:00
Jason WoltjeandClaude Opus 4.6 b1eb1fb2f9 feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:27:42 -06:00
Jason WoltjeandClaude Opus 4.6 dfeb4d9692 feat: Expand fleet to 23 skills across all domains
New skills (14):
- nestjs-best-practices: 40 priority-ranked rules (kadajett)
- fastapi: Pydantic v2, async SQLAlchemy, JWT auth (jezweb)
- architecture-patterns: Clean Architecture, Hexagonal, DDD (wshobson)
- python-performance-optimization: Profiling and optimization (wshobson)
- ai-sdk: Vercel AI SDK streaming and agent patterns (vercel)
- create-agent: Modular agent architecture with OpenRouter (openrouterteam)
- proactive-agent: WAL Protocol, compaction recovery, self-improvement (halthelobster)
- brand-guidelines: Brand identity enforcement (anthropics)
- ui-animation: Motion design with accessibility (mblode)
- marketing-ideas: 139 ideas across 14 categories (coreyhaines31)
- pricing-strategy: SaaS pricing and tier design (coreyhaines31)
- programmatic-seo: SEO at scale with playbooks (coreyhaines31)
- competitor-alternatives: Comparison page architecture (coreyhaines31)
- referral-program: Referral and affiliate programs (coreyhaines31)

README reorganized by domain: Code Quality, Frontend, Backend,
Auth, AI/Agent Building, Marketing, Design, Meta.

Mosaic Stack is not limited to coding — the Orchestrator serves
coding, business, design, marketing, writing, logistics, and analysis.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:22:53 -06:00
Jason WoltjeandClaude Opus 4.6 7ea13332ed feat: Add 5 curated skills for Mosaic Stack
New skills:
- next-best-practices: Next.js 15+ RSC, async patterns, self-hosting (vercel-labs)
- better-auth-best-practices: Official Better-Auth with Drizzle adapter (better-auth)
- verification-before-completion: Evidence-based completion claims (obra/superpowers)
- shadcn-ui: Component patterns with Tailwind v4 adaptation note (developer-kit)
- writing-skills: TDD methodology for skill authoring (obra/superpowers)

README reorganized by category with Mosaic Stack alignment section.
Total: 9 skills (4 existing + 5 new).

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:17:40 -06:00
Jason WoltjeandClaude Opus 4.6 b032d23889 docs: Add npx install commands and clone instructions
- Add npx skills add commands for single, all, and non-interactive install
- Document .git suffix requirement for Gitea-hosted repos
- Add git clone step to manual installation
- Use ln -sf for idempotent symlinks

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:09:05 -06:00
Jason WoltjeandClaude Opus 4.6 ecde74439c feat: Initial agent-skills repo — 4 adapted skills for Mosaic Stack
Skills included:
- pr-reviewer: Adapted for Gitea/GitHub via platform-aware scripts
  (dropped fetch_pr_data.py and add_inline_comment.py, kept generate_review_files.py)
- code-review-excellence: Methodology and checklists (React, TS, Python, etc.)
- vercel-react-best-practices: 57 rules for React/Next.js performance
- tailwind-design-system: Tailwind CSS v4 patterns, CVA, design tokens

New shell scripts added to ~/.claude/scripts/git/:
- pr-diff.sh: Get PR diff (GitHub gh / Gitea API)
- pr-metadata.sh: Get PR metadata as normalized JSON

Co-Authored-By: Claude Opus 4.6 <[email protected]>
2026-02-16 16:03:39 -06:00
1413 changed files with 268508 additions and 289 deletions
+1 -1
View File
@@ -331,7 +331,7 @@ The framework is the bash-based standards layer installed to every developer mac
├── bin/mosaic ← Unified launcher (claude, codex, opencode, pi, yolo)
├── guides/ ← E2E delivery, orchestrator protocol, PRD, etc.
├── runtime/ ← Per-runtime configs (claude/, codex/, opencode/, pi/)
├── skills/ ← Universal skills (synced from agent-skills repo)
├── skills/ ← Universal skills (shipped with the framework package)
├── tools/ ← Tool suites (orchestrator, git, quality, prdy, etc.)
└── memory/ ← Persistent agent memory (preserved across upgrades)
```
+4 -4
View File
@@ -16,17 +16,17 @@
> the PR head, squash merge to `next`, and acceptance evidence in notes.
| id | status | description | issue | agent | repo | branch | depends_on | estimate | notes |
| -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---------- | ----------------- | --------------------------------- | ---------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| -------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---------- | ----------------- | --------------------------------- | ---------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| RI-0-001 | done | Bootstrap: issue #1275, PRD section, this DAG, scratchpad (docs only) | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-mission-bootstrap | — | 6K | PR #1276 (head 758659dd): docs-only, CI green (2475). Review requested from fargo. Merges first (no publish run). |
| RI-1-001 | done | RI-N1: canonical terminal verification command + publish-pipeline exact-commit gate (every publish step depends on verify; commit identity check; fail closed) | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-publish-gate | RI-0-001 | 25K | PR #1277 (head 46784c8d): CI GREEN at head after serialized retry (pipeline 2476, 2026-08-18) - earlier red was CI-agent contention (web SPA timeouts under concurrent pipelines), not code. Review requested from fargo at pinned head (comms 20260818T021025Z). |
| RI-1-002 | done | RI-N1 negative control: checked-in tests proving a broken mandatory check blocks every publish step and that DAG edges cannot be bypassed | #1275 | pi-glm-5.3 | mosaicstack/stack | test/ri-050-publish-gate-negative | RI-1-001 | 12K | |
| RI-2-001 | done | RI-N2 (Forge): remove stub-executor false success; `--simulate` typed `simulated` results that satisfy nothing; literal-`true` gates and echo-review replaced with real gates or typed waiting-for-authority | #1275 | pi-glm-5.3 | mosaicstack/stack | fix/ri-050-forge-fail-closed | RI-0-001 | 20K | Independent review APPROVED 2026-08-17 (Gitea review 172 on PR #1278, head 99b8f6ea; reviewing seat fargo — recorded under shared host principal mos-dt-0, provenance correction posted by fred; wrapper gap filed by fred). Executed at head: forge tests 116/116, lint green, typecheck green after building macp dist (minimal-install artifact, not a defect), workspace typecheck 45/45, no external type consumers of the changed interfaces. CI red = known lane-wide fleet-test failure only, carries no information about this change (fred, log-content analysis, pipelines 2456-2458). Non-blocking finding: README L141-143 + skills/mosaic-forge/SKILL.md document bare forge run/resume, which now fails closed — fast-follow docs touch. Merge queued behind #1270. UPDATE 2026-08-18: #1270 merged; CI GREEN at head 4917df1f via serialized retry (pipeline 2477) - root cause of prior reds was CI-agent contention (web SPA timeouts under concurrent pipelines), superseding the fleet-test-failure theory. |
| RI-2-002 | done | RI-N2 (MACP): gate runner fails closed on empty commands, stub executors, and unimplemented CI-provider gates unless explicit simulate; typed capability failures | #1275 | pi-glm-5.3 | mosaicstack/stack | fix/ri-050-macp-fail-closed | RI-0-001 | 15K | PR #1293 (head 2097379e): CI green (pipeline 2465), independent review APPROVED (Gitea review 173, jarvis seat, 2026-08-17) - macp 109/109 verified at head. Merge queued behind #1276/#1277/#1278. |
| RI-3-001 | done | RI-N4: complete probe inventory mapping every TS and shell quality-rail check to one canonical check with disposition (preserve/strengthen/retire, each named) | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-qr-probe-inventory | RI-0-001 | 12K | PR #1302 (head e06a47fac591): CI green (2484), independent review APPROVED (Gitea review 187, fargo seat, 2026-08-18) — 54 rows / 21 canonical checks / dispositions 43-2-9-0 verified by row-count and code spot-checks. Merged by fargo at pinned head. |
| RI-3-002 | done | RI-N4: TS evaluator absorbs effective shell probes; typed results (passed/failed/blocked/error/not-applicable) with versioned digested check definitions; shell commands become thin adapters; contract/parity/negative-control tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-qr-evaluator | RI-3-001 | 30K | | PR #1308 (head 68279d61): CI green (2506), independent review APPROVED (Gitea review 188, fred, seven mutations incl. vacuous-pass + stage-removal). Merged by fargo at pinned head → next @ 245e0c4. Follow-up #1309 (digest wording). |
| RI-4-001 | done | RI-N3: one PRD application service — `mission --plan` persists mission↔PRD linkage (ids/versions/selected requirements); `mosaic prdy` routes through the service or becomes a named import/export adapter; Markdown is a labeled generated view; explicit conflict-aware import | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-prd-authority | RI-0-001 | 35K | PR #1294 (head 8d258e1d): CI green (pipeline 2466), independent review APPROVED (Gitea review 174, jarvis seat, 2026-08-17) - prdy 20/20 + command specs 9/9 at head. Merge queued behind #1276/#1277/#1278. | PR #1294 (head 8d258e1d): CI green (2466), review 174. Merged 2026-08-18 overnight wave → next @ d92de53. |
| RI-3-002 | not-started | RI-N4: TS evaluator absorbs effective shell probes; typed results (passed/failed/blocked/error/not-applicable) with versioned digested check definitions; shell commands become thin adapters; contract/parity/negative-control tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-qr-evaluator | RI-3-001 | 30K | |
| RI-4-001 | in-progress | RI-N3: one PRD application service — `mission --plan` persists mission↔PRD linkage (ids/versions/selected requirements); `mosaic prdy` routes through the service or becomes a named import/export adapter; Markdown is a labeled generated view; explicit conflict-aware import | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-prd-authority | RI-0-001 | 35K | PR #1294 (head 8d258e1d): CI green (pipeline 2466), independent review APPROVED (Gitea review 174, jarvis seat, 2026-08-17) - prdy 20/20 + command specs 9/9 at head. Merge queued behind #1276/#1277/#1278. |
| RI-5-001 | done | RI-N5: typed freshness states (current/stale/partial/unknown/unavailable); no failed-fetch-renders-empty; stale derived verdicts → unknown; mutations disabled when stale; failure-matrix tests | #1275 | pi-glm-5.3 | mosaicstack/stack | feat/ri-050-web-stale-safety | RI-0-001 | 25K | |
| RI-V-001 | in-progress | Final verification + release evidence: all cards verified merged, negative controls demonstrated, real `next` publish run green on exact commit, evidence pack recorded | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-release-evidence | RI-1-002, RI-2-001, RI-2-002, RI-3-002, RI-4-001, RI-5-001 | 10K | | Evidence pack live on branch docs/ri-050-release-evidence — all five requirements evidenced; registry credential fixed (jarvis, #1275 c23239) and PROVEN green: pipeline 2517 (retry of 2512, identical commit) all steps green incl. build-gateway; pack PR next, then topher review + merge, close #1275. |
| RI-V-001 | not-started | Final verification + release evidence: all cards verified merged, negative controls demonstrated, real `next` publish run green on exact commit, evidence pack recorded | #1275 | pi-glm-5.3 | mosaicstack/stack | docs/ri-050-release-evidence | RI-1-002, RI-2-001, RI-2-002, RI-3-002, RI-4-001, RI-5-001 | 10K | |
## Dispatch waves (max 2 parallel workers)
-121
View File
@@ -1,121 +0,0 @@
# RI-050 Release Evidence Pack (alpha 0.0.50 release-integrity floor)
> Status: **DRAFT — proof complete, awaiting review + merge**. All five normative requirements (RI-N1..N5) merged to `next` behind the live gate. Registry credential fixed 2026-08-18 23:47Z and **proven end-to-end**: push pipeline **2517** (retry of failed 2512 at the identical commit d4d32a8, only the secret changed between runs) — all steps green including `build-gateway`. Remaining for closure: this pack PR reviewed (topher), merged to `next`, its own push pipeline green, #1275 closed. Last updated 2026-08-19 by fargo (day-takeover orchestrator).
> Card: RI-V-001. All sections marked ⏳ pending their card's merge. Normative source:
> `docs/PRD.md` § Release Integrity Workstream (#1275).
## RI-N1 — Canonical terminal verification + exact-commit publish gate
| exhibit | evidence | where |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------- |
| Gate live, fail-closed | Push pipeline **2486**: `verify` ran at exact commit, FAILED on a real latent defect (gateway cross-user-isolation cleanup on the no-DB path), and `build` / `publish-npm` / `build-gateway` were all **skipped**. First push in repo history that did not publish ungated (prior ungated publishes beside failing builds: 2439, 2462, 2482). | Woodpecker repo 47 pipeline 2486 |
| Gate-caught defect fixed | PR **#1304** (afterAll honors `dbAvailable`; both paths verified: dead-port 28 skipped + file passes; live-5433 28 passed). Review 180 (fred). | PR #1304 |
| First gated green npm publish | Push pipeline **2488** (post-#1304): `verify` GREEN → `build` GREEN → `publish-next-npm` GREEN, all publish effects behind the gate. | Woodpecker pipeline 2488 |
| Negative controls | PR **#1305**: structural DAG tests (S1 missing edge, S2 renamed effect incl. command-based npm/kaniko detection, S3 detach, S4 failure:ignore/success override, S5 when-filter, S6 HEAD-mover between verify and publish with legitimate-recheckout positive control, S7 removal) + subset-stage composition control in verify-release.test.mjs. Mutation-verified by the dispatching seat in both directions (true bypass → S1 assertion fires; non-bypass edit → correctly green). Scripts tests 20/20, CI 2490 green. | PR #1305 |
| ✅ Canonical command | `scripts/verify-release.mjs` (stage table pinned to ci.yml by checked-in test). Merged with #1277; now also invokes the RI-N4 evaluator via its `quality-rails` stage (#1308). | `scripts/verify-release.mjs` |
## RI-N2 — Forge + MACP fail-closed (typed explicit simulation)
- ✅ Forge: PR **#1278** merged (head 4917df1f; CI 2477; review 184 fred at pinned head — prior review 172 dismissed by rebase, correctly re-taken).
- ✅ MACP: PR **#1293** merged (head 2097379e; CI 2465; review 173).
- ✅ Post-merge behavior docs: PR **#1299** merged (head 8a405b14; CI 2497; review 186 fargo at pinned head — legitimate independent seat; merged 2026-08-18 with --expect-head pin, content-verified on next @ ff45f7b).
## RI-N3 — PRD authority
- ✅ PR **#1294** merged (head 8d258e1d; CI 2466; review 174).
## RI-N4 — Quality-rails evaluator
- ✅ Probe inventory: PR **#1302** merged (head e06a47fac59; CI 2484; review 187 fargo at pinned head; 54 rows / 21 canonical checks / dispositions 43-2-9-0 row-count-verified; merged 2026-08-18, content-verified on next @ 6435089).
- ✅ TS evaluator absorbs shell probes: PR **#1308** merged (head 68279d61; CI 2506; review 188 fred at pinned head — seven targeted mutations, seven detections, incl. the vacuous-pass hole M1 and stage-removal M7). Evaluator: typed fail-closed verdicts, digested versioned definitions, per-subject sets; QC-19 absorbed (verbatim-list parity oracle), QC-20 as thin adapter (verify.sh unmodified); verify-release `quality-rails` stage wired (RI-N1 consumes the evaluator). Worker-produced, independently verified by the dispatching seat (quality-rails 40/40 incl. sabotage control 6-failed/34-passed restored sha-verified; root build 25/25; typecheck 45/45).
## RI-N5 — Consequence-aware stale UI
- ✅ PR **#1300** merged (head a337d787; CI 2481; review 179). Web suite 199 → 281 tests (failure matrix + negative controls), independently re-run by the dispatching seat before merge.
## Known-open infrastructure item (not a card)
Gateway/ci-base **image** pushes fail on registry credentials: Woodpecker repo
secrets `REGISTRY_USERNAME`/`REGISTRY_PASSWORD` are rejected by the Gitea
container registry (explicit `UNAUTHORIZED` at `/v2/token`; pipeline 2494 after
PR #1306 corrected the secret references — previously masked as an ambiguous
push-permission error since at least 2439). Requires a package-scoped token
(Jason). The npm publish path is green and gated; this item tracks image pushes
only and predates the RI-050 floor.
**Update 2026-08-18 (fargo):** Jason set new secret values ~17:25Z; pipeline
**2507** (the #1308 merge push, first after the update, 18:0xZ) still fails
`build-gateway` with the identical `UNAUTHORIZED`. Read-only isolation (no
secrets read, no CI retries): the registry endpoint and auth mechanism are
HEALTHY — a valid Gitea token via basic-auth mints a JWT at `/v2/token` (200),
bad credentials 401 cleanly. Therefore the failure is isolated to the secret
VALUES, not the endpoint or pipeline. Most likely shape error (labeled guess):
the registry authenticates username + **API token with package scope**, not
username + login password; if REGISTRY_PASSWORD holds a login password rather
than a minted token value, `/v2/token` 401s exactly as observed. npm publishes
remained green in 2507; every publish step except the image push is gated and
green.
**Resolution 2026-08-18 23:47Z — FIXED on the Gitea server (jarvis, #1275
comment 23239).** Root cause was neither scope nor a missing token:
`REGISTRY_USERNAME` held `mosaic`, the **pre-rename org name**. Gitea's rename
redirect covers API/web paths but not Basic-auth username lookup, and
`mosaicstack` is an organization, which has no password — the pair could never
authenticate. Fix: `REGISTRY_USERNAME`=`woodpecker` (the existing service
account, Gitea user 41, already in `ci-publish`) and `REGISTRY_PASSWORD`= a
newly minted `write:package`-only token (`gitea admin user generate-access-token`
in the Gitea container; minting with a token is forbidden server-side). Events
`[push, tag]` preserved. Verified **without a pipeline run**:
`POST /v2/<pkg>/blobs/uploads/` opened then cancelled a session — **202** on
all four kaniko destinations (gateway, appservice, web, ci-base), anonymous
control **401**, wrong-owner control **401**. The earlier "Requires a
package-scoped token (Jason)" expectation is superseded: the defect was a
stale value from the org rename, not a scope grant Jason owed.
**Proof 2026-08-19 ~00:2xZ (fargo): pipeline 2517 green at build-gateway.**
Woodpecker retry of 2512 — identical commit d4d32a8, identical pipeline
config, only the server-side secret changed between runs — went green on
every step (clone, install, verify, build, publish-next-npm,
**build-gateway**). A/B at the same commit isolates the credential as the
variable; the stored value is byte-intact. Retry was serialized (sole run in
flight; merge-purpose CI queue guard had blocked on 2512's terminal failure
at the `next` head, which this retry also clears). The item is closed.
## Process record (audit trail)
- Merges executed under the jarvis principal (topher seat; identity provisioning
pending) via the Gitea API replicating `pr-merge.sh` semantics (head-pin +
squash + keep branch): `pr-merge.sh` hard-codes `main`-only targets and cannot
express this repo's `next` trunk — wrapper gap captured to OpenBrain
(id 9db7a95a) and to the framework queue.
- Reviews tonight: 175/178 (zane's #1298, both heads, by topher); 176/177/179/
180/181/182 (fred) — cross-review rule (producer ≠ reviewer) held on every
merge: producers were pi workers / zane; reviewers were the other seat.
- CI contention note: concurrent PR pipelines on the single CI agent can time
out the web SPA suite (measured 2470/2472 vs serialized 2475/2476/2477);
serialize retries when the queue is busy.
## Process record — 2026-08-18 day takeover (fargo)
- Takeover directive: Jason (via jarvis router + both seats' handoff documents,
relayed verbatim over comms). First-move conflict between the two handoffs
(zane: doctor PR first; topher: review-queue first) resolved on dependency
grounds per jarvis's read — topher's order won; zane's finding-2 doctor PR
(upgraded by fred's measurement) remains queued, nothing depends on it.
- Reviews 186 (#1299) + 187 (#1302): fargo, at pinned heads, as the legitimate
independent seat (topher dispatched both producers; cross-review rule held).
Both merged with --expect-head pinning via the REPO-COPY pr-merge.sh
(allows next; the installed copy still lags — zane's route, not the raw-API
break-glass), each preceded by ci-queue-wait -B next -R mosaicstack/stack.
CI green at both heads (2497, 2484). Merges content-verified on the shipping
ref (TASKS anchors at ff45f7b / 6435089).
- RI-3-002: one pi worker (zai/glm-5.3:high), independently verified by the
dispatching seat before push; PR #1308 reviewed by fred (188, seven
mutations incl. vacuous-pass and stage-removal) and merged head-pinned at
68279d61 → next @ 245e0c4.
- Registry-credential isolation measurement (above) performed read-only; no
secret values read, no retry-pushes against CI.
- One reviewer-scope disclosure (fred, review 188): fred's approval explicitly
did NOT re-run root build/typecheck/mosaic-vitest — those remain the
dispatching seat's numbers. The changed-package suites, verify-release
suite, and seven mutations were fred's own.
@@ -43,6 +43,8 @@ overwritten on upgrade. (Layer model: `constitution/LAYER-MODEL.md`.)
| Secrets / vault usage | `guides/VAULT-SECRETS.md` |
| Tool/credential reference (service CLIs, wrappers) | `guides/TOOLS-REFERENCE.md` |
| Memory protocol (OpenBrain capture/recall) | `guides/MEMORY.md` |
| Seat identity, git credentials, token slots | `guides/SEAT-IDENTITY.md` |
| Reaching another agent (fleet comms) | `guides/FLEET-COMMS.md` |
## Subagent Model Selection (Cost — Hard Rule)
+4 -4
View File
@@ -126,7 +126,7 @@ You can still launch runtimes directly (`claude`, `codex`, etc.) — thin runtim
│ ├── opencode/ ← AGENTS.md, RUNTIME.md
│ ├── pi/ ← RUNTIME.md, mosaic-extension.ts
│ └── mcp/ ← MCP server configs
├── skills/ ← Universal skills (synced from mosaic/agent-skills)
├── skills/ ← Universal skills (shipped with the framework package)
├── skills-local/ ← Local cross-runtime skills
├── memory/ ← Persistent agent memory (preserved across upgrades)
└── templates/ ← SOUL.md template, project templates
@@ -193,11 +193,11 @@ The installer rejects unrecognized flags or positional arguments before making c
## Universal Skills
The installer syncs skills from `mosaic/agent-skills` into `~/.config/mosaic/skills/`. Install, wizard finalization, and `mosaic update` automatically reconcile every canonical skill into Claude Code's `~/.claude/skills/` directory.
Canonical skills ship inside the framework package itself; the installer installs them into `~/.config/mosaic/skills/` together with the rest of the framework (there is no separate skills repository). Install, wizard finalization, and `mosaic update` automatically link every canonical skill into Claude Code's `~/.claude/skills/` directory.
```bash
mosaic sync # Full canonical catalog sync
~/.config/mosaic/tools/_scripts/mosaic-sync-skills --link-only # Re-link only
mosaic sync # Relink the full canonical catalog
~/.config/mosaic/tools/_scripts/mosaic-sync-skills --link-only # Re-link only (same as default)
mosaic skill list # Show registered, missing, dangling, and foreign entries
mosaic skill register <name> # Register or repair one canonical Claude link
mosaic skill unregister <name> # Remove one Mosaic-owned Claude link
@@ -15,8 +15,78 @@ Merge strategy enforcement (HARD RULE):
- Merge to `main` MUST be squash-only.
- Use `~/.config/mosaic/tools/git/pr-merge.sh -n {PR_NUMBER} -m squash --expect-head {approved_full_sha}` (or PowerShell equivalent).
An estate MAY carry a documented exception for a repository whose gates are commit hooks rather
than review. Such an exception belongs in that estate's own working copy of this guide, is
scoped to the named repository, and is never precedent for a second one.
**Do not use `pr-review.sh` or `issue-comment.sh` to post a verdict** (mosaicstack#1280). Post
through a direct authenticated API call as your own seat, or hand the verdict to the requesting
seat. Handing it over is a legitimate delivery path, not a fallback.
## Evidence Discipline (applies to every finding)
The checklist below says what to look at. This section says when you are allowed to believe what
you saw. Every rule here was earned by a wrong conclusion that reached a report.
1. **A finding is a claim about behavior.** State the failing input, the path taken, and the
wrong result. "This looks fragile" is not a finding.
2. **A green check is not a result until you have shown it could go red.** Run the control. A
`0`, an empty result, or a column of identical values with no failing counterpart is a
non-result.
3. **Measurement and explanation are separate sentences.** Report the command and its output,
then, as its own sentence, what you think it means.
4. **Never widen the case you measured.** If you checked one path, the finding covers one path.
5. **Reproduce a reported failure before recording it, and say which tree you measured.** Two
correct measurements of two different trees disagree without either being wrong.
6. **Verify by content on the ref that ships**, never by ancestry of a local sha. A rebase mints
new shas; a commit being an ancestor of something local proves nothing about the remote.
Compare by digest against `origin/<branch>`.
7. **Confidence is part of the finding.** "I could not reproduce this" is a usable review
comment. A confident guess is not.
8. **Author is not reviewer** (Gate-16). Do not review your own work, or work you shaped closely
enough to be a co-author of. Say so and hand it back.
### Measuring a shell suite
Each of these produced a wrong conclusion before it was written down.
9. **`cmd | tail; echo rc=$?` reports `tail`'s exit code, not `cmd`'s.** It reads as a pass when
the command failed. Redirect to a file and check `rc` directly, or use `${PIPESTATUS[0]}`.
10. **Under `set -o pipefail`, a missed glob makes `ls` exit 2**, the pipeline inherits it, and
`set -e` kills the run. Iterate a glob with a `for` loop and an `-e` test instead of piping
`ls`.
11. **A suite that exits nonzero with ZERO output is an environment question, not a defect in
the code under review.** The usual cause is a sourced dependency that is absent, so `set -e`
kills the first case before anything prints. Extract whole tool trees — `tools/git` alone is
missing `tools/_lib/credentials.sh`. Isolate the variable and prove it by adding only that
back.
12. **`git -C <dir>` in a directory that is not itself a repo answers from the enclosing repo.**
A scratch tree under `~/.mosaic` reports `~/.mosaic`'s HEAD, not the PR's, and every
conclusion drawn from it describes the wrong tree. Confirm `git rev-parse --show-toplevel`
is the tree you think it is before trusting any git output.
### Feedback Categories
- **Blocker**: must fix before merge (security, bugs, test failures)
- **Should Fix**: important but not blocking (code quality, minor issues)
- **Suggestion**: optional improvement (style preference, nice-to-have)
- **Question**: seeking clarification
## Review Checklist
Reviewer seats split this checklist by class rather than duplicating it. A seat reviews its own
sections in full and may raise anything it notices outside them as a Suggestion, never as a
Blocker on someone else's ground.
| Reviewer class | Owns |
| ---------------- | ------------------------------------------------------------------------------------------------------- |
| `rev-code-*` | 1 Correctness, 3 Testing, 4 Code Quality, 4a TypeScript, 5 Documentation, 6 Performance, 7 Dependencies |
| `rev-security-*` | 2 Security, 2a OWASP |
Where two seats of the same class review the same change, they review independently and compare
after. A second seat that reads the first seat's findings before measuring is a proofreader, not
a second opinion.
### 1. Correctness
- [ ] Code does what the issue/PR description says
@@ -53,7 +123,7 @@ Merge strategy enforcement (HARD RULE):
- [ ] Tests cover happy path AND error cases
- [ ] Situational tests cover all impacted change surfaces (primary gate)
- [ ] Tests validate required behavior/outcomes, not only internal implementation details
- [ ] TDD was applied when required by `~/.config/mosaic/guides/QA-TESTING.md`
- [ ] TDD was applied when required by `guides/QA-TESTING.md`
- [ ] Coverage meets 85% minimum
- [ ] Tests are readable and maintainable
- [ ] No flaky tests introduced
@@ -82,7 +152,7 @@ Merge strategy enforcement (HARD RULE):
### 5. Documentation
- [ ] Complex logic has explanatory comments
- [ ] Required docs updated per `~/.config/mosaic/guides/DOCUMENTATION.md`
- [ ] Required docs updated per `guides/DOCUMENTATION.md`
- [ ] Public APIs are documented
- [ ] Private/internal APIs are documented
- [ ] API input/output schemas are documented
@@ -126,13 +196,6 @@ git diff main...HEAD
- Distinguish between blocking issues and suggestions
- Be constructive, not critical of the person
### Feedback Categories
- **Blocker**: Must fix before merge (security, bugs, test failures)
- **Should Fix**: Important but not blocking (code quality, minor issues)
- **Suggestion**: Optional improvements (style preferences, nice-to-haves)
- **Question**: Seeking clarification
### Review Comment Format
```
@@ -0,0 +1,86 @@
# Fleet Comms Guide
How one seat reaches another on a host. The mechanism is the framework's; the sessions and
sockets are per-host, so measure yours rather than trusting an example.
`mosaic <runtime>` would normally inject the addressing block from the roster. Where the composer
is unavailable, or where the roster is stale, this guide is the substitute.
## Measure the fleet; do not trust the roster
`fleet/roster.yaml` is a declaration of intent, not an observation. It routinely names a socket
that was never created, lists seats that are not running, and omits seats that are — this was
all three have been observed true at once on a live host. Find out what is actually
up before addressing anyone:
```bash
tmux list-sessions
tmux list-panes -a -F '#{session_name} #{pane_current_command} #{pane_current_path}'
```
The pane command tells you the runtime. A pane showing `bash` is an idle shell with no agent
attached — a send there lands in a shell prompt and is not read by anyone.
Use the **default socket**. Do not pass `-L mosaic-fleet` on the strength of the roster.
## Sending
```bash
~/.config/mosaic/tools/tmux/agent-send.sh -s <dst_session> -C <class> -m "<message>"
```
`-s` also accepts `session:window.pane`. `-f <file>` sends a file body; stdin works too.
### Classes
`-C` takes exactly one of these. Anything else exits 3.
| Class | Use for |
| -------------- | -------------------------------------------------------- |
| `terminal-log` | log only; never needs the agent's attention |
| `actionable` | a decision, blocker, gate, or question needing an answer |
| `human` | relayed from a human operator |
| `reaction` | an ack or acknowledgement token |
| `digest` | machine wake, coalescible |
An absent class is treated as `actionable` by consumers, which is the fail-safe direction. Prefer
naming it anyway.
### Addressing preamble
The wire format is `[<src> -> <dst> class=<class>] <body>`. Flip it when you reply — the tool
sends, it does not auto-reply.
### Exit codes
| rc | Meaning |
| --- | ---------------------------------------------- |
| 0 | delivered or queued |
| 1 | target session not found |
| 2 | text reached the pane but is **still a draft** |
| 3 | usage error (bad class, missing `-s`) |
**Never retry on rc=2.** The message is in the target pane; retrying double-sends it. Confirm
instead:
```bash
tmux capture-pane -p -t <session>:0.0 | tail -20
```
rc=2 is the normal result when the target is an idle pi seat.
## Durable comms
tmux delivery is host-local and does not survive a pane. Anything that must outlive the session
goes through the estate's durable comms protocol — a committed `comms/` tree in an estate repo,
with its own README. Use it for cross-host messages, verdicts, and anything a later session needs
to find.
## Handing work across seats
1. **A verdict handed to the requesting seat is a legitimate delivery path**, and the required one
for anything `pr-review.sh` would otherwise post (see `guides/CODE-REVIEW.md`).
2. **Address the seat, not the runtime.** A seat name is a session name; whether it runs claude,
pi or codex is not the sender's business.
3. **Say what you measured, not just what you concluded** — the receiving seat cannot see your
terminal.
@@ -219,7 +219,7 @@ Use the Cloudflare tools for any DNS configuration: pointing domains at services
# Update an existing record (get record ID from record-list first)
~/.config/mosaic/tools/cloudflare/record-update.sh \
-z example.com -r <record-id> -t A -n myapp -c 10.0.0.5 -p
-z example.com -r <record-id> -t A -n myapp -c 192.0.2.5 -p
```
**DNS + Deployment integration**: When deploying a new service via Coolify or Portainer that needs a public domain, the typical sequence is:
@@ -0,0 +1,133 @@
# Seat Identity & Credentials Guide
Every agent that touches a Mosaic-managed git host acts as a named seat with its own credential.
This guide is how that works on a host, and what an agent must never do with it.
The mechanism below is the framework's. The specific paths, seats and stores are per-host:
measure yours before trusting any of them.
## The rule
**One seat, one identity, one token file.** A seat never borrows another seat's credential, never
falls back to a shared owner account, and never carries a second copy of its own token. A second
copy is drift, and drift surfaces as the stale copy returning 401 — which reads as a revoked
token and sends whoever debugs it somewhere else entirely.
A credential refusal is correct behavior, not a bug to route around. If git refuses with a
fail-closed diagnostic, the fix is to provision or correct _your_ identity. Escalate; do not
substitute.
## How a credential is resolved
Find the helper the way **git** does, not with `command -v`. Git runs whatever
`credential.helper` names, and on a Mosaic host that is an absolute path — so a PATH lookup
answers a different question and the two disagree the moment the PATH copy is removed. It was
removed on hosts that have completed that migration.
```bash
git config --get-all credential.helper # every helper, in the order git tries them
```
Git tries **each** configured helper in turn until one supplies a credential. A fail-closed
helper supplies nothing, so a second helper configured behind it silently becomes the one that
answers. When you care which binary serves a credential, read the whole list.
Resolve all three forms git accepts — absolute path, `!command`, and a bare name looked up on
PATH — not just the one your host happens to use.
The helper resolves the identity in this order:
1. `$MOSAIC_GIT_IDENTITY`
2. `git config --get mosaic.gitIdentity`
3. the username git supplied on stdin
It maps the host to a store prefix — `git.mosaicstack.dev` to `gitea-mosaicstack`,
`git.uscllc.com` to `gitea-usc`. Any other host is declined quietly with rc=0, which is not an
error and raises no escalation.
Then it chooses **one** of two stores, and reads exactly one file:
```
brain_home = ${MOSAIC_BRAIN_HOME:-$HOME/.mosaic}
seat — when $brain_home/fleet/agents/<identity>/ EXISTS
$brain_home/fleet/agents/<identity>/secrets/<prefix>-<identity>.token
service — otherwise
~/.config/mosaic/secrets/gitea-tokens/<prefix>-<identity>.token
```
**There is no precedence between the two and no fallback from one to the other.** The existence
of the seat directory decides it. A seat that has a directory and an empty slot fails closed; it
does not reach the service store. That is the intended behavior — the alternative is an agent
silently acting as somebody else.
If the file is unreadable the helper **fails closed**: it refuses and writes a durable record to
the escalation spool. It does not fall back to a shared account. The record is what exists — any
alerting built on top of it is a separate, best-effort concern and is not performed by the helper,
so do not wait for a notification that nothing sends. That fallback is what made
`usc/uconnect#3084` unattributable, and it was removed deliberately.
Verify the helper you actually have:
```bash
h=$(git config --get credential.helper)
grep -c 'FAIL CLOSED' "$h" # expect >= 1
grep -c 'fleet/agents' "$h" # expect >= 1; 0 means it predates mosaicstack#1311
```
## Where a seat's token lives
The seat slot is the **only** copy:
```
~/.mosaic/fleet/agents/<seat>/secrets/<prefix>-<seat>.token real file, mode 600
```
The framework store at `~/.config/mosaic/secrets/gitea-tokens/` holds tokens for **service
identities only** — identities with no seat directory. A seat's token does not belong there.
Before mosaicstack#1311 the deployed helper knew only the service store, and seats were bridged
with a symlink from the store into the slot. **Those bridges must be removed once a seat-aware helper is deployed, and must not be
recreated.** Remove them only after the helper can reach the slot without them; the reverse order
takes every seat offline. A symlink
is not how a system finds a credential; the helper resolving the right store is.
`.principal` and `.scopes` beside the token are grant records, not secrets. They are tracked. The
`.token` never is.
### Provisioning a new seat
1. Create `~/.mosaic/fleet/agents/<seat>/secrets/` mode 700.
2. Write `.principal` (the Gitea login) and `.scopes` (the granted scopes), mode 600.
3. The estate operator mints the token into the seat slot, mode 600. Agents do not mint their
own, and do not ask another agent to mint one for them.
4. Verify with an authenticated `GET /user` and confirm the returned login is the seat, **not the
minting account**. Record the date in `ENTITY.md`. Never record the value.
There is no step that links the framework store to the slot. A seat-aware helper reads the slot
directly; a store entry pointing at a slot is the bridge described in **Where a seat's token lives** above,
and it is not part of provisioning.
Until step 3, the seat is unminted and its git writes fail closed. That is the designed state and
is safe to launch in — the seat is told at launch so it does not discover it mid-task.
## Acting as yourself
Name the identity on every invocation:
```bash
MOSAIC_GIT_IDENTITY=<seat> git push
git -c user.name=<seat> -c user.email=<seat>@mosaicstack.dev commit -m "..."
```
**Never persist `git config mosaic.gitIdentity` inside a `~/src/stack` worktree.** Every worktree
of that clone shares one `.git/config`, so a persisted identity there silently rewrites the
identity of every other seat working in that clone. The per-invocation form has no exception.
## Handling
1. **Never print a token value.** Compare by SHA-256 digest, or write `<REDACTED>`.
2. **Never stage a `.token`, `secrets.json`, or `ENTITY.md`.** Stage explicit paths and **never
`git add -A`** — `secrets/*.principal` and `secrets/*.scopes` are covered by no ignore rule.
3. **Never place a token in an environment variable** in an interactive session. A `declare -x`
dump has leaked the whole environment to a terminal before.
4. **No real credential or operator data on a sandbox VM, ever.**
+2 -2
View File
@@ -17,7 +17,7 @@ set -Eeuo pipefail
# MOSAIC_HOME — target directory (default: ~/.config/mosaic)
# MOSAIC_INSTALL_MODE — prompt|keep|overwrite (default: prompt)
# MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING — 1 to bypass MCP check
# MOSAIC_SKIP_SKILLS_SYNC — 1 to skip skill sync
# MOSAIC_SKIP_SKILLS_SYNC — 1 to skip linking skills into runtime homes
#
# Flags (CLI args, NOT environment variables — see #869 Point-1 C2):
# --allow-inactive-enforcement Explicit, per-invocation opt-out that lets the
@@ -828,7 +828,7 @@ if [[ -x "$SCRIPTS/mosaic-ensure-excalidraw" ]]; then
fi
if [[ "${MOSAIC_SKIP_SKILLS_SYNC:-0}" != "1" ]] && [[ -x "$SCRIPTS/mosaic-sync-skills" ]]; then
"$SCRIPTS/mosaic-sync-skills" >/dev/null 2>&1 && ok "Skills synced" || warn "Skills sync failed (non-fatal)"
"$SCRIPTS/mosaic-sync-skills" >/dev/null 2>&1 && ok "Skills linked into runtime homes" || warn "Skills linking failed (non-fatal)"
fi
if [[ -x "$SCRIPTS/mosaic-migrate-local-skills" ]]; then
+228
View File
@@ -0,0 +1,228 @@
# Agent Skills
Complete agent skill fleet for Mosaic Stack. 101 skills across 12 domains — coding, business development, design, marketing, writing, orchestration, document generation, Vue/Vite ecosystem, and more. Platform-aware — works with both GitHub (`gh`) and Gitea (`tea`) via our abstraction scripts.
This tree lives in the monorepo (`packages/mosaic/framework/skills/`) and ships inside the framework package; it is no longer a separate repository.
## Security Audit
All skills were reviewed on 2026-02-16. Findings:
| ID | Severity | Skill | Issue | Action |
| ----- | ------------- | ---------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| C-001 | **CRITICAL** | `vercel-deploy` | Uploads entire project to external endpoint via `curl` | **REMOVED** |
| C-002 | **ANNOTATED** | `docx`, `pptx`, `xlsx` | LD_PRELOAD shim compiles C at runtime to hook `socket()` | Security warnings added — legitimate sandbox workaround, should never activate on Docker Swarm |
| W-001 | WARNING | `using-superpowers` | Forces aggressive auto-loading via `<EXTREMELY-IMPORTANT>` tags | Awareness only — review before enabling |
| W-002 | WARNING | `mcp-builder` | Can connect to arbitrary MCP servers | Awareness only — review server URLs |
| W-003 | WARNING | `create-agent` | Uses `Function()` constructor (eval equivalent) | Awareness only — review generated code |
88 of 93 audited skills passed all checks as clean instruction-only SKILL.md files.
## Skills (95)
### Code Quality & Review (6)
| Skill | Purpose | Origin |
| -------------------------------- | ------------------------------------------------------------------------------- | ------------------------------- |
| `lint` | Zero-tolerance linting — detect linter, fix ALL violations, never disable rules | Mosaic Stack |
| `pr-reviewer` | Structured PR code review workflow (Gitea/GitHub) | Adapted from SpillwaveSolutions |
| `code-review-excellence` | Code review methodology and checklists | awesome-skills |
| `verification-before-completion` | Evidence-based completion claims | obra/superpowers |
| `receiving-code-review` | How to receive and respond to code reviews | obra/superpowers |
| `requesting-code-review` | How to request effective code reviews | obra/superpowers |
### Frontend & UI (8)
| Skill | Purpose | Origin |
| ----------------------------- | ----------------------------------------------------- | ----------------------- |
| `next-best-practices` | Next.js 15+ — RSC, async, self-hosting, data patterns | vercel-labs/next-skills |
| `vercel-react-best-practices` | React/Next.js performance (57 rules) | vercel-labs |
| `vercel-composition-patterns` | React composition and component patterns | vercel-labs |
| `vercel-react-native-skills` | React Native development patterns | vercel-labs |
| `shadcn-ui` | Component patterns — forms, dialogs, tables, charts | developer-kit |
| `tailwind-design-system` | Tailwind CSS v4 design system patterns | wshobson |
| `ui-animation` | Motion design — performance, accessibility, easing | mblode |
| `web-design-guidelines` | Web design principles and guidelines | vercel-labs |
### Backend & API (4)
| Skill | Purpose | Origin |
| --------------------------------- | ------------------------------------------------- | -------- |
| `nestjs-best-practices` | NestJS — 40 rules, 10 categories, priority-ranked | kadajett |
| `fastapi` | FastAPI + Pydantic v2 + async SQLAlchemy 2.0 | jezweb |
| `architecture-patterns` | Clean Architecture, Hexagonal, DDD | wshobson |
| `python-performance-optimization` | Profiling, memory, parallelization | wshobson |
### Authentication (5)
| Skill | Purpose | Origin |
| ------------------------------------------ | -------------------------------------------------- | ----------- |
| `better-auth-best-practices` | Better-Auth — Drizzle, sessions, plugins, security | better-auth |
| `create-auth-skill` | Creating custom Better-Auth skills | better-auth |
| `email-and-password-best-practices` | Email/password auth patterns | better-auth |
| `organization-best-practices` | Multi-org/team auth patterns | better-auth |
| `two-factor-authentication-best-practices` | 2FA implementation patterns | better-auth |
### AI & Agent Building (7)
| Skill | Purpose | Origin |
| ----------------------------- | --------------------------------------------------- | ---------------- |
| `ai-sdk` | Vercel AI SDK — streaming, multi-provider, agents | vercel/ai |
| `create-agent` | Modular agent with OpenRouter multi-model access | openrouterteam |
| `proactive-agent` | WAL Protocol, compaction recovery, self-improvement | halthelobster |
| `dispatching-parallel-agents` | Launching and managing parallel subagents | obra/superpowers |
| `subagent-driven-development` | Development workflow using subagents | obra/superpowers |
| `executing-plans` | Executing multi-step implementation plans | obra/superpowers |
| `using-superpowers` | Overview of the superpowers skill system | obra/superpowers |
### Development Workflow (6)
| Skill | Purpose | Origin |
| -------------------------------- | --------------------------------------- | ---------------- |
| `test-driven-development` | TDD Red-Green-Refactor discipline | obra/superpowers |
| `systematic-debugging` | Structured debugging methodology | obra/superpowers |
| `using-git-worktrees` | Git worktree patterns for parallel work | obra/superpowers |
| `finishing-a-development-branch` | Branch cleanup, squash, merge patterns | obra/superpowers |
| `writing-plans` | Writing effective implementation plans | obra/superpowers |
| `brainstorming` | Structured brainstorming methodology | obra/superpowers |
### Document Generation (6)
| Skill | Purpose | Origin |
| ----------------- | ---------------------------------- | ---------- |
| `pdf` | PDF document generation | anthropics |
| `docx` | Word document generation | anthropics |
| `pptx` | PowerPoint presentation generation | anthropics |
| `xlsx` | Excel spreadsheet generation | anthropics |
| `doc-coauthoring` | Collaborative document writing | anthropics |
| `internal-comms` | Internal communications drafting | anthropics |
### Design & Creative (7)
| Skill | Purpose | Origin |
| ----------------------- | --------------------------------------- | ---------- |
| `brand-guidelines` | Brand identity enforcement | anthropics |
| `frontend-design` | Frontend design patterns and principles | anthropics |
| `canvas-design` | Canvas/visual design patterns | anthropics |
| `algorithmic-art` | Generative/algorithmic art creation | anthropics |
| `theme-factory` | Theme generation and customization | anthropics |
| `slack-gif-creator` | Animated GIF creation for Slack | anthropics |
| `web-artifacts-builder` | Self-contained HTML artifact building | anthropics |
### Marketing & Business (25)
| Skill | Purpose | Origin |
| --------------------------- | --------------------------------------------- | ------------- |
| `marketing-ideas` | 139 ideas across 14 categories | coreyhaines31 |
| `pricing-strategy` | SaaS pricing — value metrics, tiers, research | coreyhaines31 |
| `programmatic-seo` | SEO at scale — templates, playbooks | coreyhaines31 |
| `competitor-alternatives` | Competitor comparison pages | coreyhaines31 |
| `referral-program` | Referral & affiliate programs | coreyhaines31 |
| `seo-audit` | Comprehensive SEO audit methodology | coreyhaines31 |
| `copywriting` | Marketing copywriting patterns | coreyhaines31 |
| `copy-editing` | Copy editing and proofreading | coreyhaines31 |
| `content-strategy` | Content strategy and planning | coreyhaines31 |
| `social-content` | Social media content creation | coreyhaines31 |
| `email-sequence` | Email sequence design and automation | coreyhaines31 |
| `launch-strategy` | Product launch planning | coreyhaines31 |
| `marketing-psychology` | Psychology-driven marketing | coreyhaines31 |
| `product-marketing-context` | Product marketing positioning | coreyhaines31 |
| `paid-ads` | Paid advertising campaigns | coreyhaines31 |
| `schema-markup` | Schema.org structured data | coreyhaines31 |
| `analytics-tracking` | Analytics setup and tracking | coreyhaines31 |
| `ab-test-setup` | A/B testing methodology | coreyhaines31 |
| `page-cro` | Landing page conversion optimization | coreyhaines31 |
| `form-cro` | Form conversion optimization | coreyhaines31 |
| `signup-flow-cro` | Signup flow conversion optimization | coreyhaines31 |
| `onboarding-cro` | User onboarding optimization | coreyhaines31 |
| `popup-cro` | Popup/modal conversion optimization | coreyhaines31 |
| `paywall-upgrade-cro` | Paywall/upgrade conversion optimization | coreyhaines31 |
| `free-tool-strategy` | Free tool as marketing strategy | coreyhaines31 |
### Vue/Vite Ecosystem (16)
| Skill | Purpose | Origin |
| ---------------------------- | ----------------------------------------- | ------ |
| `vue` | Vue.js development patterns | antfu |
| `vue-best-practices` | Vue.js best practices and conventions | antfu |
| `vue-router-best-practices` | Vue Router patterns and guards | antfu |
| `vue-testing-best-practices` | Vue component testing patterns | antfu |
| `vueuse-functions` | VueUse composable function patterns | antfu |
| `nuxt` | Nuxt.js framework patterns | antfu |
| `vite` | Vite build tool configuration and plugins | antfu |
| `vitest` | Vitest testing framework patterns | antfu |
| `vitepress` | VitePress documentation site patterns | antfu |
| `slidev` | Slidev presentation framework | antfu |
| `pnpm` | pnpm package manager patterns | antfu |
| `turborepo` | Turborepo monorepo patterns | antfu |
| `unocss` | UnoCSS atomic CSS engine | antfu |
| `tsdown` | tsdown TypeScript bundler | antfu |
| `pinia` | Pinia state management | antfu |
| `antfu` | Anthony Fu's coding conventions | antfu |
### Orchestration (1)
| Skill | Purpose | Origin |
| ----------- | ------------------------------------------------------------------------------------------ | ------------ |
| `kickstart` | Launch orchestrator for milestone/issue/task — auto-discovers context, bootstraps tracking | Mosaic Stack |
### Meta / Skill Authoring (4)
| Skill | Purpose | Origin |
| ---------------- | --------------------------------------------- | ---------------- |
| `writing-skills` | TDD-based skill authoring methodology | obra/superpowers |
| `skill-creator` | Anthropic's skill creation guide | anthropics |
| `mcp-builder` | Building MCP (Model Context Protocol) servers | anthropics |
| `webapp-testing` | Web application testing patterns | anthropics |
## Source Repositories
| Repository | Skills | Domain Focus |
| --------------------------------------------------------------------------------------------- | ------ | ---------------------------------------------- |
| [anthropics/skills](https://github.com/anthropics/skills) | 16 | Documents, design, MCP, testing |
| [obra/superpowers](https://github.com/obra/superpowers) | 14 | Agent workflows, TDD, code review, planning |
| [coreyhaines31/marketingskills](https://github.com/coreyhaines31/marketingskills) | 25 | Marketing, CRO, SEO, growth |
| [antfu/skills](https://github.com/antfu/skills) | 16 | Vue, Vite, Vitest, pnpm, Nuxt |
| [better-auth/skills](https://github.com/better-auth/skills) | 5 | Authentication patterns |
| [vercel-labs/agent-skills](https://github.com/vercel-labs/agent-skills) | 4 | React, design |
| [vercel-labs/next-skills](https://github.com/vercel-labs/next-skills) | 1 | Next.js 15+ |
| [vercel/ai](https://github.com/vercel/ai) | 1 | AI SDK |
| [halthelobster/proactive-agent](https://github.com/halthelobster/proactive-agent) | 1 | Agent architecture |
| [openrouterteam/agent-skills](https://github.com/openrouterteam/agent-skills) | 1 | Agent building |
| [kadajett/agent-nestjs-skills](https://github.com/kadajett/agent-nestjs-skills) | 1 | NestJS |
| [jezweb/claude-skills](https://github.com/jezweb/claude-skills) | 1 | FastAPI |
| [wshobson/agents](https://github.com/wshobson/agents) | 3 | Architecture, Python, Tailwind |
| [mblode/agent-skills](https://github.com/mblode/agent-skills) | 1 | UI animation |
| [giuseppe-trisciuoglio/developer-kit](https://github.com/giuseppe-trisciuoglio/developer-kit) | 1 | shadcn/ui |
| Mosaic Stack (original) | 4 | PR review, code review, orchestration, linting |
## Installation
The skills ship with the framework package. The framework installer installs them
into `~/.config/mosaic/skills/`, and the post-install step links them into each
runtime's skill directory:
```bash
# Install or upgrade the framework (skills arrive with it — no second repo)
./packages/mosaic/framework/install.sh
# Re-link installed skills into runtime homes (claude, codex, opencode, pi)
mosaic sync
```
Operators can override any canonical skill by copying it to
`~/.config/mosaic/skills-local/<name>/` — local skills take precedence during
linking.
## Adapting Skills
When adding skills from the community:
1. Replace raw `gh`/`tea` calls with our `~/.config/mosaic/rails/git/` scripts
2. Test on both GitHub and Gitea repos
3. Add Mosaic Stack context notes where upstream assumptions differ
4. Document any platform-specific limitations
## License
Individual skills retain their original licenses. Adaptations are MIT.
@@ -0,0 +1,287 @@
---
name: ab-test-setup
version: 1.0.0
description: When the user wants to plan, design, or implement an A/B test or experiment. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," or "hypothesis." For tracking implementation, see analytics-tracking.
---
# A/B Test Setup
You are an expert in experimentation and A/B testing. Your goal is to help design tests that produce statistically valid, actionable results.
## Initial Assessment
**Check for product marketing context first:**
If `.mosaic/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task.
Before designing a test, understand:
1. **Test Context** - What are you trying to improve? What change are you considering?
2. **Current State** - Baseline conversion rate? Current traffic volume?
3. **Constraints** - Technical complexity? Timeline? Tools available?
---
## Core Principles
### 1. Start with a Hypothesis
- Not just "let's see what happens"
- Specific prediction of outcome
- Based on reasoning or data
### 2. Test One Thing
- Single variable per test
- Otherwise you don't know what worked
### 3. Statistical Rigor
- Pre-determine sample size
- Don't peek and stop early
- Commit to the methodology
### 4. Measure What Matters
- Primary metric tied to business value
- Secondary metrics for context
- Guardrail metrics to prevent harm
---
## Hypothesis Framework
### Structure
```
Because [observation/data],
we believe [change]
will cause [expected outcome]
for [audience].
We'll know this is true when [metrics].
```
### Example
**Weak**: "Changing the button color might increase clicks."
**Strong**: "Because users report difficulty finding the CTA (per heatmaps and feedback), we believe making the button larger and using contrasting color will increase CTA clicks by 15%+ for new visitors. We'll measure click-through rate from page view to signup start."
---
## Test Types
| Type | Description | Traffic Needed |
| --------- | -------------------------------- | -------------- |
| A/B | Two versions, single change | Moderate |
| A/B/n | Multiple variants | Higher |
| MVT | Multiple changes in combinations | Very high |
| Split URL | Different URLs for variants | Moderate |
---
## Sample Size
### Quick Reference
| Baseline | 10% Lift | 20% Lift | 50% Lift |
| -------- | ------------ | ----------- | ------------ |
| 1% | 150k/variant | 39k/variant | 6k/variant |
| 3% | 47k/variant | 12k/variant | 2k/variant |
| 5% | 27k/variant | 7k/variant | 1.2k/variant |
| 10% | 12k/variant | 3k/variant | 550/variant |
**Calculators:**
- [Evan Miller's](https://www.evanmiller.org/ab-testing/sample-size.html)
- [Optimizely's](https://www.optimizely.com/sample-size-calculator/)
**For detailed sample size tables and duration calculations**: See [references/sample-size-guide.md](references/sample-size-guide.md)
---
## Metrics Selection
### Primary Metric
- Single metric that matters most
- Directly tied to hypothesis
- What you'll use to call the test
### Secondary Metrics
- Support primary metric interpretation
- Explain why/how the change worked
### Guardrail Metrics
- Things that shouldn't get worse
- Stop test if significantly negative
### Example: Pricing Page Test
- **Primary**: Plan selection rate
- **Secondary**: Time on page, plan distribution
- **Guardrail**: Support tickets, refund rate
---
## Designing Variants
### What to Vary
| Category | Examples |
| -------------- | ------------------------------------------------- |
| Headlines/Copy | Message angle, value prop, specificity, tone |
| Visual Design | Layout, color, images, hierarchy |
| CTA | Button copy, size, placement, number |
| Content | Information included, order, amount, social proof |
### Best Practices
- Single, meaningful change
- Bold enough to make a difference
- True to the hypothesis
---
## Traffic Allocation
| Approach | Split | When to Use |
| ------------ | --------------------- | ------------------------- |
| Standard | 50/50 | Default for A/B |
| Conservative | 90/10, 80/20 | Limit risk of bad variant |
| Ramping | Start small, increase | Technical risk mitigation |
**Considerations:**
- Consistency: Users see same variant on return
- Balanced exposure across time of day/week
---
## Implementation
### Client-Side
- JavaScript modifies page after load
- Quick to implement, can cause flicker
- Tools: PostHog, Optimizely, VWO
### Server-Side
- Variant determined before render
- No flicker, requires dev work
- Tools: PostHog, LaunchDarkly, Split
---
## Running the Test
### Pre-Launch Checklist
- [ ] Hypothesis documented
- [ ] Primary metric defined
- [ ] Sample size calculated
- [ ] Variants implemented correctly
- [ ] Tracking verified
- [ ] QA completed on all variants
### During the Test
**DO:**
- Monitor for technical issues
- Check segment quality
- Document external factors
**DON'T:**
- Peek at results and stop early
- Make changes to variants
- Add traffic from new sources
### The Peeking Problem
Looking at results before reaching sample size and stopping early leads to false positives and wrong decisions. Pre-commit to sample size and trust the process.
---
## Analyzing Results
### Statistical Significance
- 95% confidence = p-value < 0.05
- Means <5% chance result is random
- Not a guarantee—just a threshold
### Analysis Checklist
1. **Reach sample size?** If not, result is preliminary
2. **Statistically significant?** Check confidence intervals
3. **Effect size meaningful?** Compare to MDE, project impact
4. **Secondary metrics consistent?** Support the primary?
5. **Guardrail concerns?** Anything get worse?
6. **Segment differences?** Mobile vs. desktop? New vs. returning?
### Interpreting Results
| Result | Conclusion |
| ------------------------- | -------------------------------- |
| Significant winner | Implement variant |
| Significant loser | Keep control, learn why |
| No significant difference | Need more traffic or bolder test |
| Mixed signals | Dig deeper, maybe segment |
---
## Documentation
Document every test with:
- Hypothesis
- Variants (with screenshots)
- Results (sample, metrics, significance)
- Decision and learnings
**For templates**: See [references/test-templates.md](references/test-templates.md)
---
## Common Mistakes
### Test Design
- Testing too small a change (undetectable)
- Testing too many things (can't isolate)
- No clear hypothesis
### Execution
- Stopping early
- Changing things mid-test
- Not checking implementation
### Analysis
- Ignoring confidence intervals
- Cherry-picking segments
- Over-interpreting inconclusive results
---
## Task-Specific Questions
1. What's your current conversion rate?
2. How much traffic does this page get?
3. What change are you considering and why?
4. What's the smallest improvement worth detecting?
5. What tools do you have for testing?
6. Have you tested this area before?
---
## Related Skills
- **page-cro**: For generating test ideas based on CRO principles
- **analytics-tracking**: For setting up test measurement
- **copywriting**: For creating variant copy
@@ -0,0 +1,272 @@
# Sample Size Guide
Reference for calculating sample sizes and test duration.
## Sample Size Fundamentals
### Required Inputs
1. **Baseline conversion rate**: Your current rate
2. **Minimum detectable effect (MDE)**: Smallest change worth detecting
3. **Statistical significance level**: Usually 95% (α = 0.05)
4. **Statistical power**: Usually 80% (β = 0.20)
### What These Mean
**Baseline conversion rate**: If your page converts at 5%, that's your baseline.
**MDE (Minimum Detectable Effect)**: The smallest improvement you care about detecting. Set this based on:
- Business impact (is a 5% lift meaningful?)
- Implementation cost (worth the effort?)
- Realistic expectations (what have past tests shown?)
**Statistical significance (95%)**: Means there's less than 5% chance the observed difference is due to random chance.
**Statistical power (80%)**: Means if there's a real effect of size MDE, you have 80% chance of detecting it.
---
## Sample Size Quick Reference Tables
### Conversion Rate: 1%
| Lift to Detect | Sample per Variant | Total Sample |
| --------------- | ------------------ | ------------ |
| 5% (1% → 1.05%) | 1,500,000 | 3,000,000 |
| 10% (1% → 1.1%) | 380,000 | 760,000 |
| 20% (1% → 1.2%) | 97,000 | 194,000 |
| 50% (1% → 1.5%) | 16,000 | 32,000 |
| 100% (1% → 2%) | 4,200 | 8,400 |
### Conversion Rate: 3%
| Lift to Detect | Sample per Variant | Total Sample |
| --------------- | ------------------ | ------------ |
| 5% (3% → 3.15%) | 480,000 | 960,000 |
| 10% (3% → 3.3%) | 120,000 | 240,000 |
| 20% (3% → 3.6%) | 31,000 | 62,000 |
| 50% (3% → 4.5%) | 5,200 | 10,400 |
| 100% (3% → 6%) | 1,400 | 2,800 |
### Conversion Rate: 5%
| Lift to Detect | Sample per Variant | Total Sample |
| --------------- | ------------------ | ------------ |
| 5% (5% → 5.25%) | 280,000 | 560,000 |
| 10% (5% → 5.5%) | 72,000 | 144,000 |
| 20% (5% → 6%) | 18,000 | 36,000 |
| 50% (5% → 7.5%) | 3,100 | 6,200 |
| 100% (5% → 10%) | 810 | 1,620 |
### Conversion Rate: 10%
| Lift to Detect | Sample per Variant | Total Sample |
| ---------------- | ------------------ | ------------ |
| 5% (10% → 10.5%) | 130,000 | 260,000 |
| 10% (10% → 11%) | 34,000 | 68,000 |
| 20% (10% → 12%) | 8,700 | 17,400 |
| 50% (10% → 15%) | 1,500 | 3,000 |
| 100% (10% → 20%) | 400 | 800 |
### Conversion Rate: 20%
| Lift to Detect | Sample per Variant | Total Sample |
| ---------------- | ------------------ | ------------ |
| 5% (20% → 21%) | 60,000 | 120,000 |
| 10% (20% → 22%) | 16,000 | 32,000 |
| 20% (20% → 24%) | 4,000 | 8,000 |
| 50% (20% → 30%) | 700 | 1,400 |
| 100% (20% → 40%) | 200 | 400 |
---
## Duration Calculator
### Formula
```
Duration (days) = (Sample per variant × Number of variants) / (Daily traffic × % exposed)
```
### Examples
**Scenario 1: High-traffic page**
- Need: 10,000 per variant (2 variants = 20,000 total)
- Daily traffic: 5,000 visitors
- 100% exposed to test
- Duration: 20,000 / 5,000 = **4 days**
**Scenario 2: Medium-traffic page**
- Need: 30,000 per variant (60,000 total)
- Daily traffic: 2,000 visitors
- 100% exposed
- Duration: 60,000 / 2,000 = **30 days**
**Scenario 3: Low-traffic with partial exposure**
- Need: 15,000 per variant (30,000 total)
- Daily traffic: 500 visitors
- 50% exposed to test
- Effective daily: 250
- Duration: 30,000 / 250 = **120 days** (too long!)
### Minimum Duration Rules
Even with sufficient sample size, run tests for at least:
- **1 full week**: To capture day-of-week variation
- **2 business cycles**: If B2B (weekday vs. weekend patterns)
- **Through paydays**: If e-commerce (beginning/end of month)
### Maximum Duration Guidelines
Avoid running tests longer than 4-8 weeks:
- Novelty effects wear off
- External factors intervene
- Opportunity cost of other tests
---
## Online Calculators
### Recommended Tools
**Evan Miller's Calculator**
https://www.evanmiller.org/ab-testing/sample-size.html
- Simple interface
- Bookmark-worthy
**Optimizely's Calculator**
https://www.optimizely.com/sample-size-calculator/
- Business-friendly language
- Duration estimates
**AB Test Guide Calculator**
https://www.abtestguide.com/calc/
- Includes Bayesian option
- Multiple test types
**VWO Duration Calculator**
https://vwo.com/tools/ab-test-duration-calculator/
- Duration-focused
- Good for planning
---
## Adjusting for Multiple Variants
With more than 2 variants (A/B/n tests), you need more sample:
| Variants | Multiplier |
| ----------- | -------------------------- |
| 2 (A/B) | 1x |
| 3 (A/B/C) | ~1.5x |
| 4 (A/B/C/D) | ~2x |
| 5+ | Consider reducing variants |
**Why?** More comparisons increase chance of false positives. You're comparing:
- A vs B
- A vs C
- B vs C (sometimes)
Apply Bonferroni correction or use tools that handle this automatically.
---
## Common Sample Size Mistakes
### 1. Underpowered tests
**Problem**: Not enough sample to detect realistic effects
**Fix**: Be realistic about MDE, get more traffic, or don't test
### 2. Overpowered tests
**Problem**: Waiting for sample size when you already have significance
**Fix**: This is actually fine—you committed to sample size, honor it
### 3. Wrong baseline rate
**Problem**: Using wrong conversion rate for calculation
**Fix**: Use the specific metric and page, not site-wide averages
### 4. Ignoring segments
**Problem**: Calculating for full traffic, then analyzing segments
**Fix**: If you plan segment analysis, calculate sample for smallest segment
### 5. Testing too many things
**Problem**: Dividing traffic too many ways
**Fix**: Prioritize ruthlessly, run fewer concurrent tests
---
## When Sample Size Requirements Are Too High
Options when you can't get enough traffic:
1. **Increase MDE**: Accept only detecting larger effects (20%+ lift)
2. **Lower confidence**: Use 90% instead of 95% (risky, document it)
3. **Reduce variants**: Test only the most promising variant
4. **Combine traffic**: Test across multiple similar pages
5. **Test upstream**: Test earlier in funnel where traffic is higher
6. **Don't test**: Make decision based on qualitative data instead
7. **Longer test**: Accept longer duration (weeks/months)
---
## Sequential Testing
If you must check results before reaching sample size:
### What is it?
Statistical method that adjusts for multiple looks at data.
### When to use
- High-risk changes
- Need to stop bad variants early
- Time-sensitive decisions
### Tools that support it
- Optimizely (Stats Accelerator)
- VWO (SmartStats)
- PostHog (Bayesian approach)
### Tradeoff
- More flexibility to stop early
- Slightly larger sample size requirement
- More complex analysis
---
## Quick Decision Framework
### Can I run this test?
```
Daily traffic to page: _____
Baseline conversion rate: _____
MDE I care about: _____
Sample needed per variant: _____ (from tables above)
Days to run: Sample / Daily traffic = _____
If days > 60: Consider alternatives
If days > 30: Acceptable for high-impact tests
If days < 14: Likely feasible
If days < 7: Easy to run, consider running longer anyway
```
@@ -0,0 +1,292 @@
# A/B Test Templates Reference
Templates for planning, documenting, and analyzing experiments.
## Test Plan Template
```markdown
# A/B Test: [Name]
## Overview
- **Owner**: [Name]
- **Test ID**: [ID in testing tool]
- **Page/Feature**: [What's being tested]
- **Planned dates**: [Start] - [End]
## Hypothesis
Because [observation/data],
we believe [change]
will cause [expected outcome]
for [audience].
We'll know this is true when [metrics].
## Test Design
| Element | Details |
| ------------------ | ------------------------- |
| Test type | A/B / A/B/n / MVT |
| Duration | X weeks |
| Sample size | X per variant |
| Traffic allocation | 50/50 |
| Tool | [Tool name] |
| Implementation | Client-side / Server-side |
## Variants
### Control (A)
[Screenshot]
- Current experience
- [Key details about current state]
### Variant (B)
[Screenshot or mockup]
- [Specific change #1]
- [Specific change #2]
- Rationale: [Why we think this will win]
## Metrics
### Primary
- **Metric**: [metric name]
- **Definition**: [how it's calculated]
- **Current baseline**: [X%]
- **Minimum detectable effect**: [X%]
### Secondary
- [Metric 1]: [what it tells us]
- [Metric 2]: [what it tells us]
- [Metric 3]: [what it tells us]
### Guardrails
- [Metric that shouldn't get worse]
- [Another safety metric]
## Segment Analysis Plan
- Mobile vs. desktop
- New vs. returning visitors
- Traffic source
- [Other relevant segments]
## Success Criteria
- Winner: [Primary metric improves by X% with 95% confidence]
- Loser: [Primary metric decreases significantly]
- Inconclusive: [What we'll do if no significant result]
## Pre-Launch Checklist
- [ ] Hypothesis documented and reviewed
- [ ] Primary metric defined and trackable
- [ ] Sample size calculated
- [ ] Test duration estimated
- [ ] Variants implemented correctly
- [ ] Tracking verified in all variants
- [ ] QA completed on all variants
- [ ] Stakeholders informed
- [ ] Calendar hold for analysis date
```
---
## Results Documentation Template
```markdown
# A/B Test Results: [Name]
## Summary
| Element | Value |
| -------- | ----------------------------- |
| Test ID | [ID] |
| Dates | [Start] - [End] |
| Duration | X days |
| Result | Winner / Loser / Inconclusive |
| Decision | [What we're doing] |
## Hypothesis (Reminder)
[Copy from test plan]
## Results
### Sample Size
| Variant | Target | Actual | % of target |
| ------- | ------ | ------ | ----------- |
| Control | X | Y | Z% |
| Variant | X | Y | Z% |
### Primary Metric: [Metric Name]
| Variant | Value | 95% CI | vs. Control |
| ------- | ----- | -------- | ----------- |
| Control | X% | [X%, Y%] | — |
| Variant | X% | [X%, Y%] | +X% |
**Statistical significance**: p = X.XX (95% = sig / not sig)
**Practical significance**: [Is this lift meaningful for the business?]
### Secondary Metrics
| Metric | Control | Variant | Change | Significant? |
| ---------- | ------- | ------- | ------ | ------------ |
| [Metric 1] | X | Y | +Z% | Yes/No |
| [Metric 2] | X | Y | +Z% | Yes/No |
### Guardrail Metrics
| Metric | Control | Variant | Change | Concern? |
| ---------- | ------- | ------- | ------ | -------- |
| [Metric 1] | X | Y | +Z% | Yes/No |
### Segment Analysis
**Mobile vs. Desktop**
| Segment | Control | Variant | Lift |
|---------|---------|---------|------|
| Mobile | X% | Y% | +Z% |
| Desktop | X% | Y% | +Z% |
**New vs. Returning**
| Segment | Control | Variant | Lift |
|---------|---------|---------|------|
| New | X% | Y% | +Z% |
| Returning | X% | Y% | +Z% |
## Interpretation
### What happened?
[Explanation of results in plain language]
### Why do we think this happened?
[Analysis and reasoning]
### Caveats
[Any limitations, external factors, or concerns]
## Decision
**Winner**: [Control / Variant]
**Action**: [Implement variant / Keep control / Re-test]
**Timeline**: [When changes will be implemented]
## Learnings
### What we learned
- [Key insight 1]
- [Key insight 2]
### What to test next
- [Follow-up test idea 1]
- [Follow-up test idea 2]
### Impact
- **Projected lift**: [X% improvement in Y metric]
- **Business impact**: [Revenue, conversions, etc.]
```
---
## Test Repository Entry Template
For tracking all tests in a central location:
```markdown
| Test ID | Name | Page | Dates | Primary Metric | Result | Lift | Link |
| ------- | -------------------- | -------- | --------- | -------------- | ------------ | ---- | ------ |
| 001 | Hero headline test | Homepage | 1/1-1/15 | CTR | Winner | +12% | [Link] |
| 002 | Pricing table layout | Pricing | 1/10-1/31 | Plan selection | Loser | -5% | [Link] |
| 003 | Signup form fields | Signup | 2/1-2/14 | Completion | Inconclusive | +2% | [Link] |
```
---
## Quick Test Brief Template
For simple tests that don't need full documentation:
```markdown
## [Test Name]
**What**: [One sentence description]
**Why**: [One sentence hypothesis]
**Metric**: [Primary metric]
**Duration**: [X weeks]
**Result**: [TBD / Winner / Loser / Inconclusive]
**Learnings**: [Key takeaway]
```
---
## Stakeholder Update Template
```markdown
## A/B Test Update: [Name]
**Status**: Running / Complete
**Days remaining**: X (or complete)
**Current sample**: X% of target
### Preliminary observations
[What we're seeing - without making decisions yet]
### Next steps
[What happens next]
### Timeline
- [Date]: Analysis complete
- [Date]: Decision and recommendation
- [Date]: Implementation 'if winner'
```
---
## Experiment Prioritization Scorecard
For deciding which tests to run:
| Factor | Weight | Test A | Test B | Test C |
| ------------------------ | ------ | ------ | ------ | ------ |
| Potential impact | 30% | | | |
| Confidence in hypothesis | 25% | | | |
| Ease of implementation | 20% | | | |
| Risk if wrong | 15% | | | |
| Strategic alignment | 10% | | | |
| **Total** | | | | |
Scoring: 1-5 (5 = best)
---
## Hypothesis Bank Template
For collecting test ideas:
```markdown
| ID | Page/Area | Observation | Hypothesis | Potential Impact | Status |
| --- | --------- | ------------------- | ------------------------------------- | ---------------- | ------- |
| H1 | Homepage | Low scroll depth | Shorter hero will increase scroll | High | Testing |
| H2 | Pricing | Users compare plans | Comparison table will help | Medium | Backlog |
| H3 | Signup | Drop-off at email | Social login will increase completion | Medium | Backlog |
```
@@ -0,0 +1,78 @@
---
name: ai-sdk
description: 'Answer questions about the AI SDK and help build AI-powered features. Use when developers: (1) Ask about AI SDK functions like generateText, streamText, ToolLoopAgent, embed, or tools, (2) Want to build AI agents, chatbots, RAG systems, or text generation features, (3) Have questions about AI providers (OpenAI, Anthropic, Google, etc.), streaming, tool calling, structured output, or embeddings, (4) Use React hooks like useChat or useCompletion. Triggers on: "AI SDK", "Vercel AI SDK", "generateText", "streamText", "add AI to my app", "build an agent", "tool calling", "structured output", "useChat".'
---
## Prerequisites
Before searching docs, check if `node_modules/ai/docs/` exists. If not, install **only** the `ai` package using the project's package manager (e.g., `pnpm add ai`).
Do not install other packages at this stage. Provider packages (e.g., `@ai-sdk/openai`) and client packages (e.g., `@ai-sdk/react`) should be installed later when needed based on user requirements.
## Critical: Do Not Trust Internal Knowledge
Everything you know about the AI SDK is outdated or wrong. Your training data contains obsolete APIs, deprecated patterns, and incorrect usage.
**When working with the AI SDK:**
1. Ensure `ai` package is installed (see Prerequisites)
2. Search `node_modules/ai/docs/` and `node_modules/ai/src/` for current APIs
3. If not found locally, search ai-sdk.dev documentation (instructions below)
4. Never rely on memory - always verify against source code or docs
5. **`useChat` has changed significantly** - check [Common Errors](references/common-errors.md) before writing client code
6. When deciding which model and provider to use (e.g. OpenAI, Anthropic, Gemini), use the Vercel AI Gateway provider unless the user specifies otherwise. See [AI Gateway Reference](references/ai-gateway.md) for usage details.
7. **Always fetch current model IDs** - Never use model IDs from memory. Before writing code that uses a model, run `curl -s https://ai-gateway.vercel.sh/v1/models | jq -r '[.data[] | select(.id | startswith("provider/")) | .id] | reverse | .[]'` (replacing `provider` with the relevant provider like `anthropic`, `openai`, or `google`) to get the full list with newest models first. Use the model with the highest version number (e.g., `claude-sonnet-4-5` over `claude-sonnet-4` over `claude-3-5-sonnet`).
8. Run typecheck after changes to ensure code is correct
9. **Be minimal** - Only specify options that differ from defaults. When unsure of defaults, check docs or source rather than guessing or over-specifying.
If you cannot find documentation to support your answer, state that explicitly.
## Finding Documentation
### ai@6.0.34+
Search bundled docs and source in `node_modules/ai/`:
- **Docs**: `grep "query" node_modules/ai/docs/`
- **Source**: `grep "query" node_modules/ai/src/`
Provider packages include docs at `node_modules/@ai-sdk/<provider>/docs/`.
### Earlier versions
1. Search: `https://ai-sdk.dev/api/search-docs?q=your_query`
2. Fetch `.md` URLs from results (e.g., `https://ai-sdk.dev/docs/agents/building-agents.md`)
## When Typecheck Fails
**Before searching source code**, grep [Common Errors](references/common-errors.md) for the failing property or function name. Many type errors are caused by deprecated APIs documented there.
If not found in common-errors.md:
1. Search `node_modules/ai/src/` and `node_modules/ai/docs/`
2. Search ai-sdk.dev (for earlier versions or if not found locally)
## Building and Consuming Agents
### Creating Agents
Always use the `ToolLoopAgent` pattern. Search `node_modules/ai/docs/` for current agent creation APIs.
**File conventions**: See [type-safe-agents.md](references/type-safe-agents.md) for where to save agents and tools.
**Type Safety**: When consuming agents with `useChat`, always use `InferAgentUIMessage<typeof agent>` for type-safe tool results. See [reference](references/type-safe-agents.md).
### Consuming Agents (Framework-Specific)
Before implementing agent consumption:
1. Check `package.json` to detect the project's framework/stack
2. Search documentation for the framework's quickstart guide
3. Follow the framework-specific patterns for streaming, API routes, and client integration
## References
- [Common Errors](references/common-errors.md) - Renamed parameters reference (parameters → inputSchema, etc.)
- [AI Gateway](references/ai-gateway.md) - Gateway setup and usage
- [Type-Safe Agents with useChat](references/type-safe-agents.md) - End-to-end type safety with InferAgentUIMessage
- [DevTools](references/devtools.md) - Set up local debugging and observability (development only)
@@ -0,0 +1,66 @@
---
title: Vercel AI Gateway
description: Reference for using Vercel AI Gateway with the AI SDK.
---
# Vercel AI Gateway
The Vercel AI Gateway is the fastest way to get started with the AI SDK. It provides access to models from OpenAI, Anthropic, Google, and other providers through a single API.
## Authentication
Authenticate with OIDC (for Vercel deployments) or an [AI Gateway API key](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai-gateway%2Fapi-keys&title=AI+Gateway+API+Keys):
```env filename=".env.local"
AI_GATEWAY_API_KEY=your_api_key_here
```
## Usage
The AI Gateway is the default global provider, so you can access models using a simple string:
```ts
import { generateText } from 'ai';
const { text } = await generateText({
model: 'anthropic/claude-sonnet-4.5',
prompt: 'What is love?',
});
```
You can also explicitly import and use the gateway provider:
```ts
// Option 1: Import from 'ai' package (included by default)
import { gateway } from 'ai';
model: gateway('anthropic/claude-sonnet-4.5');
// Option 2: Install and import from '@ai-sdk/gateway' package
import { gateway } from '@ai-sdk/gateway';
model: gateway('anthropic/claude-sonnet-4.5');
```
## Find Available Models
**Important**: Always fetch the current model list before writing code. Never use model IDs from memory - they may be outdated.
List all available models through the gateway API:
```bash
curl https://ai-gateway.vercel.sh/v1/models
```
Filter by provider using `jq`. **Do not truncate with `head`** - always fetch the full list to find the latest models:
```bash
# Anthropic models
curl -s https://ai-gateway.vercel.sh/v1/models | jq -r '[.data[] | select(.id | startswith("anthropic/")) | .id] | reverse | .[]'
# OpenAI models
curl -s https://ai-gateway.vercel.sh/v1/models | jq -r '[.data[] | select(.id | startswith("openai/")) | .id] | reverse | .[]'
# Google models
curl -s https://ai-gateway.vercel.sh/v1/models | jq -r '[.data[] | select(.id | startswith("google/")) | .id] | reverse | .[]'
```
When multiple versions of a model exist, use the one with the highest version number (e.g., prefer `claude-sonnet-4-5` over `claude-sonnet-4` over `claude-3-5-sonnet`).
@@ -0,0 +1,439 @@
---
title: Common Errors
description: Reference for common AI SDK errors and how to resolve them.
---
# Common Errors
## `maxTokens``maxOutputTokens`
```typescript
// ❌ Incorrect
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
maxTokens: 512, // deprecated: use `maxOutputTokens` instead
prompt: 'Write a short story',
});
// ✅ Correct
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
maxOutputTokens: 512,
prompt: 'Write a short story',
});
```
## `maxSteps``stopWhen: stepCountIs(n)`
```typescript
// ❌ Incorrect
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
tools: { weather },
maxSteps: 5, // deprecated: use `stopWhen: stepCountIs(n)` instead
prompt: 'What is the weather in NYC?',
});
// ✅ Correct
import { generateText, stepCountIs } from 'ai';
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
tools: { weather },
stopWhen: stepCountIs(5),
prompt: 'What is the weather in NYC?',
});
```
## `parameters``inputSchema` (in tool definition)
```typescript
// ❌ Incorrect
const weatherTool = tool({
description: 'Get weather for a location',
parameters: z.object({
// deprecated: use `inputSchema` instead
location: z.string(),
}),
execute: async ({ location }) => ({ location, temp: 72 }),
});
// ✅ Correct
const weatherTool = tool({
description: 'Get weather for a location',
inputSchema: z.object({
location: z.string(),
}),
execute: async ({ location }) => ({ location, temp: 72 }),
});
```
## `generateObject``generateText` with `output`
`generateObject` is deprecated. Use `generateText` with the `output` option instead.
```typescript
// ❌ Deprecated
import { generateObject } from 'ai'; // deprecated: use `generateText` with `output` instead
const result = await generateObject({
// deprecated function
model: 'anthropic/claude-opus-4.5',
schema: z.object({
// deprecated: use `Output.object({ schema })` instead
recipe: z.object({
name: z.string(),
ingredients: z.array(z.string()),
}),
}),
prompt: 'Generate a recipe for chocolate cake',
});
// ✅ Correct
import { generateText, Output } from 'ai';
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
output: Output.object({
schema: z.object({
recipe: z.object({
name: z.string(),
ingredients: z.array(z.string()),
}),
}),
}),
prompt: 'Generate a recipe for chocolate cake',
});
console.log(result.output); // typed object
```
## Manual JSON parsing → `generateText` with `output`
```typescript
// ❌ Incorrect
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
prompt: `Extract the user info as JSON: { "name": string, "age": number }
Input: John is 25 years old`,
});
const parsed = JSON.parse(result.text);
// ✅ Correct
import { generateText, Output } from 'ai';
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
output: Output.object({
schema: z.object({
name: z.string(),
age: z.number(),
}),
}),
prompt: 'Extract the user info: John is 25 years old',
});
console.log(result.output); // { name: 'John', age: 25 }
```
## Other `output` options
```typescript
// Output.array - for generating arrays of items
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
output: Output.array({
element: z.object({
city: z.string(),
country: z.string(),
}),
}),
prompt: 'List 5 capital cities',
});
// Output.choice - for selecting from predefined options
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
output: Output.choice({
options: ['positive', 'negative', 'neutral'] as const,
}),
prompt: 'Classify the sentiment: I love this product!',
});
// Output.json - for untyped JSON output
const result = await generateText({
model: 'anthropic/claude-opus-4.5',
output: Output.json(),
prompt: 'Return some JSON data',
});
```
## `toDataStreamResponse``toUIMessageStreamResponse`
When using `useChat` on the frontend, use `toUIMessageStreamResponse()` instead of `toDataStreamResponse()`. The UI message stream format is designed to work with the chat UI components and handles message state correctly.
```typescript
// ❌ Incorrect (when using useChat)
const result = streamText({
// config
});
return result.toDataStreamResponse(); // deprecated for useChat: use toUIMessageStreamResponse
// ✅ Correct
const result = streamText({
// config
});
return result.toUIMessageStreamResponse();
```
## Removed managed input state in `useChat`
The `useChat` hook no longer manages input state internally. You must now manage input state manually.
```tsx
// ❌ Deprecated
import { useChat } from '@ai-sdk/react';
export default function Page() {
const {
input, // deprecated: manage input state manually with useState
handleInputChange, // deprecated: use custom onChange handler
handleSubmit, // deprecated: use sendMessage() instead
} = useChat({
api: '/api/chat', // deprecated: use `transport: new DefaultChatTransport({ api })` instead
});
return (
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
);
}
// ✅ Correct
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';
export default function Page() {
const [input, setInput] = useState('');
const { sendMessage } = useChat({
transport: new DefaultChatTransport({ api: '/api/chat' }),
});
const handleSubmit = (e) => {
e.preventDefault();
sendMessage({ text: input });
setInput('');
};
return (
<form onSubmit={handleSubmit}>
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button type="submit">Send</button>
</form>
);
}
```
## `tool-invocation``tool-{toolName}` (typed tool parts)
When rendering messages with `useChat`, use the typed tool part names (`tool-{toolName}`) instead of the generic `tool-invocation` type. This provides better type safety and access to tool-specific input/output types.
> For end-to-end type-safety, see [Type-Safe Agents](type-safe-agents.md).
Typed tool parts also use different property names:
- `part.args``part.input`
- `part.result``part.output`
```tsx
// ❌ Incorrect - using generic tool-invocation
{
message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <div key={`${message.id}-${i}`}>{part.text}</div>;
case 'tool-invocation': // deprecated: use typed tool parts instead
return <pre key={`${message.id}-${i}`}>{JSON.stringify(part.toolInvocation, null, 2)}</pre>;
}
});
}
// ✅ Correct - using typed tool parts (recommended)
{
message.parts.map((part) => {
switch (part.type) {
case 'text':
return part.text;
case 'tool-askForConfirmation':
// handle askForConfirmation tool
break;
case 'tool-getWeatherInformation':
// handle getWeatherInformation tool
break;
}
});
}
// ✅ Alternative - using isToolUIPart as a catch-all
import { isToolUIPart } from 'ai';
{
message.parts.map((part) => {
if (part.type === 'text') {
return part.text;
}
if (isToolUIPart(part)) {
// handle any tool part generically
return (
<div key={part.toolCallId}>
{part.toolName}: {part.state}
</div>
);
}
});
}
```
## `useChat` state-dependent property access
Tool part properties are only available in certain states. TypeScript will error if you access them without checking state first.
```tsx
// ❌ Incorrect - input may be undefined during streaming
// TS18048: 'part.input' is possibly 'undefined'
if (part.type === 'tool-getWeather') {
const location = part.input.location;
}
// ✅ Correct - check for input-available or output-available
if (
part.type === 'tool-getWeather' &&
(part.state === 'input-available' || part.state === 'output-available')
) {
const location = part.input.location;
}
// ❌ Incorrect - output is only available after execution
// TS18048: 'part.output' is possibly 'undefined'
if (part.type === 'tool-getWeather') {
const weather = part.output;
}
// ✅ Correct - check for output-available
if (part.type === 'tool-getWeather' && part.state === 'output-available') {
const location = part.input.location;
const weather = part.output;
}
```
## `part.toolInvocation.args``part.input`
```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
// deprecated: use `part.input` on typed tool parts instead
const location = part.toolInvocation.args.location;
}
// ✅ Correct
if (
part.type === 'tool-getWeather' &&
(part.state === 'input-available' || part.state === 'output-available')
) {
const location = part.input.location;
}
```
## `part.toolInvocation.result``part.output`
```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
// deprecated: use `part.output` on typed tool parts instead
const weather = part.toolInvocation.result;
}
// ✅ Correct
if (part.type === 'tool-getWeather' && part.state === 'output-available') {
const weather = part.output;
}
```
## `part.toolInvocation.toolCallId``part.toolCallId`
```tsx
// ❌ Incorrect
if (part.type === 'tool-invocation') {
// deprecated: use `part.toolCallId` on typed tool parts instead
const id = part.toolInvocation.toolCallId;
}
// ✅ Correct
if (part.type === 'tool-getWeather') {
const id = part.toolCallId;
}
```
## Tool invocation states renamed
```tsx
// ❌ Incorrect
switch (part.toolInvocation.state) {
case 'partial-call': // deprecated: use `input-streaming` instead
return <div>Loading...</div>;
case 'call': // deprecated: use `input-available` instead
return <div>Executing...</div>;
case 'result': // deprecated: use `output-available` instead
return <div>Done</div>;
}
// ✅ Correct
switch (part.state) {
case 'input-streaming':
return <div>Loading...</div>;
case 'input-available':
return <div>Executing...</div>;
case 'output-available':
return <div>Done</div>;
}
```
## `addToolResult``addToolOutput`
```tsx
// ❌ Incorrect
addToolResult({
// deprecated: use `addToolOutput` instead
toolCallId: part.toolInvocation.toolCallId,
result: 'Yes, confirmed.', // deprecated: use `output` instead
});
// ✅ Correct
addToolOutput({
tool: 'askForConfirmation',
toolCallId: part.toolCallId,
output: 'Yes, confirmed.',
});
```
## `messages``uiMessages` in `createAgentUIStreamResponse`
```typescript
// ❌ Incorrect
return createAgentUIStreamResponse({
agent: myAgent,
messages, // incorrect: use `uiMessages` instead
});
// ✅ Correct
return createAgentUIStreamResponse({
agent: myAgent,
uiMessages: messages,
});
```
@@ -0,0 +1,52 @@
---
title: AI SDK DevTools
description: Debug AI SDK calls by inspecting captured runs and steps.
---
# AI SDK DevTools
## Why Use DevTools
DevTools captures all AI SDK calls (`generateText`, `streamText`, `ToolLoopAgent`) to a local JSON file. This lets you inspect LLM requests, responses, tool calls, and multi-step interactions without manually logging.
## Setup
Requires AI SDK 6. Install `@ai-sdk/devtools` using your project's package manager.
Wrap your model with the middleware:
```ts
import { wrapLanguageModel, gateway } from 'ai';
import { devToolsMiddleware } from '@ai-sdk/devtools';
const model = wrapLanguageModel({
model: gateway('anthropic/claude-sonnet-4.5'),
middleware: devToolsMiddleware(),
});
```
## Viewing Captured Data
All runs and steps are saved to:
```
.devtools/generations.json
```
Read this file directly to inspect captured data:
```bash
cat .devtools/generations.json | jq
```
Or launch the web UI:
```bash
npx @ai-sdk/devtools
# Open http://localhost:4983
```
## Data Structure
- **Run**: A complete multi-step interaction grouped by initial prompt
- **Step**: A single LLM call within a run (includes input, output, tool calls, token usage)
@@ -0,0 +1,200 @@
---
title: Type-Safe useChat with Agents
description: Build end-to-end type-safe agents by inferring UIMessage types from your agent definition.
---
# Type-Safe useChat with Agents
Build end-to-end type-safe agents by inferring `UIMessage` types from your agent definition for type-safe UI rendering with `useChat`.
## Recommended Structure
```
lib/
agents/
my-agent.ts # Agent definition + type export
tools/
weather-tool.ts # Individual tool definitions
calculator-tool.ts
```
## Define Tools
```ts
// lib/tools/weather-tool.ts
import { tool } from 'ai';
import { z } from 'zod';
export const weatherTool = tool({
description: 'Get current weather for a location',
inputSchema: z.object({
location: z.string().describe('City name'),
}),
execute: async ({ location }) => {
return { temperature: 72, condition: 'sunny', location };
},
});
```
## Define Agent and Export Type
```ts
// lib/agents/my-agent.ts
import { ToolLoopAgent, InferAgentUIMessage } from 'ai';
import { weatherTool } from '../tools/weather-tool';
import { calculatorTool } from '../tools/calculator-tool';
export const myAgent = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-4',
instructions: 'You are a helpful assistant.',
tools: {
weather: weatherTool,
calculator: calculatorTool,
},
});
// Infer the UIMessage type from the agent
export type MyAgentUIMessage = InferAgentUIMessage<typeof myAgent>;
```
### With Custom Metadata
```ts
// lib/agents/my-agent.ts
import { z } from 'zod';
const metadataSchema = z.object({
createdAt: z.number(),
model: z.string().optional(),
});
type MyMetadata = z.infer<typeof metadataSchema>;
export type MyAgentUIMessage = InferAgentUIMessage<typeof myAgent, MyMetadata>;
```
## Use with `useChat`
```tsx
// app/chat.tsx
import { useChat } from '@ai-sdk/react';
import type { MyAgentUIMessage } from '@/lib/agents/my-agent';
export function Chat() {
const { messages } = useChat<MyAgentUIMessage>();
return (
<div>
{messages.map((message) => (
<Message key={message.id} message={message} />
))}
</div>
);
}
```
## Rendering Parts with Type Safety
Tool parts are typed as `tool-{toolName}` based on your agent's tools:
```tsx
function Message({ message }: { message: MyAgentUIMessage }) {
return (
<div>
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <p key={i}>{part.text}</p>;
case 'tool-weather':
// part.input and part.output are fully typed
if (part.state === 'output-available') {
return (
<div key={i}>
Weather in {part.input.location}: {part.output.temperature}F
</div>
);
}
return <div key={i}>Loading weather...</div>;
case 'tool-calculator':
// TypeScript knows this is the calculator tool
return <div key={i}>Calculating...</div>;
default:
return null;
}
})}
</div>
);
}
```
The `part.type` discriminant narrows the type, giving you autocomplete and type checking for `input` and `output` based on each tool's schema.
## Splitting Tool Rendering into Components
When rendering many tools, you may want to split each tool into its own component. Use `UIToolInvocation<TOOL>` to derive a typed invocation from your tool and export it alongside the tool definition:
```ts
// lib/tools/weather-tool.ts
import { tool, UIToolInvocation } from 'ai';
import { z } from 'zod';
export const weatherTool = tool({
description: 'Get current weather for a location',
inputSchema: z.object({
location: z.string().describe('City name'),
}),
execute: async ({ location }) => {
return { temperature: 72, condition: 'sunny', location };
},
});
// Export the invocation type for use in UI components
export type WeatherToolInvocation = UIToolInvocation<typeof weatherTool>;
```
Then import only the type in your component:
```tsx
// components/weather-tool.tsx
import type { WeatherToolInvocation } from '@/lib/tools/weather-tool';
export function WeatherToolComponent({ invocation }: { invocation: WeatherToolInvocation }) {
// invocation.input and invocation.output are fully typed
if (invocation.state === 'output-available') {
return (
<div>
Weather in {invocation.input.location}: {invocation.output.temperature}F
</div>
);
}
return <div>Loading weather for {invocation.input?.location}...</div>;
}
```
Use the component in your message renderer:
```tsx
function Message({ message }: { message: MyAgentUIMessage }) {
return (
<div>
{message.parts.map((part, i) => {
switch (part.type) {
case 'text':
return <p key={i}>{part.text}</p>;
case 'tool-weather':
return <WeatherToolComponent key={i} invocation={part} />;
case 'tool-calculator':
return <CalculatorToolComponent key={i} invocation={part} />;
default:
return null;
}
})}
</div>
);
}
```
This approach keeps your tool rendering logic organized while maintaining full type safety, without needing to import the tool implementation into your UI components.
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,443 @@
---
name: algorithmic-art
description: Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
license: Complete terms in LICENSE.txt
---
Algorithmic philosophies are computational aesthetic movements that are then expressed through code. Output .md files (philosophy), .html files (interactive viewer), and .js files (generative algorithms).
This happens in two steps:
1. Algorithmic Philosophy Creation (.md file)
2. Express by creating p5.js generative art (.html + .js files)
First, undertake this task:
## ALGORITHMIC PHILOSOPHY CREATION
To begin, create an ALGORITHMIC PHILOSOPHY (not static images or templates) that will be interpreted through:
- Computational processes, emergent behavior, mathematical beauty
- Seeded randomness, noise fields, organic systems
- Particles, flows, fields, forces
- Parametric variation and controlled chaos
### THE CRITICAL UNDERSTANDING
- What is received: Some subtle input or instructions by the user to take into account, but use as a foundation; it should not constrain creative freedom.
- What is created: An algorithmic philosophy/generative aesthetic movement.
- What happens next: The same version receives the philosophy and EXPRESSES IT IN CODE - creating p5.js sketches that are 90% algorithmic generation, 10% essential parameters.
Consider this approach:
- Write a manifesto for a generative art movement
- The next phase involves writing the algorithm that brings it to life
The philosophy must emphasize: Algorithmic expression. Emergent behavior. Computational beauty. Seeded variation.
### HOW TO GENERATE AN ALGORITHMIC PHILOSOPHY
**Name the movement** (1-2 words): "Organic Turbulence" / "Quantum Harmonics" / "Emergent Stillness"
**Articulate the philosophy** (4-6 paragraphs - concise but complete):
To capture the ALGORITHMIC essence, express how this philosophy manifests through:
- Computational processes and mathematical relationships?
- Noise functions and randomness patterns?
- Particle behaviors and field dynamics?
- Temporal evolution and system states?
- Parametric variation and emergent complexity?
**CRITICAL GUIDELINES:**
- **Avoid redundancy**: Each algorithmic aspect should be mentioned once. Avoid repeating concepts about noise theory, particle dynamics, or mathematical principles unless adding new depth.
- **Emphasize craftsmanship REPEATEDLY**: The philosophy MUST stress multiple times that the final algorithm should appear as though it took countless hours to develop, was refined with care, and comes from someone at the absolute top of their field. This framing is essential - repeat phrases like "meticulously crafted algorithm," "the product of deep computational expertise," "painstaking optimization," "master-level implementation."
- **Leave creative space**: Be specific about the algorithmic direction, but concise enough that the next Claude has room to make interpretive implementation choices at an extremely high level of craftsmanship.
The philosophy must guide the next version to express ideas ALGORITHMICALLY, not through static images. Beauty lives in the process, not the final frame.
### PHILOSOPHY EXAMPLES
**"Organic Turbulence"**
Philosophy: Chaos constrained by natural law, order emerging from disorder.
Algorithmic expression: Flow fields driven by layered Perlin noise. Thousands of particles following vector forces, their trails accumulating into organic density maps. Multiple noise octaves create turbulent regions and calm zones. Color emerges from velocity and density - fast particles burn bright, slow ones fade to shadow. The algorithm runs until equilibrium - a meticulously tuned balance where every parameter was refined through countless iterations by a master of computational aesthetics.
**"Quantum Harmonics"**
Philosophy: Discrete entities exhibiting wave-like interference patterns.
Algorithmic expression: Particles initialized on a grid, each carrying a phase value that evolves through sine waves. When particles are near, their phases interfere - constructive interference creates bright nodes, destructive creates voids. Simple harmonic motion generates complex emergent mandalas. The result of painstaking frequency calibration where every ratio was carefully chosen to produce resonant beauty.
**"Recursive Whispers"**
Philosophy: Self-similarity across scales, infinite depth in finite space.
Algorithmic expression: Branching structures that subdivide recursively. Each branch slightly randomized but constrained by golden ratios. L-systems or recursive subdivision generate tree-like forms that feel both mathematical and organic. Subtle noise perturbations break perfect symmetry. Line weights diminish with each recursion level. Every branching angle the product of deep mathematical exploration.
**"Field Dynamics"**
Philosophy: Invisible forces made visible through their effects on matter.
Algorithmic expression: Vector fields constructed from mathematical functions or noise. Particles born at edges, flowing along field lines, dying when they reach equilibrium or boundaries. Multiple fields can attract, repel, or rotate particles. The visualization shows only the traces - ghost-like evidence of invisible forces. A computational dance meticulously choreographed through force balance.
**"Stochastic Crystallization"**
Philosophy: Random processes crystallizing into ordered structures.
Algorithmic expression: Randomized circle packing or Voronoi tessellation. Start with random points, let them evolve through relaxation algorithms. Cells push apart until equilibrium. Color based on cell size, neighbor count, or distance from center. The organic tiling that emerges feels both random and inevitable. Every seed produces unique crystalline beauty - the mark of a master-level generative algorithm.
_These are condensed examples. The actual algorithmic philosophy should be 4-6 substantial paragraphs._
### ESSENTIAL PRINCIPLES
- **ALGORITHMIC PHILOSOPHY**: Creating a computational worldview to be expressed through code
- **PROCESS OVER PRODUCT**: Always emphasize that beauty emerges from the algorithm's execution - each run is unique
- **PARAMETRIC EXPRESSION**: Ideas communicate through mathematical relationships, forces, behaviors - not static composition
- **ARTISTIC FREEDOM**: The next Claude interprets the philosophy algorithmically - provide creative implementation room
- **PURE GENERATIVE ART**: This is about making LIVING ALGORITHMS, not static images with randomness
- **EXPERT CRAFTSMANSHIP**: Repeatedly emphasize the final algorithm must feel meticulously crafted, refined through countless iterations, the product of deep expertise by someone at the absolute top of their field in computational aesthetics
**The algorithmic philosophy should be 4-6 paragraphs long.** Fill it with poetic computational philosophy that brings together the intended vision. Avoid repeating the same points. Output this algorithmic philosophy as a .md file.
---
## DEDUCING THE CONCEPTUAL SEED
**CRITICAL STEP**: Before implementing the algorithm, identify the subtle conceptual thread from the original request.
**THE ESSENTIAL PRINCIPLE**:
The concept is a **subtle, niche reference embedded within the algorithm itself** - not always literal, always sophisticated. Someone familiar with the subject should feel it intuitively, while others simply experience a masterful generative composition. The algorithmic philosophy provides the computational language. The deduced concept provides the soul - the quiet conceptual DNA woven invisibly into parameters, behaviors, and emergence patterns.
This is **VERY IMPORTANT**: The reference must be so refined that it enhances the work's depth without announcing itself. Think like a jazz musician quoting another song through algorithmic harmony - only those who know will catch it, but everyone appreciates the generative beauty.
---
## P5.JS IMPLEMENTATION
With the philosophy AND conceptual framework established, express it through code. Pause to gather thoughts before proceeding. Use only the algorithmic philosophy created and the instructions below.
### ⚠️ STEP 0: READ THE TEMPLATE FIRST ⚠️
**CRITICAL: BEFORE writing any HTML:**
1. **Read** `templates/viewer.html` using the Read tool
2. **Study** the exact structure, styling, and Anthropic branding
3. **Use that file as the LITERAL STARTING POINT** - not just inspiration
4. **Keep all FIXED sections exactly as shown** (header, sidebar structure, Anthropic colors/fonts, seed controls, action buttons)
5. **Replace only the VARIABLE sections** marked in the file's comments (algorithm, parameters, UI controls for parameters)
**Avoid:**
- ❌ Creating HTML from scratch
- ❌ Inventing custom styling or color schemes
- ❌ Using system fonts or dark themes
- ❌ Changing the sidebar structure
**Follow these practices:**
- ✅ Copy the template's exact HTML structure
- ✅ Keep Anthropic branding (Poppins/Lora fonts, light colors, gradient backdrop)
- ✅ Maintain the sidebar layout (Seed → Parameters → Colors? → Actions)
- ✅ Replace only the p5.js algorithm and parameter controls
The template is the foundation. Build on it, don't rebuild it.
---
To create gallery-quality computational art that lives and breathes, use the algorithmic philosophy as the foundation.
### TECHNICAL REQUIREMENTS
**Seeded Randomness (Art Blocks Pattern)**:
```javascript
// ALWAYS use a seed for reproducibility
let seed = 12345; // or hash from user input
randomSeed(seed);
noiseSeed(seed);
```
**Parameter Structure - FOLLOW THE PHILOSOPHY**:
To establish parameters that emerge naturally from the algorithmic philosophy, consider: "What qualities of this system can be adjusted?"
```javascript
let params = {
seed: 12345, // Always include seed for reproducibility
// colors
// Add parameters that control YOUR algorithm:
// - Quantities (how many?)
// - Scales (how big? how fast?)
// - Probabilities (how likely?)
// - Ratios (what proportions?)
// - Angles (what direction?)
// - Thresholds (when does behavior change?)
};
```
**To design effective parameters, focus on the properties the system needs to be tunable rather than thinking in terms of "pattern types".**
**Core Algorithm - EXPRESS THE PHILOSOPHY**:
**CRITICAL**: The algorithmic philosophy should dictate what to build.
To express the philosophy through code, avoid thinking "which pattern should I use?" and instead think "how to express this philosophy through code?"
If the philosophy is about **organic emergence**, consider using:
- Elements that accumulate or grow over time
- Random processes constrained by natural rules
- Feedback loops and interactions
If the philosophy is about **mathematical beauty**, consider using:
- Geometric relationships and ratios
- Trigonometric functions and harmonics
- Precise calculations creating unexpected patterns
If the philosophy is about **controlled chaos**, consider using:
- Random variation within strict boundaries
- Bifurcation and phase transitions
- Order emerging from disorder
**The algorithm flows from the philosophy, not from a menu of options.**
To guide the implementation, let the conceptual essence inform creative and original choices. Build something that expresses the vision for this particular request.
**Canvas Setup**: Standard p5.js structure:
```javascript
function setup() {
createCanvas(1200, 1200);
// Initialize your system
}
function draw() {
// Your generative algorithm
// Can be static (noLoop) or animated
}
```
### CRAFTSMANSHIP REQUIREMENTS
**CRITICAL**: To achieve mastery, create algorithms that feel like they emerged through countless iterations by a master generative artist. Tune every parameter carefully. Ensure every pattern emerges with purpose. This is NOT random noise - this is CONTROLLED CHAOS refined through deep expertise.
- **Balance**: Complexity without visual noise, order without rigidity
- **Color Harmony**: Thoughtful palettes, not random RGB values
- **Composition**: Even in randomness, maintain visual hierarchy and flow
- **Performance**: Smooth execution, optimized for real-time if animated
- **Reproducibility**: Same seed ALWAYS produces identical output
### OUTPUT FORMAT
Output:
1. **Algorithmic Philosophy** - As markdown or text explaining the generative aesthetic
2. **Single HTML Artifact** - Self-contained interactive generative art built from `templates/viewer.html` (see STEP 0 and next section)
The HTML artifact contains everything: p5.js (from CDN), the algorithm, parameter controls, and UI - all in one file that works immediately in claude.ai artifacts or any browser. Start from the template file, not from scratch.
---
## INTERACTIVE ARTIFACT CREATION
**REMINDER: `templates/viewer.html` should have already been read (see STEP 0). Use that file as the starting point.**
To allow exploration of the generative art, create a single, self-contained HTML artifact. Ensure this artifact works immediately in claude.ai or any browser - no setup required. Embed everything inline.
### CRITICAL: WHAT'S FIXED VS VARIABLE
The `templates/viewer.html` file is the foundation. It contains the exact structure and styling needed.
**FIXED (always include exactly as shown):**
- Layout structure (header, sidebar, main canvas area)
- Anthropic branding (UI colors, fonts, gradients)
- Seed section in sidebar:
- Seed display
- Previous/Next buttons
- Random button
- Jump to seed input + Go button
- Actions section in sidebar:
- Regenerate button
- Reset button
**VARIABLE (customize for each artwork):**
- The entire p5.js algorithm (setup/draw/classes)
- The parameters object (define what the art needs)
- The Parameters section in sidebar:
- Number of parameter controls
- Parameter names
- Min/max/step values for sliders
- Control types (sliders, inputs, etc.)
- Colors section (optional):
- Some art needs color pickers
- Some art might use fixed colors
- Some art might be monochrome (no color controls needed)
- Decide based on the art's needs
**Every artwork should have unique parameters and algorithm!** The fixed parts provide consistent UX - everything else expresses the unique vision.
### REQUIRED FEATURES
**1. Parameter Controls**
- Sliders for numeric parameters (particle count, noise scale, speed, etc.)
- Color pickers for palette colors
- Real-time updates when parameters change
- Reset button to restore defaults
**2. Seed Navigation**
- Display current seed number
- "Previous" and "Next" buttons to cycle through seeds
- "Random" button for random seed
- Input field to jump to specific seed
- Generate 100 variations when requested (seeds 1-100)
**3. Single Artifact Structure**
```html
<!DOCTYPE html>
<html>
<head>
<!-- p5.js from CDN - always available -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
<style>
/* All styling inline - clean, minimal */
/* Canvas on top, controls below */
</style>
</head>
<body>
<div id="canvas-container"></div>
<div id="controls">
<!-- All parameter controls -->
</div>
<script>
// ALL p5.js code inline here
// Parameter objects, classes, functions
// setup() and draw()
// UI handlers
// Everything self-contained
</script>
</body>
</html>
```
**CRITICAL**: This is a single artifact. No external files, no imports (except p5.js CDN). Everything inline.
**4. Implementation Details - BUILD THE SIDEBAR**
The sidebar structure:
**1. Seed (FIXED)** - Always include exactly as shown:
- Seed display
- Prev/Next/Random/Jump buttons
**2. Parameters (VARIABLE)** - Create controls for the art:
```html
<div class="control-group">
<label>Parameter Name</label>
<input
type="range"
id="param"
min="..."
max="..."
step="..."
value="..."
oninput="updateParam('param', this.value)"
/>
<span class="value-display" id="param-value">...</span>
</div>
```
Add as many control-group divs as there are parameters.
**3. Colors (OPTIONAL/VARIABLE)** - Include if the art needs adjustable colors:
- Add color pickers if users should control palette
- Skip this section if the art uses fixed colors
- Skip if the art is monochrome
**4. Actions (FIXED)** - Always include exactly as shown:
- Regenerate button
- Reset button
- Download PNG button
**Requirements**:
- Seed controls must work (prev/next/random/jump/display)
- All parameters must have UI controls
- Regenerate, Reset, Download buttons must work
- Keep Anthropic branding (UI styling, not art colors)
### USING THE ARTIFACT
The HTML artifact works immediately:
1. **In claude.ai**: Displayed as an interactive artifact - runs instantly
2. **As a file**: Save and open in any browser - no server needed
3. **Sharing**: Send the HTML file - it's completely self-contained
---
## VARIATIONS & EXPLORATION
The artifact includes seed navigation by default (prev/next/random buttons), allowing users to explore variations without creating multiple files. If the user wants specific variations highlighted:
- Include seed presets (buttons for "Variation 1: Seed 42", "Variation 2: Seed 127", etc.)
- Add a "Gallery Mode" that shows thumbnails of multiple seeds side-by-side
- All within the same single artifact
This is like creating a series of prints from the same plate - the algorithm is consistent, but each seed reveals different facets of its potential. The interactive nature means users discover their own favorites by exploring the seed space.
---
## THE CREATIVE PROCESS
**User request** → **Algorithmic philosophy** → **Implementation**
Each request is unique. The process involves:
1. **Interpret the user's intent** - What aesthetic is being sought?
2. **Create an algorithmic philosophy** (4-6 paragraphs) describing the computational approach
3. **Implement it in code** - Build the algorithm that expresses this philosophy
4. **Design appropriate parameters** - What should be tunable?
5. **Build matching UI controls** - Sliders/inputs for those parameters
**The constants**:
- Anthropic branding (colors, fonts, layout)
- Seed navigation (always present)
- Self-contained HTML artifact
**Everything else is variable**:
- The algorithm itself
- The parameters
- The UI controls
- The visual outcome
To achieve the best results, trust creativity and let the philosophy guide the implementation.
---
## RESOURCES
This skill includes helpful templates and documentation:
- **templates/viewer.html**: REQUIRED STARTING POINT for all HTML artifacts.
- This is the foundation - contains the exact structure and Anthropic branding
- **Keep unchanged**: Layout structure, sidebar organization, Anthropic colors/fonts, seed controls, action buttons
- **Replace**: The p5.js algorithm, parameter definitions, and UI controls in Parameters section
- The extensive comments in the file mark exactly what to keep vs replace
- **templates/generator_template.js**: Reference for p5.js best practices and code structure principles.
- Shows how to organize parameters, use seeded randomness, structure classes
- NOT a pattern menu - use these principles to build unique algorithms
- Embed algorithms inline in the HTML artifact (don't create separate .js files)
**Critical reminder**:
- The **template is the STARTING POINT**, not inspiration
- The **algorithm is where to create** something unique
- Don't copy the flow field example - build what the philosophy demands
- But DO keep the exact UI structure and Anthropic branding from the template
@@ -0,0 +1,223 @@
/**
*
* P5.JS GENERATIVE ART - BEST PRACTICES
*
*
* This file shows STRUCTURE and PRINCIPLES for p5.js generative art.
* It does NOT prescribe what art you should create.
*
* Your algorithmic philosophy should guide what you build.
* These are just best practices for how to structure your code.
*
*
*/
// ============================================================================
// 1. PARAMETER ORGANIZATION
// ============================================================================
// Keep all tunable parameters in one object
// This makes it easy to:
// - Connect to UI controls
// - Reset to defaults
// - Serialize/save configurations
let params = {
// Define parameters that match YOUR algorithm
// Examples (customize for your art):
// - Counts: how many elements (particles, circles, branches, etc.)
// - Scales: size, speed, spacing
// - Probabilities: likelihood of events
// - Angles: rotation, direction
// - Colors: palette arrays
seed: 12345,
// define colorPalette as an array -- choose whatever colors you'd like ['#d97757', '#6a9bcc', '#788c5d', '#b0aea5']
// Add YOUR parameters here based on your algorithm
};
// ============================================================================
// 2. SEEDED RANDOMNESS (Critical for reproducibility)
// ============================================================================
// ALWAYS use seeded random for Art Blocks-style reproducible output
function initializeSeed(seed) {
randomSeed(seed);
noiseSeed(seed);
// Now all random() and noise() calls will be deterministic
}
// ============================================================================
// 3. P5.JS LIFECYCLE
// ============================================================================
function setup() {
createCanvas(800, 800);
// Initialize seed first
initializeSeed(params.seed);
// Set up your generative system
// This is where you initialize:
// - Arrays of objects
// - Grid structures
// - Initial positions
// - Starting states
// For static art: call noLoop() at the end of setup
// For animated art: let draw() keep running
}
function draw() {
// Option 1: Static generation (runs once, then stops)
// - Generate everything in setup()
// - Call noLoop() in setup()
// - draw() doesn't do much or can be empty
// Option 2: Animated generation (continuous)
// - Update your system each frame
// - Common patterns: particle movement, growth, evolution
// - Can optionally call noLoop() after N frames
// Option 3: User-triggered regeneration
// - Use noLoop() by default
// - Call redraw() when parameters change
}
// ============================================================================
// 4. CLASS STRUCTURE (When you need objects)
// ============================================================================
// Use classes when your algorithm involves multiple entities
// Examples: particles, agents, cells, nodes, etc.
class Entity {
constructor() {
// Initialize entity properties
// Use random() here - it will be seeded
}
update() {
// Update entity state
// This might involve:
// - Physics calculations
// - Behavioral rules
// - Interactions with neighbors
}
display() {
// Render the entity
// Keep rendering logic separate from update logic
}
}
// ============================================================================
// 5. PERFORMANCE CONSIDERATIONS
// ============================================================================
// For large numbers of elements:
// - Pre-calculate what you can
// - Use simple collision detection (spatial hashing if needed)
// - Limit expensive operations (sqrt, trig) when possible
// - Consider using p5 vectors efficiently
// For smooth animation:
// - Aim for 60fps
// - Profile if things are slow
// - Consider reducing particle counts or simplifying calculations
// ============================================================================
// 6. UTILITY FUNCTIONS
// ============================================================================
// Color utilities
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
function colorFromPalette(index) {
return params.colorPalette[index % params.colorPalette.length];
}
// Mapping and easing
function mapRange(value, inMin, inMax, outMin, outMax) {
return outMin + (outMax - outMin) * ((value - inMin) / (inMax - inMin));
}
function easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}
// Constrain to bounds
function wrapAround(value, max) {
if (value < 0) return max;
if (value > max) return 0;
return value;
}
// ============================================================================
// 7. PARAMETER UPDATES (Connect to UI)
// ============================================================================
function updateParameter(paramName, value) {
params[paramName] = value;
// Decide if you need to regenerate or just update
// Some params can update in real-time, others need full regeneration
}
function regenerate() {
// Reinitialize your generative system
// Useful when parameters change significantly
initializeSeed(params.seed);
// Then regenerate your system
}
// ============================================================================
// 8. COMMON P5.JS PATTERNS
// ============================================================================
// Drawing with transparency for trails/fading
function fadeBackground(opacity) {
fill(250, 249, 245, opacity); // Anthropic light with alpha
noStroke();
rect(0, 0, width, height);
}
// Using noise for organic variation
function getNoiseValue(x, y, scale = 0.01) {
return noise(x * scale, y * scale);
}
// Creating vectors from angles
function vectorFromAngle(angle, magnitude = 1) {
return createVector(cos(angle), sin(angle)).mult(magnitude);
}
// ============================================================================
// 9. EXPORT FUNCTIONS
// ============================================================================
function exportImage() {
saveCanvas('generative-art-' + params.seed, 'png');
}
// ============================================================================
// REMEMBER
// ============================================================================
//
// These are TOOLS and PRINCIPLES, not a recipe.
// Your algorithmic philosophy should guide WHAT you create.
// This structure helps you create it WELL.
//
// Focus on:
// - Clean, readable code
// - Parameterized for exploration
// - Seeded for reproducibility
// - Performant execution
//
// The art itself is entirely up to you!
//
// ============================================================================
@@ -0,0 +1,599 @@
<!DOCTYPE html>
<!--
THIS IS A TEMPLATE THAT SHOULD BE USED EVERY TIME AND MODIFIED.
WHAT TO KEEP:
✓ Overall structure (header, sidebar, main content)
✓ Anthropic branding (colors, fonts, layout)
✓ Seed navigation section (always include this)
✓ Self-contained artifact (everything inline)
WHAT TO CREATIVELY EDIT:
✗ The p5.js algorithm (implement YOUR vision)
✗ The parameters (define what YOUR art needs)
✗ The UI controls (match YOUR parameters)
Let your philosophy guide the implementation.
The world is your oyster - be creative!
-->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generative Art Viewer</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&family=Lora:wght@400;500&display=swap" rel="stylesheet">
<style>
/* Anthropic Brand Colors */
:root {
--anthropic-dark: #141413;
--anthropic-light: #faf9f5;
--anthropic-mid-gray: #b0aea5;
--anthropic-light-gray: #e8e6dc;
--anthropic-orange: #d97757;
--anthropic-blue: #6a9bcc;
--anthropic-green: #788c5d;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, var(--anthropic-light) 0%, #f5f3ee 100%);
min-height: 100vh;
color: var(--anthropic-dark);
}
.container {
display: flex;
min-height: 100vh;
padding: 20px;
gap: 20px;
}
/* Sidebar */
.sidebar {
width: 320px;
flex-shrink: 0;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
padding: 24px;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(20, 20, 19, 0.1);
overflow-y: auto;
overflow-x: hidden;
}
.sidebar h1 {
font-family: 'Lora', serif;
font-size: 24px;
font-weight: 500;
color: var(--anthropic-dark);
margin-bottom: 8px;
}
.sidebar .subtitle {
color: var(--anthropic-mid-gray);
font-size: 14px;
margin-bottom: 32px;
line-height: 1.4;
}
/* Control Sections */
.control-section {
margin-bottom: 32px;
}
.control-section h3 {
font-size: 16px;
font-weight: 600;
color: var(--anthropic-dark);
margin-bottom: 16px;
display: flex;
align-items: center;
gap: 8px;
}
.control-section h3::before {
content: '•';
color: var(--anthropic-orange);
font-weight: bold;
}
/* Seed Controls */
.seed-input {
width: 100%;
background: var(--anthropic-light);
padding: 12px;
border-radius: 8px;
font-family: 'Courier New', monospace;
font-size: 14px;
margin-bottom: 12px;
border: 1px solid var(--anthropic-light-gray);
text-align: center;
}
.seed-input:focus {
outline: none;
border-color: var(--anthropic-orange);
box-shadow: 0 0 0 2px rgba(217, 119, 87, 0.1);
background: white;
}
.seed-controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
margin-bottom: 8px;
}
.regen-button {
margin-bottom: 0;
}
/* Parameter Controls */
.control-group {
margin-bottom: 20px;
}
.control-group label {
display: block;
font-size: 14px;
font-weight: 500;
color: var(--anthropic-dark);
margin-bottom: 8px;
}
.slider-container {
display: flex;
align-items: center;
gap: 12px;
}
.slider-container input[type="range"] {
flex: 1;
height: 4px;
background: var(--anthropic-light-gray);
border-radius: 2px;
outline: none;
-webkit-appearance: none;
}
.slider-container input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: var(--anthropic-orange);
border-radius: 50%;
cursor: pointer;
transition: all 0.2s ease;
}
.slider-container input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.1);
background: #c86641;
}
.slider-container input[type="range"]::-moz-range-thumb {
width: 16px;
height: 16px;
background: var(--anthropic-orange);
border-radius: 50%;
border: none;
cursor: pointer;
transition: all 0.2s ease;
}
.value-display {
font-family: 'Courier New', monospace;
font-size: 12px;
color: var(--anthropic-mid-gray);
min-width: 60px;
text-align: right;
}
/* Color Pickers */
.color-group {
margin-bottom: 16px;
}
.color-group label {
display: block;
font-size: 12px;
color: var(--anthropic-mid-gray);
margin-bottom: 4px;
}
.color-picker-container {
display: flex;
align-items: center;
gap: 8px;
}
.color-picker-container input[type="color"] {
width: 32px;
height: 32px;
border: none;
border-radius: 6px;
cursor: pointer;
background: none;
padding: 0;
}
.color-value {
font-family: 'Courier New', monospace;
font-size: 12px;
color: var(--anthropic-mid-gray);
}
/* Buttons */
.button {
background: var(--anthropic-orange);
color: white;
border: none;
padding: 10px 16px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
width: 100%;
}
.button:hover {
background: #c86641;
transform: translateY(-1px);
}
.button:active {
transform: translateY(0);
}
.button.secondary {
background: var(--anthropic-blue);
}
.button.secondary:hover {
background: #5a8bb8;
}
.button.tertiary {
background: var(--anthropic-green);
}
.button.tertiary:hover {
background: #6b7b52;
}
.button-row {
display: flex;
gap: 8px;
}
.button-row .button {
flex: 1;
}
/* Canvas Area */
.canvas-area {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
min-width: 0;
}
#canvas-container {
width: 100%;
max-width: 1000px;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 20px 40px rgba(20, 20, 19, 0.1);
background: white;
}
#canvas-container canvas {
display: block;
width: 100% !important;
height: auto !important;
}
/* Loading State */
.loading {
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
color: var(--anthropic-mid-gray);
}
/* Responsive - Stack on mobile */
@media (max-width: 600px) {
.container {
flex-direction: column;
}
.sidebar {
width: 100%;
}
.canvas-area {
padding: 20px;
}
}
</style>
</head>
<body>
<div class="container">
<!-- Control Sidebar -->
<div class="sidebar">
<!-- Headers (CUSTOMIZE THIS FOR YOUR ART) -->
<h1>TITLE - EDIT</h1>
<div class="subtitle">SUBHEADER - EDIT</div>
<!-- Seed Section (ALWAYS KEEP THIS) -->
<div class="control-section">
<h3>Seed</h3>
<input type="number" id="seed-input" class="seed-input" value="12345" onchange="updateSeed()">
<div class="seed-controls">
<button class="button secondary" onclick="previousSeed()">← Prev</button>
<button class="button secondary" onclick="nextSeed()">Next →</button>
</div>
<button class="button tertiary regen-button" onclick="randomSeedAndUpdate()">↻ Random</button>
</div>
<!-- Parameters Section (CUSTOMIZE THIS FOR YOUR ART) -->
<div class="control-section">
<h3>Parameters</h3>
<!-- Particle Count -->
<div class="control-group">
<label>Particle Count</label>
<div class="slider-container">
<input type="range" id="particleCount" min="1000" max="10000" step="500" value="5000" oninput="updateParam('particleCount', this.value)">
<span class="value-display" id="particleCount-value">5000</span>
</div>
</div>
<!-- Flow Speed -->
<div class="control-group">
<label>Flow Speed</label>
<div class="slider-container">
<input type="range" id="flowSpeed" min="0.1" max="2.0" step="0.1" value="0.5" oninput="updateParam('flowSpeed', this.value)">
<span class="value-display" id="flowSpeed-value">0.5</span>
</div>
</div>
<!-- Noise Scale -->
<div class="control-group">
<label>Noise Scale</label>
<div class="slider-container">
<input type="range" id="noiseScale" min="0.001" max="0.02" step="0.001" value="0.005" oninput="updateParam('noiseScale', this.value)">
<span class="value-display" id="noiseScale-value">0.005</span>
</div>
</div>
<!-- Trail Length -->
<div class="control-group">
<label>Trail Length</label>
<div class="slider-container">
<input type="range" id="trailLength" min="2" max="20" step="1" value="8" oninput="updateParam('trailLength', this.value)">
<span class="value-display" id="trailLength-value">8</span>
</div>
</div>
</div>
<!-- Colors Section (OPTIONAL - CUSTOMIZE OR REMOVE) -->
<div class="control-section">
<h3>Colors</h3>
<!-- Color 1 -->
<div class="color-group">
<label>Primary Color</label>
<div class="color-picker-container">
<input type="color" id="color1" value="#d97757" onchange="updateColor('color1', this.value)">
<span class="color-value" id="color1-value">#d97757</span>
</div>
</div>
<!-- Color 2 -->
<div class="color-group">
<label>Secondary Color</label>
<div class="color-picker-container">
<input type="color" id="color2" value="#6a9bcc" onchange="updateColor('color2', this.value)">
<span class="color-value" id="color2-value">#6a9bcc</span>
</div>
</div>
<!-- Color 3 -->
<div class="color-group">
<label>Accent Color</label>
<div class="color-picker-container">
<input type="color" id="color3" value="#788c5d" onchange="updateColor('color3', this.value)">
<span class="color-value" id="color3-value">#788c5d</span>
</div>
</div>
</div>
<!-- Actions Section (ALWAYS KEEP THIS) -->
<div class="control-section">
<h3>Actions</h3>
<div class="button-row">
<button class="button" onclick="resetParameters()">Reset</button>
</div>
</div>
</div>
<!-- Main Canvas Area -->
<div class="canvas-area">
<div id="canvas-container">
<div class="loading">Initializing generative art...</div>
</div>
</div>
</div>
<script>
// ═══════════════════════════════════════════════════════════════════════
// GENERATIVE ART PARAMETERS - CUSTOMIZE FOR YOUR ALGORITHM
// ═══════════════════════════════════════════════════════════════════════
let params = {
seed: 12345,
particleCount: 5000,
flowSpeed: 0.5,
noiseScale: 0.005,
trailLength: 8,
colorPalette: ['#d97757', '#6a9bcc', '#788c5d']
};
let defaultParams = {...params}; // Store defaults for reset
// ═══════════════════════════════════════════════════════════════════════
// P5.JS GENERATIVE ART ALGORITHM - REPLACE WITH YOUR VISION
// ═══════════════════════════════════════════════════════════════════════
let particles = [];
let flowField = [];
let cols, rows;
let scl = 10; // Flow field resolution
function setup() {
let canvas = createCanvas(1200, 1200);
canvas.parent('canvas-container');
initializeSystem();
// Remove loading message
document.querySelector('.loading').style.display = 'none';
}
function initializeSystem() {
// Seed the randomness for reproducibility
randomSeed(params.seed);
noiseSeed(params.seed);
// Clear particles and recreate
particles = [];
// Initialize particles
for (let i = 0; i < params.particleCount; i++) {
particles.push(new Particle());
}
// Calculate flow field dimensions
cols = floor(width / scl);
rows = floor(height / scl);
// Generate flow field
generateFlowField();
// Clear background
background(250, 249, 245); // Anthropic light background
}
function generateFlowField() {
// fill this in
}
function draw() {
// fill this in
}
// ═══════════════════════════════════════════════════════════════════════
// PARTICLE SYSTEM - CUSTOMIZE FOR YOUR ALGORITHM
// ═══════════════════════════════════════════════════════════════════════
class Particle {
constructor() {
// fill this in
}
// fill this in
}
// ═══════════════════════════════════════════════════════════════════════
// UI CONTROL HANDLERS - CUSTOMIZE FOR YOUR PARAMETERS
// ═══════════════════════════════════════════════════════════════════════
function updateParam(paramName, value) {
// fill this in
}
function updateColor(colorId, value) {
// fill this in
}
// ═══════════════════════════════════════════════════════════════════════
// SEED CONTROL FUNCTIONS - ALWAYS KEEP THESE
// ═══════════════════════════════════════════════════════════════════════
function updateSeedDisplay() {
document.getElementById('seed-input').value = params.seed;
}
function updateSeed() {
let input = document.getElementById('seed-input');
let newSeed = parseInt(input.value);
if (newSeed && newSeed > 0) {
params.seed = newSeed;
initializeSystem();
} else {
// Reset to current seed if invalid
updateSeedDisplay();
}
}
function previousSeed() {
params.seed = Math.max(1, params.seed - 1);
updateSeedDisplay();
initializeSystem();
}
function nextSeed() {
params.seed = params.seed + 1;
updateSeedDisplay();
initializeSystem();
}
function randomSeedAndUpdate() {
params.seed = Math.floor(Math.random() * 999999) + 1;
updateSeedDisplay();
initializeSystem();
}
function resetParameters() {
params = {...defaultParams};
// Update UI elements
document.getElementById('particleCount').value = params.particleCount;
document.getElementById('particleCount-value').textContent = params.particleCount;
document.getElementById('flowSpeed').value = params.flowSpeed;
document.getElementById('flowSpeed-value').textContent = params.flowSpeed;
document.getElementById('noiseScale').value = params.noiseScale;
document.getElementById('noiseScale-value').textContent = params.noiseScale;
document.getElementById('trailLength').value = params.trailLength;
document.getElementById('trailLength-value').textContent = params.trailLength;
// Reset colors
document.getElementById('color1').value = params.colorPalette[0];
document.getElementById('color1-value').textContent = params.colorPalette[0];
document.getElementById('color2').value = params.colorPalette[1];
document.getElementById('color2-value').textContent = params.colorPalette[1];
document.getElementById('color3').value = params.colorPalette[2];
document.getElementById('color3-value').textContent = params.colorPalette[2];
updateSeedDisplay();
initializeSystem();
}
// Initialize UI on load
window.addEventListener('load', function() {
updateSeedDisplay();
});
</script>
</body>
</html>
@@ -0,0 +1,317 @@
---
name: analytics-tracking
version: 1.0.0
description: When the user wants to set up, improve, or audit analytics tracking and measurement. Also use when the user mentions "set up tracking," "GA4," "Google Analytics," "conversion tracking," "event tracking," "UTM parameters," "tag manager," "GTM," "analytics implementation," or "tracking plan." For A/B test measurement, see ab-test-setup.
---
# Analytics Tracking
You are an expert in analytics implementation and measurement. Your goal is to help set up tracking that provides actionable insights for marketing and product decisions.
## Initial Assessment
**Check for product marketing context first:**
If `.mosaic/product-marketing-context.md` exists, read it before asking questions. Use that context and only ask for information not already covered or specific to this task.
Before implementing tracking, understand:
1. **Business Context** - What decisions will this data inform? What are key conversions?
2. **Current State** - What tracking exists? What tools are in use?
3. **Technical Context** - What's the tech stack? Any privacy/compliance requirements?
---
## Core Principles
### 1. Track for Decisions, Not Data
- Every event should inform a decision
- Avoid vanity metrics
- Quality > quantity of events
### 2. Start with the Questions
- What do you need to know?
- What actions will you take based on this data?
- Work backwards to what you need to track
### 3. Name Things Consistently
- Naming conventions matter
- Establish patterns before implementing
- Document everything
### 4. Maintain Data Quality
- Validate implementation
- Monitor for issues
- Clean data > more data
---
## Tracking Plan Framework
### Structure
```
Event Name | Category | Properties | Trigger | Notes
---------- | -------- | ---------- | ------- | -----
```
### Event Types
| Type | Examples |
| ------------------ | ------------------------------------------------ |
| Pageviews | Automatic, enhanced with metadata |
| User Actions | Button clicks, form submissions, feature usage |
| System Events | Signup completed, purchase, subscription changed |
| Custom Conversions | Goal completions, funnel stages |
**For comprehensive event lists**: See [references/event-library.md](references/event-library.md)
---
## Event Naming Conventions
### Recommended Format: Object-Action
```
signup_completed
button_clicked
form_submitted
article_read
checkout_payment_completed
```
### Best Practices
- Lowercase with underscores
- Be specific: `cta_hero_clicked` vs. `button_clicked`
- Include context in properties, not event name
- Avoid spaces and special characters
- Document decisions
---
## Essential Events
### Marketing Site
| Event | Properties |
| ---------------- | --------------------- |
| cta_clicked | button_text, location |
| form_submitted | form_type |
| signup_completed | method, source |
| demo_requested | - |
### Product/App
| Event | Properties |
| ------------------------- | ---------------------- |
| onboarding_step_completed | step_number, step_name |
| feature_used | feature_name |
| purchase_completed | plan, value |
| subscription_cancelled | reason |
**For full event library by business type**: See [references/event-library.md](references/event-library.md)
---
## Event Properties
### Standard Properties
| Category | Properties |
| -------- | ----------------------------------------- |
| Page | page_title, page_location, page_referrer |
| User | user_id, user_type, account_id, plan_type |
| Campaign | source, medium, campaign, content, term |
| Product | product_id, product_name, category, price |
### Best Practices
- Use consistent property names
- Include relevant context
- Don't duplicate automatic properties
- Avoid PII in properties
---
## GA4 Implementation
### Quick Setup
1. Create GA4 property and data stream
2. Install gtag.js or GTM
3. Enable enhanced measurement
4. Configure custom events
5. Mark conversions in Admin
### Custom Event Example
```javascript
gtag('event', 'signup_completed', {
method: 'email',
plan: 'free',
});
```
**For detailed GA4 implementation**: See [references/ga4-implementation.md](references/ga4-implementation.md)
---
## Google Tag Manager
### Container Structure
| Component | Purpose |
| --------- | --------------------------------------- |
| Tags | Code that executes (GA4, pixels) |
| Triggers | When tags fire (page view, click) |
| Variables | Dynamic values (click text, data layer) |
### Data Layer Pattern
```javascript
dataLayer.push({
event: 'form_submitted',
form_name: 'contact',
form_location: 'footer',
});
```
**For detailed GTM implementation**: See [references/gtm-implementation.md](references/gtm-implementation.md)
---
## UTM Parameter Strategy
### Standard Parameters
| Parameter | Purpose | Example |
| ------------ | ---------------------- | ------------------ |
| utm_source | Traffic source | google, newsletter |
| utm_medium | Marketing medium | cpc, email, social |
| utm_campaign | Campaign name | spring_sale |
| utm_content | Differentiate versions | hero_cta |
| utm_term | Paid search keywords | running+shoes |
### Naming Conventions
- Lowercase everything
- Use underscores or hyphens consistently
- Be specific but concise: `blog_footer_cta`, not `cta1`
- Document all UTMs in a spreadsheet
---
## Debugging and Validation
### Testing Tools
| Tool | Use For |
| ------------------ | ---------------------------------- |
| GA4 DebugView | Real-time event monitoring |
| GTM Preview Mode | Test triggers before publish |
| Browser Extensions | Tag Assistant, dataLayer Inspector |
### Validation Checklist
- [ ] Events firing on correct triggers
- [ ] Property values populating correctly
- [ ] No duplicate events
- [ ] Works across browsers and mobile
- [ ] Conversions recorded correctly
- [ ] No PII leaking
### Common Issues
| Issue | Check |
| ----------------- | ----------------------------------------- |
| Events not firing | Trigger config, GTM loaded |
| Wrong values | Variable path, data layer structure |
| Duplicate events | Multiple containers, trigger firing twice |
---
## Privacy and Compliance
### Considerations
- Cookie consent required in EU/UK/CA
- No PII in analytics properties
- Data retention settings
- User deletion capabilities
### Implementation
- Use consent mode (wait for consent)
- IP anonymization
- Only collect what you need
- Integrate with consent management platform
---
## Output Format
### Tracking Plan Document
```markdown
# [Site/Product] Tracking Plan
## Overview
- Tools: GA4, GTM
- Last updated: [Date]
## Events
| Event Name | Description | Properties | Trigger |
| ---------------- | --------------------- | ------------ | ------------ |
| signup_completed | User completes signup | method, plan | Success page |
## Custom Dimensions
| Name | Scope | Parameter |
| --------- | ----- | --------- |
| user_type | User | user_type |
## Conversions
| Conversion | Event | Counting |
| ---------- | ---------------- | ---------------- |
| Signup | signup_completed | Once per session |
```
---
## Task-Specific Questions
1. What tools are you using (GA4, Mixpanel, etc.)?
2. What key actions do you want to track?
3. What decisions will this data inform?
4. Who implements - dev team or marketing?
5. Are there privacy/consent requirements?
6. What's already tracked?
---
## Tool Integrations
For implementation, see the [tools registry](../../tools/REGISTRY.md). Key analytics tools:
| Tool | Best For | MCP | Guide |
| ------------- | ------------------------------------- | :-: | ----------------------------------------------------- |
| **GA4** | Web analytics, Google ecosystem | ✓ | [ga4.md](../../tools/integrations/ga4.md) |
| **Mixpanel** | Product analytics, event tracking | - | [mixpanel.md](../../tools/integrations/mixpanel.md) |
| **Amplitude** | Product analytics, cohort analysis | - | [amplitude.md](../../tools/integrations/amplitude.md) |
| **PostHog** | Open-source analytics, session replay | - | [posthog.md](../../tools/integrations/posthog.md) |
| **Segment** | Customer data platform, routing | - | [segment.md](../../tools/integrations/segment.md) |
---
## Related Skills
- **ab-test-setup**: For experiment tracking
- **seo-audit**: For organic traffic analysis
- **page-cro**: For conversion optimization (uses this data)
@@ -0,0 +1,259 @@
# Event Library Reference
Comprehensive list of events to track by business type and context.
## Marketing Site Events
### Navigation & Engagement
| Event Name | Description | Properties |
| --------------------- | -------------------------- | ---------------------------------------- |
| page_view | Page loaded (enhanced) | page_title, page_location, content_group |
| scroll_depth | User scrolled to threshold | depth (25, 50, 75, 100) |
| outbound_link_clicked | Click to external site | link_url, link_text |
| internal_link_clicked | Click within site | link_url, link_text, location |
| video_played | Video started | video_id, video_title, duration |
| video_completed | Video finished | video_id, video_title, duration |
### CTA & Form Interactions
| Event Name | Description | Properties |
| -------------------- | ---------------------- | ------------------------------- |
| cta_clicked | Call to action clicked | button_text, cta_location, page |
| form_started | User began form | form_name, form_location |
| form_field_completed | Field filled | form_name, field_name |
| form_submitted | Form successfully sent | form_name, form_location |
| form_error | Form validation failed | form_name, error_type |
| resource_downloaded | Asset downloaded | resource_name, resource_type |
### Conversion Events
| Event Name | Description | Properties |
| --------------------- | ------------------- | ---------------------- |
| signup_started | Initiated signup | source, page |
| signup_completed | Finished signup | method, plan, source |
| demo_requested | Demo form submitted | company_size, industry |
| contact_submitted | Contact form sent | inquiry_type |
| newsletter_subscribed | Email list signup | source, list_name |
| trial_started | Free trial began | plan, source |
---
## Product/App Events
### Onboarding
| Event Name | Description | Properties |
| -------------------------- | ----------------------- | --------------------------------- |
| signup_completed | Account created | method, referral_source |
| onboarding_started | Began onboarding | - |
| onboarding_step_completed | Step finished | step_number, step_name |
| onboarding_completed | All steps done | steps_completed, time_to_complete |
| onboarding_skipped | User skipped onboarding | step_skipped_at |
| first_key_action_completed | Aha moment reached | action_type |
### Core Usage
| Event Name | Description | Properties |
| ---------------- | --------------------- | ------------------------------ |
| session_started | App session began | session_number |
| feature_used | Feature interaction | feature_name, feature_category |
| action_completed | Core action done | action_type, count |
| content_created | User created content | content_type |
| content_edited | User modified content | content_type |
| content_deleted | User removed content | content_type |
| search_performed | In-app search | query, results_count |
| settings_changed | Settings modified | setting_name, new_value |
| invite_sent | User invited others | invite_type, count |
### Errors & Support
| Event Name | Description | Properties |
| ------------------ | -------------------- | ------------------------------- |
| error_occurred | Error experienced | error_type, error_message, page |
| help_opened | Help accessed | help_type, page |
| support_contacted | Support request made | contact_method, issue_type |
| feedback_submitted | User feedback given | feedback_type, rating |
---
## Monetization Events
### Pricing & Checkout
| Event Name | Description | Properties |
| -------------------- | ------------------- | ------------------------------------- |
| pricing_viewed | Pricing page seen | source |
| plan_selected | Plan chosen | plan_name, billing_cycle |
| checkout_started | Began checkout | plan, value |
| payment_info_entered | Payment submitted | payment_method |
| purchase_completed | Purchase successful | plan, value, currency, transaction_id |
| purchase_failed | Purchase failed | error_reason, plan |
### Subscription Management
| Event Name | Description | Properties |
| ----------------------- | ---------------------- | ------------------------- |
| trial_started | Trial began | plan, trial_length |
| trial_ended | Trial expired | plan, converted (bool) |
| subscription_upgraded | Plan upgraded | from_plan, to_plan, value |
| subscription_downgraded | Plan downgraded | from_plan, to_plan |
| subscription_cancelled | Cancelled | plan, reason, tenure |
| subscription_renewed | Renewed | plan, value |
| billing_updated | Payment method changed | - |
---
## E-commerce Events
### Browsing
| Event Name | Description | Properties |
| ------------------- | -------------------- | ----------------------------------------- |
| product_viewed | Product page viewed | product_id, product_name, category, price |
| product_list_viewed | Category/list viewed | list_name, products[] |
| product_searched | Search performed | query, results_count |
| product_filtered | Filters applied | filter_type, filter_value |
| product_sorted | Sort applied | sort_by, sort_order |
### Cart
| Event Name | Description | Properties |
| ------------------------- | ---------------- | ----------------------------------------- |
| product_added_to_cart | Item added | product_id, product_name, price, quantity |
| product_removed_from_cart | Item removed | product_id, product_name, price, quantity |
| cart_viewed | Cart page viewed | cart_value, items_count |
### Checkout
| Event Name | Description | Properties |
| ----------------------- | --------------- | ---------------------------------------- |
| checkout_started | Checkout began | cart_value, items_count |
| checkout_step_completed | Step finished | step_number, step_name |
| shipping_info_entered | Address entered | shipping_method |
| payment_info_entered | Payment entered | payment_method |
| coupon_applied | Coupon used | coupon_code, discount_value |
| purchase_completed | Order placed | transaction_id, value, currency, items[] |
### Post-Purchase
| Event Name | Description | Properties |
| ---------------- | ------------------- | ---------------------- |
| order_confirmed | Confirmation viewed | transaction_id |
| refund_requested | Refund initiated | transaction_id, reason |
| refund_completed | Refund processed | transaction_id, value |
| review_submitted | Product reviewed | product_id, rating |
---
## B2B / SaaS Specific Events
### Team & Collaboration
| Event Name | Description | Properties |
| ------------------- | ------------------- | --------------------------- |
| team_created | New team/org made | team_size, plan |
| team_member_invited | Invite sent | role, invite_method |
| team_member_joined | Member accepted | role |
| team_member_removed | Member removed | role |
| role_changed | Permissions updated | user_id, old_role, new_role |
### Integration Events
| Event Name | Description | Properties |
| ------------------------ | ---------------------- | ------------------------ |
| integration_viewed | Integration page seen | integration_name |
| integration_started | Setup began | integration_name |
| integration_connected | Successfully connected | integration_name |
| integration_disconnected | Removed integration | integration_name, reason |
### Account Events
| Event Name | Description | Properties |
| ------------------- | ----------------- | ------------------------- |
| account_created | New account | source, plan |
| account_upgraded | Plan upgrade | from_plan, to_plan |
| account_churned | Account closed | reason, tenure, mrr_lost |
| account_reactivated | Returned customer | previous_tenure, new_plan |
---
## Event Properties (Parameters)
### Standard Properties to Include
**User Context:**
```
user_id: "12345"
user_type: "free" | "trial" | "paid"
account_id: "acct_123"
plan_type: "starter" | "pro" | "enterprise"
```
**Session Context:**
```
session_id: "sess_abc"
session_number: 5
page: "/pricing"
referrer: "https://google.com"
```
**Campaign Context:**
```
source: "google"
medium: "cpc"
campaign: "spring_sale"
content: "hero_cta"
```
**Product Context (E-commerce):**
```
product_id: "SKU123"
product_name: "Product Name"
category: "Category"
price: 99.99
quantity: 1
currency: "USD"
```
**Timing:**
```
timestamp: "2024-01-15T10:30:00Z"
time_on_page: 45
session_duration: 300
```
---
## Funnel Event Sequences
### Signup Funnel
1. signup_started
2. signup_step_completed (email)
3. signup_step_completed (password)
4. signup_completed
5. onboarding_started
### Purchase Funnel
1. pricing_viewed
2. plan_selected
3. checkout_started
4. payment_info_entered
5. purchase_completed
### E-commerce Funnel
1. product_viewed
2. product_added_to_cart
3. cart_viewed
4. checkout_started
5. shipping_info_entered
6. payment_info_entered
7. purchase_completed
@@ -0,0 +1,309 @@
# GA4 Implementation Reference
Detailed implementation guide for Google Analytics 4.
## Configuration
### Data Streams
- One stream per platform (web, iOS, Android)
- Enable enhanced measurement for automatic tracking
- Configure data retention (2 months default, 14 months max)
- Enable Google Signals (for cross-device, if consented)
### Enhanced Measurement Events (Automatic)
| Event | Description | Configuration |
| ---------------- | ------------------------ | ----------------------- |
| page_view | Page loads | Automatic |
| scroll | 90% scroll depth | Toggle on/off |
| outbound_click | Click to external domain | Automatic |
| site_search | Search query used | Configure parameter |
| video_engagement | YouTube video plays | Toggle on/off |
| file_download | PDF, docs, etc. | Configurable extensions |
### Recommended Events
Use Google's predefined events when possible for enhanced reporting:
**All properties:**
- login, sign_up
- share
- search
**E-commerce:**
- view_item, view_item_list
- add_to_cart, remove_from_cart
- begin_checkout
- add_payment_info
- purchase, refund
**Games:**
- level_up, unlock_achievement
- post_score, spend_virtual_currency
Reference: https://support.google.com/analytics/answer/9267735
---
## Custom Events
### gtag.js Implementation
```javascript
// Basic event
gtag('event', 'signup_completed', {
method: 'email',
plan: 'free',
});
// Event with value
gtag('event', 'purchase', {
transaction_id: 'T12345',
value: 99.99,
currency: 'USD',
items: [
{
item_id: 'SKU123',
item_name: 'Product Name',
price: 99.99,
},
],
});
// User properties
gtag('set', 'user_properties', {
user_type: 'premium',
plan_name: 'pro',
});
// User ID (for logged-in users)
gtag('config', 'GA_MEASUREMENT_ID', {
user_id: 'USER_ID',
});
```
### Google Tag Manager (dataLayer)
```javascript
// Custom event
dataLayer.push({
event: 'signup_completed',
method: 'email',
plan: 'free',
});
// Set user properties
dataLayer.push({
user_id: '12345',
user_type: 'premium',
});
// E-commerce purchase
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'T12345',
value: 99.99,
currency: 'USD',
items: [
{
item_id: 'SKU123',
item_name: 'Product Name',
price: 99.99,
quantity: 1,
},
],
},
});
// Clear ecommerce before sending (best practice)
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'view_item',
ecommerce: {
// ...
},
});
```
---
## Conversions Setup
### Creating Conversions
1. **Collect the event** - Ensure event is firing in GA4
2. **Mark as conversion** - Admin > Events > Mark as conversion
3. **Set counting method**:
- Once per session (leads, signups)
- Every event (purchases)
4. **Import to Google Ads** - For conversion-optimized bidding
### Conversion Values
```javascript
// Event with conversion value
gtag('event', 'purchase', {
value: 99.99,
currency: 'USD',
});
```
Or set default value in GA4 Admin when marking conversion.
---
## Custom Dimensions and Metrics
### When to Use
**Custom dimensions:**
- Properties you want to segment/filter by
- User attributes (plan type, industry)
- Content attributes (author, category)
**Custom metrics:**
- Numeric values to aggregate
- Scores, counts, durations
### Setup Steps
1. Admin > Data display > Custom definitions
2. Create dimension or metric
3. Choose scope:
- **Event**: Per event (content_type)
- **User**: Per user (account_type)
- **Item**: Per product (product_category)
4. Enter parameter name (must match event parameter)
### Examples
| Dimension | Scope | Parameter | Description |
| ---------------- | ----- | ------------- | ------------------- |
| User Type | User | user_type | Free, trial, paid |
| Content Author | Event | author | Blog post author |
| Product Category | Item | item_category | E-commerce category |
---
## Audiences
### Creating Audiences
Admin > Data display > Audiences
**Use cases:**
- Remarketing audiences (export to Ads)
- Segment analysis
- Trigger-based events
### Audience Examples
**High-intent visitors:**
- Viewed pricing page
- Did not convert
- In last 7 days
**Engaged users:**
- 3+ sessions
- Or 5+ minutes total engagement
**Purchasers:**
- Purchase event
- For exclusion or lookalike
---
## Debugging
### DebugView
Enable with:
- URL parameter: `?debug_mode=true`
- Chrome extension: GA Debugger
- gtag: `'debug_mode': true` in config
View at: Reports > Configure > DebugView
### Real-Time Reports
Check events within 30 minutes:
Reports > Real-time
### Common Issues
**Events not appearing:**
- Check DebugView first
- Verify gtag/GTM firing
- Check filter exclusions
**Parameter values missing:**
- Custom dimension not created
- Parameter name mismatch
- Data still processing (24-48 hrs)
**Conversions not recording:**
- Event not marked as conversion
- Event name doesn't match
- Counting method (once vs. every)
---
## Data Quality
### Filters
Admin > Data streams > [Stream] > Configure tag settings > Define internal traffic
**Exclude:**
- Internal IP addresses
- Developer traffic
- Testing environments
### Cross-Domain Tracking
For multiple domains sharing analytics:
1. Admin > Data streams > [Stream] > Configure tag settings
2. Configure your domains
3. List all domains that should share sessions
### Session Settings
Admin > Data streams > [Stream] > Configure tag settings
- Session timeout (default 30 min)
- Engaged session duration (10 sec default)
---
## Integration with Google Ads
### Linking
1. Admin > Product links > Google Ads links
2. Enable auto-tagging in Google Ads
3. Import conversions in Google Ads
### Audience Export
Audiences created in GA4 can be used in Google Ads for:
- Remarketing campaigns
- Customer match
- Similar audiences
@@ -0,0 +1,410 @@
# Google Tag Manager Implementation Reference
Detailed guide for implementing tracking via Google Tag Manager.
## Container Structure
### Tags
Tags are code snippets that execute when triggered.
**Common tag types:**
- GA4 Configuration (base setup)
- GA4 Event (custom events)
- Google Ads Conversion
- Facebook Pixel
- LinkedIn Insight Tag
- Custom HTML (for other pixels)
### Triggers
Triggers define when tags fire.
**Built-in triggers:**
- Page View: All Pages, DOM Ready, Window Loaded
- Click: All Elements, Just Links
- Form Submission
- Scroll Depth
- Timer
- Element Visibility
**Custom triggers:**
- Custom Event (from dataLayer)
- Trigger Groups (multiple conditions)
### Variables
Variables capture dynamic values.
**Built-in (enable as needed):**
- Click Text, Click URL, Click ID, Click Classes
- Page Path, Page URL, Page Hostname
- Referrer
- Form Element, Form ID
**User-defined:**
- Data Layer variables
- JavaScript variables
- Lookup tables
- RegEx tables
- Constants
---
## Naming Conventions
### Recommended Format
```
[Type] - [Description] - [Detail]
Tags:
GA4 - Event - Signup Completed
GA4 - Config - Base Configuration
FB - Pixel - Page View
HTML - LiveChat Widget
Triggers:
Click - CTA Button
Submit - Contact Form
View - Pricing Page
Custom - signup_completed
Variables:
DL - user_id
JS - Current Timestamp
LT - Campaign Source Map
```
---
## Data Layer Patterns
### Basic Structure
```javascript
// Initialize (in <head> before GTM)
window.dataLayer = window.dataLayer || [];
// Push event
dataLayer.push({
event: 'event_name',
property1: 'value1',
property2: 'value2',
});
```
### Page Load Data
```javascript
// Set on page load (before GTM container)
window.dataLayer = window.dataLayer || [];
dataLayer.push({
pageType: 'product',
contentGroup: 'products',
user: {
loggedIn: true,
userId: '12345',
userType: 'premium',
},
});
```
### Form Submission
```javascript
document.querySelector('#contact-form').addEventListener('submit', function () {
dataLayer.push({
event: 'form_submitted',
formName: 'contact',
formLocation: 'footer',
});
});
```
### Button Click
```javascript
document.querySelector('.cta-button').addEventListener('click', function () {
dataLayer.push({
event: 'cta_clicked',
ctaText: this.innerText,
ctaLocation: 'hero',
});
});
```
### E-commerce Events
```javascript
// Product view
dataLayer.push({ ecommerce: null }); // Clear previous
dataLayer.push({
event: 'view_item',
ecommerce: {
items: [
{
item_id: 'SKU123',
item_name: 'Product Name',
price: 99.99,
item_category: 'Category',
quantity: 1,
},
],
},
});
// Add to cart
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
items: [
{
item_id: 'SKU123',
item_name: 'Product Name',
price: 99.99,
quantity: 1,
},
],
},
});
// Purchase
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'T12345',
value: 99.99,
currency: 'USD',
tax: 5.0,
shipping: 10.0,
items: [
{
item_id: 'SKU123',
item_name: 'Product Name',
price: 99.99,
quantity: 1,
},
],
},
});
```
---
## Common Tag Configurations
### GA4 Configuration Tag
**Tag Type:** Google Analytics: GA4 Configuration
**Settings:**
- Measurement ID: G-XXXXXXXX
- Send page view: Checked (for pageviews)
- User Properties: Add any user-level dimensions
**Trigger:** All Pages
### GA4 Event Tag
**Tag Type:** Google Analytics: GA4 Event
**Settings:**
- Configuration Tag: Select your config tag
- Event Name: {{DL - event_name}} or hardcode
- Event Parameters: Add parameters from dataLayer
**Trigger:** Custom Event with event name match
### Facebook Pixel - Base
**Tag Type:** Custom HTML
```html
<script>
!(function (f, b, e, v, n, t, s) {
if (f.fbq) return;
n = f.fbq = function () {
n.callMethod ? n.callMethod.apply(n, arguments) : n.queue.push(arguments);
};
if (!f._fbq) f._fbq = n;
n.push = n;
n.loaded = !0;
n.version = '2.0';
n.queue = [];
t = b.createElement(e);
t.async = !0;
t.src = v;
s = b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t, s);
})(window, document, 'script', 'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
```
**Trigger:** All Pages
### Facebook Pixel - Event
**Tag Type:** Custom HTML
```html
<script>
fbq('track', 'Lead', {
content_name: '{{DL - form_name}}',
});
</script>
```
**Trigger:** Custom Event - form_submitted
---
## Preview and Debug
### Preview Mode
1. Click "Preview" in GTM
2. Enter site URL
3. GTM debug panel opens at bottom
**What to check:**
- Tags fired on this event
- Tags not fired (and why)
- Variables and their values
- Data layer contents
### Debug Tips
**Tag not firing:**
- Check trigger conditions
- Verify data layer push
- Check tag sequencing
**Wrong variable value:**
- Check data layer structure
- Verify variable path (nested objects)
- Check timing (data may not exist yet)
**Multiple firings:**
- Check trigger uniqueness
- Look for duplicate tags
- Check tag firing options
---
## Workspaces and Versioning
### Workspaces
Use workspaces for team collaboration:
- Default workspace for production
- Separate workspaces for large changes
- Merge when ready
### Version Management
**Best practices:**
- Name every version descriptively
- Add notes explaining changes
- Review changes before publish
- Keep production version noted
**Version notes example:**
```
v15: Added purchase conversion tracking
- New tag: GA4 - Event - Purchase
- New trigger: Custom Event - purchase
- New variables: DL - transaction_id, DL - value
- Tested: Chrome, Safari, Mobile
```
---
## Consent Management
### Consent Mode Integration
```javascript
// Default state (before consent)
gtag('consent', 'default', {
analytics_storage: 'denied',
ad_storage: 'denied',
});
// Update on consent
function grantConsent() {
gtag('consent', 'update', {
analytics_storage: 'granted',
ad_storage: 'granted',
});
}
```
### GTM Consent Overview
1. Enable Consent Overview in Admin
2. Configure consent for each tag
3. Tags respect consent state automatically
---
## Advanced Patterns
### Tag Sequencing
**Setup tags to fire in order:**
Tag Configuration > Advanced Settings > Tag Sequencing
**Use cases:**
- Config tag before event tags
- Pixel initialization before tracking
- Cleanup after conversion
### Exception Handling
**Trigger exceptions** - Prevent tag from firing:
- Exclude certain pages
- Exclude internal traffic
- Exclude during testing
### Custom JavaScript Variables
```javascript
// Get URL parameter
function() {
var params = new URLSearchParams(window.location.search);
return params.get('campaign') || '(not set)';
}
// Get cookie value
function() {
var match = document.cookie.match('(^|;) ?user_id=([^;]*)(;|$)');
return match ? match[2] : null;
}
// Get data from page
function() {
var el = document.querySelector('.product-price');
return el ? parseFloat(el.textContent.replace('$', '')) : 0;
}
```
@@ -0,0 +1,129 @@
---
name: antfu
description: Anthony Fu's opinionated tooling and conventions for JavaScript/TypeScript projects. Use when setting up new projects, configuring ESLint/Prettier alternatives, monorepos, library publishing, or when the user mentions Anthony Fu's preferences.
metadata:
author: Anthony Fu
version: '2026.02.03'
---
## Coding Practices
### Code Organization
- **Single responsibility**: Each source file should have a clear, focused scope/purpose
- **Split large files**: Break files when they become large or handle too many concerns
- **Type separation**: Always separate types and interfaces into `types.ts` or `types/*.ts`
- **Constants extraction**: Move constants to a dedicated `constants.ts` file
### Runtime Environment
- **Prefer isomorphic code**: Write runtime-agnostic code that works in Node, browser, and workers whenever possible
- **Clear runtime indicators**: When code is environment-specific, add a comment at the top of the file:
```ts
// @env node
// @env browser
```
### TypeScript
- **Explicit return types**: Declare return types explicitly when possible
- **Avoid complex inline types**: Extract complex types into dedicated `type` or `interface` declarations
### Comments
- **Avoid unnecessary comments**: Code should be self-explanatory
- **Explain "why" not "how"**: Comments should describe the reasoning or intent, not what the code does
### Testing (Vitest)
- Test files: `foo.ts``foo.test.ts` (same directory)
- Use `describe`/`it` API (not `test`)
- Use `toMatchSnapshot` for complex outputs
- Use `toMatchFileSnapshot` with explicit path for language-specific snapshots
---
## Tooling Choices
### @antfu/ni Commands
| Command | Description |
| -------------------------- | ------------------------------------------ |
| `ni` | Install dependencies |
| `ni <pkg>` / `ni -D <pkg>` | Add dependency / dev dependency |
| `nr <script>` | Run script |
| `nu` | Upgrade dependencies |
| `nun <pkg>` | Uninstall dependency |
| `nci` | Clean install (`pnpm i --frozen-lockfile`) |
| `nlx <pkg>` | Execute package (`npx`) |
### TypeScript Config
```json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true
}
}
```
### ESLint Setup
```js
// eslint.config.mjs
import antfu from '@antfu/eslint-config';
export default antfu();
```
When completing tasks, run `pnpm run lint --fix` to format the code and fix coding style.
For detailed configuration options: [antfu-eslint-config](references/antfu-eslint-config.md)
### Git Hooks
```json
{
"simple-git-hooks": {
"pre-commit": "pnpm i --frozen-lockfile --ignore-scripts --offline && npx lint-staged"
},
"lint-staged": { "*": "eslint --fix" },
"scripts": {
"prepare": "npx simple-git-hooks"
}
}
```
### pnpm Catalogs
Use named catalogs in `pnpm-workspace.yaml` for version management:
| Catalog | Purpose |
| ---------- | ------------------------------------ |
| `prod` | Production dependencies |
| `inlined` | Bundler-inlined dependencies |
| `dev` | Dev tools (linter, bundler, testing) |
| `frontend` | Frontend libraries |
Avoid the default catalog. Catalog names can be adjusted per project needs.
---
## References
| Topic | Description | Reference |
| ------------------- | --------------------------------------------------------------- | -------------------------------------------------------- |
| ESLint Config | Framework support, formatters, rule overrides, VS Code settings | [antfu-eslint-config](references/antfu-eslint-config.md) |
| Project Setup | .gitignore, GitHub Actions, VS Code extensions | [setting-up](references/setting-up.md) |
| App Development | Vue/Nuxt/UnoCSS conventions and patterns | [app-development](references/app-development.md) |
| Library Development | tsdown bundling, pure ESM publishing | [library-development](references/library-development.md) |
| Monorepo | pnpm workspaces, centralized alias, Turborepo | [monorepo](references/monorepo.md) |
@@ -0,0 +1,301 @@
---
name: antfu-eslint-config
description: Configuring @antfu/eslint-config for framework support, formatters, and rule overrides. Use when adding React/Vue/Svelte/Astro support, customizing rules, or setting up VS Code integration.
---
# @antfu/eslint-config
Handles both linting and formatting (no Prettier needed). Auto-detects TypeScript and Vue.
**Style**: Single quotes, no semicolons, sorted imports, dangling commas.
## Configuration Options
```js
import antfu from '@antfu/eslint-config';
export default antfu({
// Project type: 'lib' for libraries, 'app' (default) for applications
type: 'lib',
// Global ignores (extends defaults, doesn't override)
ignores: ['**/fixtures', '**/dist'],
// Stylistic options
stylistic: {
indent: 2, // 2, 4, or 'tab'
quotes: 'single', // or 'double'
},
// Framework support (auto-detected, but can be explicit)
typescript: true,
vue: true,
// Disable specific language support
jsonc: false,
yaml: false,
});
```
## Framework Support
### Vue
Vue accessibility:
```js
export default antfu({
vue: {
a11y: true,
},
});
// Requires: pnpm add -D eslint-plugin-vuejs-accessibility
```
### React
```js
export default antfu({
react: true,
});
// Requires: pnpm add -D @eslint-react/eslint-plugin eslint-plugin-react-hooks eslint-plugin-react-refresh
```
### Next.js
```js
export default antfu({
nextjs: true,
});
// Requires: pnpm add -D @next/eslint-plugin-next
```
### Svelte
```js
export default antfu({
svelte: true,
});
// Requires: pnpm add -D eslint-plugin-svelte
```
### Astro
```js
export default antfu({
astro: true,
});
// Requires: pnpm add -D eslint-plugin-astro
```
### Solid
```js
export default antfu({
solid: true,
});
// Requires: pnpm add -D eslint-plugin-solid
```
### UnoCSS
```js
export default antfu({
unocss: true,
});
// Requires: pnpm add -D @unocss/eslint-plugin
```
## Formatters (CSS, HTML, Markdown)
For files ESLint doesn't handle natively:
```js
export default antfu({
formatters: {
css: true, // Format CSS, LESS, SCSS (uses Prettier)
html: true, // Format HTML (uses Prettier)
markdown: 'prettier', // or 'dprint'
},
});
// Requires: pnpm add -D eslint-plugin-format
```
## Rule Overrides
### Global overrides
```js
export default antfu(
{
// First argument: antfu config options
},
// Additional arguments: ESLint flat configs
{
rules: {
'style/semi': ['error', 'never'],
},
},
);
```
### Per-integration overrides
```js
export default antfu({
vue: {
overrides: {
'vue/operator-linebreak': ['error', 'before'],
},
},
typescript: {
overrides: {
'ts/consistent-type-definitions': ['error', 'interface'],
},
},
});
```
### File-specific overrides
```js
export default antfu(
{ vue: true, typescript: true },
{
files: ['**/*.vue'],
rules: {
'vue/operator-linebreak': ['error', 'before'],
},
},
);
```
## Plugin Prefix Renaming
The config renames plugin prefixes for consistency:
| New Prefix | Original |
| ---------- | ---------------------- |
| `ts/*` | `@typescript-eslint/*` |
| `style/*` | `@stylistic/*` |
| `import/*` | `import-lite/*` |
| `node/*` | `n/*` |
| `yaml/*` | `yml/*` |
| `test/*` | `vitest/*` |
| `next/*` | `@next/next` |
Use the new prefix when overriding or disabling rules:
```ts
// eslint-disable-next-line ts/consistent-type-definitions
type Foo = { bar: 2 };
```
## Type-Aware Rules
Enable TypeScript type checking:
```js
export default antfu({
typescript: {
tsconfigPath: 'tsconfig.json',
},
});
```
## Config Composer API
Chain methods for flexible composition:
```js
export default antfu()
.prepend(/* configs before main */)
.override('antfu/stylistic/rules', {
rules: {
'style/generator-star-spacing': ['error', { after: true, before: false }],
},
})
.renamePlugins({
'old-prefix': 'new-prefix',
});
```
## Less Opinionated Mode
Disable Anthony's most opinionated rules:
```js
export default antfu({
lessOpinionated: true,
});
```
## Lint-Staged Setup
```json
{
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
},
"lint-staged": {
"*": "eslint --fix"
}
}
```
```bash
pnpm add -D lint-staged simple-git-hooks
npx simple-git-hooks
```
## VS Code Settings
Add to `.vscode/settings.json`:
```jsonc
{
"prettier.enable": false,
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "never",
},
"eslint.rules.customizations": [
{ "rule": "style/*", "severity": "off", "fixable": true },
{ "rule": "format/*", "severity": "off", "fixable": true },
{ "rule": "*-indent", "severity": "off", "fixable": true },
{ "rule": "*-spacing", "severity": "off", "fixable": true },
{ "rule": "*-spaces", "severity": "off", "fixable": true },
{ "rule": "*-order", "severity": "off", "fixable": true },
{ "rule": "*-dangle", "severity": "off", "fixable": true },
{ "rule": "*-newline", "severity": "off", "fixable": true },
{ "rule": "*quotes", "severity": "off", "fixable": true },
{ "rule": "*semi", "severity": "off", "fixable": true },
],
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"html",
"markdown",
"json",
"jsonc",
"yaml",
"toml",
"xml",
"astro",
"svelte",
"css",
"less",
"scss",
],
}
```
<!--
Source references:
- https://github.com/antfu/eslint-config
- https://raw.githubusercontent.com/antfu/eslint-config/refs/heads/main/README.md
-->
@@ -0,0 +1,45 @@
---
name: app-development
description: Vue/Nuxt/UnoCSS application conventions. Use when building web apps, choosing between Vite and Nuxt, or writing Vue components.
---
# App Development
## Framework Selection
| Use Case | Choice |
| ------------------------------------------------------ | ---------- |
| SPA, client-only, library playgrounds | Vite + Vue |
| SSR, SSG, SEO-critical, file-based routing, API routes | Nuxt |
## Vue Conventions
| Convention | Preference |
| ------------- | ---------------------------------- |
| Script syntax | Always `<script setup lang="ts">` |
| State | Prefer `shallowRef()` over `ref()` |
| Objects | Use `ref()`, avoid `reactive()` |
| Styling | UnoCSS |
| Utilities | VueUse |
### Props and Emits
```vue
<script setup lang="ts">
interface Props {
title: string;
count?: number;
}
interface Emits {
(e: 'update', value: number): void;
(e: 'close'): void;
}
const props = withDefaults(defineProps<Props>(), {
count: 0,
});
const emit = defineEmits<Emits>();
</script>
```
@@ -0,0 +1,76 @@
---
name: library-development
description: Building and publishing TypeScript libraries with tsdown. Use when creating npm packages, configuring library bundling, or setting up package.json exports.
---
# Library Development
| Aspect | Choice |
| ------- | ------------------------- |
| Bundler | tsdown |
| Output | Pure ESM only (no CJS) |
| DTS | Generated via tsdown |
| Exports | Auto-generated via tsdown |
## tsdown Configuration
Use tsdown with these options enabled:
```ts
// tsdown.config.ts
import { defineConfig } from 'tsdown';
export default defineConfig({
entry: ['src/index.ts'],
format: ['esm'],
dts: true,
exports: true,
});
```
| Option | Value | Purpose |
| --------- | --------- | --------------------------------------------- |
| `format` | `['esm']` | Pure ESM, no CommonJS |
| `dts` | `true` | Generate `.d.ts` files |
| `exports` | `true` | Auto-update `exports` field in `package.json` |
### Multiple Entry Points
```ts
export default defineConfig({
entry: ['src/index.ts', 'src/utils.ts'],
format: ['esm'],
dts: true,
exports: true,
});
```
The `exports: true` option auto-generates the `exports` field in `package.json` when running `tsdown`.
---
## package.json
Required fields for pure ESM library:
```json
{
"type": "module",
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.mts",
"files": ["dist"],
"scripts": {
"build": "tsdown",
"prepack": "pnpm build",
"test": "vitest",
"release": "bumpp -r"
}
}
```
The `exports` field is managed by tsdown when `exports: true`.
### prepack Script
For each public package, add `"prepack": "pnpm build"` to `scripts`. This ensures the package is automatically built before publishing (e.g., when running `npm publish` or `pnpm publish`). This prevents accidentally publishing stale or missing build artifacts.
@@ -0,0 +1,120 @@
---
name: monorepo
description: Monorepo setup with pnpm workspaces, centralized aliases, and Turborepo. Use when creating or managing multi-package repositories.
---
# Monorepo Setup
## pnpm Workspaces
Use pnpm workspaces for monorepo management:
```yaml
# pnpm-workspace.yaml
packages:
- 'packages/*'
```
## Scripts Convention
Have scripts in each package, and use `-r` (recursive) flag at root,
Enable ESLint cache for faster linting in monorepos.
```json
// root package.json
{
"scripts": {
"build": "pnpm run -r build",
"test": "vitest",
"lint": "eslint . --cache --concurrency=auto"
}
}
```
In each package's `package.json`, add the scripts.
```json
// packages/*/package.json
{
"scripts": {
"build": "tsdown",
"prepack": "pnpm build"
}
}
```
## ESLint Cache
```json
{
"scripts": {
"lint": "eslint . --cache --concurrency=auto"
}
}
```
## Turborepo (Optional)
For monorepos with many packages or long build times, use Turborepo for task orchestration and caching.
See the dedicated Turborepo skill for detailed configuration.
## Centralized Alias
For better DX across Vite, Nuxt, Vitest configs, create a centralized `alias.ts` at project root:
```ts
// alias.ts
import fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { join, relative } from 'pathe';
const root = fileURLToPath(new URL('.', import.meta.url));
const r = (path: string) => fileURLToPath(new URL(`./packages/${path}`, import.meta.url));
export const alias = {
'@myorg/core': r('core/src/index.ts'),
'@myorg/utils': r('utils/src/index.ts'),
'@myorg/ui': r('ui/src/index.ts'),
// Add more aliases as needed
};
// Auto-update tsconfig.alias.json paths
const raw = fs.readFileSync(join(root, 'tsconfig.alias.json'), 'utf-8').trim();
const tsconfig = JSON.parse(raw);
tsconfig.compilerOptions.paths = Object.fromEntries(
Object.entries(alias).map(([key, value]) => [key, [`./${relative(root, value)}`]]),
);
const newRaw = JSON.stringify(tsconfig, null, 2);
if (newRaw !== raw) fs.writeFileSync(join(root, 'tsconfig.alias.json'), `${newRaw}\n`, 'utf-8');
```
Then update the `tsconfig.json` to use the alias file:
```json
{
"extends": ["./tsconfig.alias.json"]
}
```
### Using Alias in Configs
Reference the centralized alias in all config files:
```ts
// vite.config.ts
import { alias } from './alias';
export default defineConfig({
resolve: { alias },
});
```
```ts
// nuxt.config.ts
import { alias } from './alias';
export default defineNuxtConfig({
alias,
});
```
@@ -0,0 +1,119 @@
---
name: setting-up
description: Project setup files including .gitignore, GitHub Actions workflows, and VS Code extensions. Use when initializing new projects or adding CI/editor config.
---
# Project Setup
## .gitignore
Create when `.gitignore` is not present:
```
*.log
*.tgz
.cache
.DS_Store
.eslintcache
.idea
.env
.nuxt
.temp
.output
.turbo
cache
coverage
dist
lib-cov
logs
node_modules
temp
```
## GitHub Actions
Add these workflows when setting up a new project. Skip if workflows already exist. All use [sxzz/workflows](https://github.com/sxzz/workflows) reusable workflows.
### Autofix Workflow
**`.github/workflows/autofix.yml`** - Auto-fix linting on PRs:
```yaml
name: autofix.ci
on: [pull_request]
jobs:
autofix:
uses: sxzz/workflows/.github/workflows/autofix.yml@v1
permissions:
contents: read
```
### Unit Test Workflow
**`.github/workflows/unit-test.yml`** - Run tests on push/PR:
```yaml
name: Unit Test
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions: {}
jobs:
unit-test:
uses: sxzz/workflows/.github/workflows/unit-test.yml@v1
```
### Release Workflow
**`.github/workflows/release.yml`** - Publish on tag (library projects only):
```yaml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
uses: sxzz/workflows/.github/workflows/release.yml@v1
with:
publish: true
permissions:
contents: write
id-token: write
```
## VS Code Extensions
Configure in `.vscode/extensions.json`:
```json
{
"recommendations": [
"dbaeumer.vscode-eslint",
"antfu.pnpm-catalog-lens",
"antfu.iconify",
"antfu.unocss",
"antfu.slidev",
"vue.volar"
]
}
```
| Extension | Description |
| ------------------------- | --------------------------------------------- |
| `dbaeumer.vscode-eslint` | ESLint integration for linting and formatting |
| `antfu.pnpm-catalog-lens` | Shows pnpm catalog version hints inline |
| `antfu.iconify` | Iconify icon preview and autocomplete |
| `antfu.unocss` | UnoCSS IntelliSense and syntax highlighting |
| `antfu.slidev` | Slidev preview and syntax highlighting |
| `vue.volar` | Vue Language Features |
@@ -0,0 +1,494 @@
---
name: architecture-patterns
description: Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.
---
# Architecture Patterns
Master proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design to build maintainable, testable, and scalable systems.
## When to Use This Skill
- Designing new backend systems from scratch
- Refactoring monolithic applications for better maintainability
- Establishing architecture standards for your team
- Migrating from tightly coupled to loosely coupled architectures
- Implementing domain-driven design principles
- Creating testable and mockable codebases
- Planning microservices decomposition
## Core Concepts
### 1. Clean Architecture (Uncle Bob)
**Layers (dependency flows inward):**
- **Entities**: Core business models
- **Use Cases**: Application business rules
- **Interface Adapters**: Controllers, presenters, gateways
- **Frameworks & Drivers**: UI, database, external services
**Key Principles:**
- Dependencies point inward
- Inner layers know nothing about outer layers
- Business logic independent of frameworks
- Testable without UI, database, or external services
### 2. Hexagonal Architecture (Ports and Adapters)
**Components:**
- **Domain Core**: Business logic
- **Ports**: Interfaces defining interactions
- **Adapters**: Implementations of ports (database, REST, message queue)
**Benefits:**
- Swap implementations easily (mock for testing)
- Technology-agnostic core
- Clear separation of concerns
### 3. Domain-Driven Design (DDD)
**Strategic Patterns:**
- **Bounded Contexts**: Separate models for different domains
- **Context Mapping**: How contexts relate
- **Ubiquitous Language**: Shared terminology
**Tactical Patterns:**
- **Entities**: Objects with identity
- **Value Objects**: Immutable objects defined by attributes
- **Aggregates**: Consistency boundaries
- **Repositories**: Data access abstraction
- **Domain Events**: Things that happened
## Clean Architecture Pattern
### Directory Structure
```
app/
├── domain/ # Entities & business rules
│ ├── entities/
│ │ ├── user.py
│ │ └── order.py
│ ├── value_objects/
│ │ ├── email.py
│ │ └── money.py
│ └── interfaces/ # Abstract interfaces
│ ├── user_repository.py
│ └── payment_gateway.py
├── use_cases/ # Application business rules
│ ├── create_user.py
│ ├── process_order.py
│ └── send_notification.py
├── adapters/ # Interface implementations
│ ├── repositories/
│ │ ├── postgres_user_repository.py
│ │ └── redis_cache_repository.py
│ ├── controllers/
│ │ └── user_controller.py
│ └── gateways/
│ ├── stripe_payment_gateway.py
│ └── sendgrid_email_gateway.py
└── infrastructure/ # Framework & external concerns
├── database.py
├── config.py
└── logging.py
```
### Implementation Example
```python
# domain/entities/user.py
from dataclasses import dataclass
from datetime import datetime
from typing import Optional
@dataclass
class User:
"""Core user entity - no framework dependencies."""
id: str
email: str
name: str
created_at: datetime
is_active: bool = True
def deactivate(self):
"""Business rule: deactivating user."""
self.is_active = False
def can_place_order(self) -> bool:
"""Business rule: active users can order."""
return self.is_active
# domain/interfaces/user_repository.py
from abc import ABC, abstractmethod
from typing import Optional, List
from domain.entities.user import User
class IUserRepository(ABC):
"""Port: defines contract, no implementation."""
@abstractmethod
async def find_by_id(self, user_id: str) -> Optional[User]:
pass
@abstractmethod
async def find_by_email(self, email: str) -> Optional[User]:
pass
@abstractmethod
async def save(self, user: User) -> User:
pass
@abstractmethod
async def delete(self, user_id: str) -> bool:
pass
# use_cases/create_user.py
from domain.entities.user import User
from domain.interfaces.user_repository import IUserRepository
from dataclasses import dataclass
from datetime import datetime
import uuid
@dataclass
class CreateUserRequest:
email: str
name: str
@dataclass
class CreateUserResponse:
user: User
success: bool
error: Optional[str] = None
class CreateUserUseCase:
"""Use case: orchestrates business logic."""
def __init__(self, user_repository: IUserRepository):
self.user_repository = user_repository
async def execute(self, request: CreateUserRequest) -> CreateUserResponse:
# Business validation
existing = await self.user_repository.find_by_email(request.email)
if existing:
return CreateUserResponse(
user=None,
success=False,
error="Email already exists"
)
# Create entity
user = User(
id=str(uuid.uuid4()),
email=request.email,
name=request.name,
created_at=datetime.now(),
is_active=True
)
# Persist
saved_user = await self.user_repository.save(user)
return CreateUserResponse(
user=saved_user,
success=True
)
# adapters/repositories/postgres_user_repository.py
from domain.interfaces.user_repository import IUserRepository
from domain.entities.user import User
from typing import Optional
import asyncpg
class PostgresUserRepository(IUserRepository):
"""Adapter: PostgreSQL implementation."""
def __init__(self, pool: asyncpg.Pool):
self.pool = pool
async def find_by_id(self, user_id: str) -> Optional[User]:
async with self.pool.acquire() as conn:
row = await conn.fetchrow(
"SELECT * FROM users WHERE id = $1", user_id
)
return self._to_entity(row) if row else None
async def find_by_email(self, email: str) -> Optional[User]:
async with self.pool.acquire() as conn:
row = await conn.fetchrow(
"SELECT * FROM users WHERE email = $1", email
)
return self._to_entity(row) if row else None
async def save(self, user: User) -> User:
async with self.pool.acquire() as conn:
await conn.execute(
"""
INSERT INTO users (id, email, name, created_at, is_active)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (id) DO UPDATE
SET email = $2, name = $3, is_active = $5
""",
user.id, user.email, user.name, user.created_at, user.is_active
)
return user
async def delete(self, user_id: str) -> bool:
async with self.pool.acquire() as conn:
result = await conn.execute(
"DELETE FROM users WHERE id = $1", user_id
)
return result == "DELETE 1"
def _to_entity(self, row) -> User:
"""Map database row to entity."""
return User(
id=row["id"],
email=row["email"],
name=row["name"],
created_at=row["created_at"],
is_active=row["is_active"]
)
# adapters/controllers/user_controller.py
from fastapi import APIRouter, Depends, HTTPException
from use_cases.create_user import CreateUserUseCase, CreateUserRequest
from pydantic import BaseModel
router = APIRouter()
class CreateUserDTO(BaseModel):
email: str
name: str
@router.post("/users")
async def create_user(
dto: CreateUserDTO,
use_case: CreateUserUseCase = Depends(get_create_user_use_case)
):
"""Controller: handles HTTP concerns only."""
request = CreateUserRequest(email=dto.email, name=dto.name)
response = await use_case.execute(request)
if not response.success:
raise HTTPException(status_code=400, detail=response.error)
return {"user": response.user}
```
## Hexagonal Architecture Pattern
```python
# Core domain (hexagon center)
class OrderService:
"""Domain service - no infrastructure dependencies."""
def __init__(
self,
order_repository: OrderRepositoryPort,
payment_gateway: PaymentGatewayPort,
notification_service: NotificationPort
):
self.orders = order_repository
self.payments = payment_gateway
self.notifications = notification_service
async def place_order(self, order: Order) -> OrderResult:
# Business logic
if not order.is_valid():
return OrderResult(success=False, error="Invalid order")
# Use ports (interfaces)
payment = await self.payments.charge(
amount=order.total,
customer=order.customer_id
)
if not payment.success:
return OrderResult(success=False, error="Payment failed")
order.mark_as_paid()
saved_order = await self.orders.save(order)
await self.notifications.send(
to=order.customer_email,
subject="Order confirmed",
body=f"Order {order.id} confirmed"
)
return OrderResult(success=True, order=saved_order)
# Ports (interfaces)
class OrderRepositoryPort(ABC):
@abstractmethod
async def save(self, order: Order) -> Order:
pass
class PaymentGatewayPort(ABC):
@abstractmethod
async def charge(self, amount: Money, customer: str) -> PaymentResult:
pass
class NotificationPort(ABC):
@abstractmethod
async def send(self, to: str, subject: str, body: str):
pass
# Adapters (implementations)
class StripePaymentAdapter(PaymentGatewayPort):
"""Primary adapter: connects to Stripe API."""
def __init__(self, api_key: str):
self.stripe = stripe
self.stripe.api_key = api_key
async def charge(self, amount: Money, customer: str) -> PaymentResult:
try:
charge = self.stripe.Charge.create(
amount=amount.cents,
currency=amount.currency,
customer=customer
)
return PaymentResult(success=True, transaction_id=charge.id)
except stripe.error.CardError as e:
return PaymentResult(success=False, error=str(e))
class MockPaymentAdapter(PaymentGatewayPort):
"""Test adapter: no external dependencies."""
async def charge(self, amount: Money, customer: str) -> PaymentResult:
return PaymentResult(success=True, transaction_id="mock-123")
```
## Domain-Driven Design Pattern
```python
# Value Objects (immutable)
from dataclasses import dataclass
from typing import Optional
@dataclass(frozen=True)
class Email:
"""Value object: validated email."""
value: str
def __post_init__(self):
if "@" not in self.value:
raise ValueError("Invalid email")
@dataclass(frozen=True)
class Money:
"""Value object: amount with currency."""
amount: int # cents
currency: str
def add(self, other: "Money") -> "Money":
if self.currency != other.currency:
raise ValueError("Currency mismatch")
return Money(self.amount + other.amount, self.currency)
# Entities (with identity)
class Order:
"""Entity: has identity, mutable state."""
def __init__(self, id: str, customer: Customer):
self.id = id
self.customer = customer
self.items: List[OrderItem] = []
self.status = OrderStatus.PENDING
self._events: List[DomainEvent] = []
def add_item(self, product: Product, quantity: int):
"""Business logic in entity."""
item = OrderItem(product, quantity)
self.items.append(item)
self._events.append(ItemAddedEvent(self.id, item))
def total(self) -> Money:
"""Calculated property."""
return sum(item.subtotal() for item in self.items)
def submit(self):
"""State transition with business rules."""
if not self.items:
raise ValueError("Cannot submit empty order")
if self.status != OrderStatus.PENDING:
raise ValueError("Order already submitted")
self.status = OrderStatus.SUBMITTED
self._events.append(OrderSubmittedEvent(self.id))
# Aggregates (consistency boundary)
class Customer:
"""Aggregate root: controls access to entities."""
def __init__(self, id: str, email: Email):
self.id = id
self.email = email
self._addresses: List[Address] = []
self._orders: List[str] = [] # Order IDs, not full objects
def add_address(self, address: Address):
"""Aggregate enforces invariants."""
if len(self._addresses) >= 5:
raise ValueError("Maximum 5 addresses allowed")
self._addresses.append(address)
@property
def primary_address(self) -> Optional[Address]:
return next((a for a in self._addresses if a.is_primary), None)
# Domain Events
@dataclass
class OrderSubmittedEvent:
order_id: str
occurred_at: datetime = field(default_factory=datetime.now)
# Repository (aggregate persistence)
class OrderRepository:
"""Repository: persist/retrieve aggregates."""
async def find_by_id(self, order_id: str) -> Optional[Order]:
"""Reconstitute aggregate from storage."""
pass
async def save(self, order: Order):
"""Persist aggregate and publish events."""
await self._persist(order)
await self._publish_events(order._events)
order._events.clear()
```
## Resources
- **references/clean-architecture-guide.md**: Detailed layer breakdown
- **references/hexagonal-architecture-guide.md**: Ports and adapters patterns
- **references/ddd-tactical-patterns.md**: Entities, value objects, aggregates
- **assets/clean-architecture-template/**: Complete project structure
- **assets/ddd-examples/**: Domain modeling examples
## Best Practices
1. **Dependency Rule**: Dependencies always point inward
2. **Interface Segregation**: Small, focused interfaces
3. **Business Logic in Domain**: Keep frameworks out of core
4. **Test Independence**: Core testable without infrastructure
5. **Bounded Contexts**: Clear domain boundaries
6. **Ubiquitous Language**: Consistent terminology
7. **Thin Controllers**: Delegate to use cases
8. **Rich Domain Models**: Behavior with data
## Common Pitfalls
- **Anemic Domain**: Entities with only data, no behavior
- **Framework Coupling**: Business logic depends on frameworks
- **Fat Controllers**: Business logic in controllers
- **Repository Leakage**: Exposing ORM objects
- **Missing Abstractions**: Concrete dependencies in core
- **Over-Engineering**: Clean architecture for simple CRUD
@@ -0,0 +1,174 @@
---
name: better-auth-best-practices
description: Skill for integrating Better Auth - the comprehensive TypeScript authentication framework.
---
# Better Auth Integration Guide
**Always consult [better-auth.com/docs](https://better-auth.com/docs) for code examples and latest API.**
Better Auth is a TypeScript-first, framework-agnostic auth framework supporting email/password, OAuth, magic links, passkeys, and more via plugins.
---
## Quick Reference
### Environment Variables
- `BETTER_AUTH_SECRET` - Encryption secret (min 32 chars). Generate: `openssl rand -base64 32`
- `BETTER_AUTH_URL` - Base URL (e.g., `https://example.com`)
Only define `baseURL`/`secret` in config if env vars are NOT set.
### File Location
CLI looks for `auth.ts` in: `./`, `./lib`, `./utils`, or under `./src`. Use `--config` for custom path.
### CLI Commands
- `npx @better-auth/cli@latest migrate` - Apply schema (built-in adapter)
- `npx @better-auth/cli@latest generate` - Generate schema for Prisma/Drizzle
- `npx @better-auth/cli mcp --cursor` - Add MCP to AI tools
**Re-run after adding/changing plugins.**
---
## Core Config Options
| Option | Notes |
| ------------------ | ---------------------------------------------- |
| `appName` | Optional display name |
| `baseURL` | Only if `BETTER_AUTH_URL` not set |
| `basePath` | Default `/api/auth`. Set `/` for root. |
| `secret` | Only if `BETTER_AUTH_SECRET` not set |
| `database` | Required for most features. See adapters docs. |
| `secondaryStorage` | Redis/KV for sessions & rate limits |
| `emailAndPassword` | `{ enabled: true }` to activate |
| `socialProviders` | `{ google: { clientId, clientSecret }, ... }` |
| `plugins` | Array of plugins |
| `trustedOrigins` | CSRF whitelist |
---
## Database
**Direct connections:** Pass `pg.Pool`, `mysql2` pool, `better-sqlite3`, or `bun:sqlite` instance.
**ORM adapters:** Import from `better-auth/adapters/drizzle`, `better-auth/adapters/prisma`, `better-auth/adapters/mongodb`.
**Critical:** Better Auth uses adapter model names, NOT underlying table names. If Prisma model is `User` mapping to table `users`, use `modelName: "user"` (Prisma reference), not `"users"`.
---
## Session Management
**Storage priority:**
1. If `secondaryStorage` defined → sessions go there (not DB)
2. Set `session.storeSessionInDatabase: true` to also persist to DB
3. No database + `cookieCache` → fully stateless mode
**Cookie cache strategies:**
- `compact` (default) - Base64url + HMAC. Smallest.
- `jwt` - Standard JWT. Readable but signed.
- `jwe` - Encrypted. Maximum security.
**Key options:** `session.expiresIn` (default 7 days), `session.updateAge` (refresh interval), `session.cookieCache.maxAge`, `session.cookieCache.version` (change to invalidate all sessions).
---
## User & Account Config
**User:** `user.modelName`, `user.fields` (column mapping), `user.additionalFields`, `user.changeEmail.enabled` (disabled by default), `user.deleteUser.enabled` (disabled by default).
**Account:** `account.modelName`, `account.accountLinking.enabled`, `account.storeAccountCookie` (for stateless OAuth).
**Required for registration:** `email` and `name` fields.
---
## Email Flows
- `emailVerification.sendVerificationEmail` - Must be defined for verification to work
- `emailVerification.sendOnSignUp` / `sendOnSignIn` - Auto-send triggers
- `emailAndPassword.sendResetPassword` - Password reset email handler
---
## Security
**In `advanced`:**
- `useSecureCookies` - Force HTTPS cookies
- `disableCSRFCheck` - ⚠️ Security risk
- `disableOriginCheck` - ⚠️ Security risk
- `crossSubDomainCookies.enabled` - Share cookies across subdomains
- `ipAddress.ipAddressHeaders` - Custom IP headers for proxies
- `database.generateId` - Custom ID generation or `"serial"`/`"uuid"`/`false`
**Rate limiting:** `rateLimit.enabled`, `rateLimit.window`, `rateLimit.max`, `rateLimit.storage` ("memory" | "database" | "secondary-storage").
---
## Hooks
**Endpoint hooks:** `hooks.before` / `hooks.after` - Array of `{ matcher, handler }`. Use `createAuthMiddleware`. Access `ctx.path`, `ctx.context.returned` (after), `ctx.context.session`.
**Database hooks:** `databaseHooks.user.create.before/after`, same for `session`, `account`. Useful for adding default values or post-creation actions.
**Hook context (`ctx.context`):** `session`, `secret`, `authCookies`, `password.hash()`/`verify()`, `adapter`, `internalAdapter`, `generateId()`, `tables`, `baseURL`.
---
## Plugins
**Import from dedicated paths for tree-shaking:**
```
import { twoFactor } from "better-auth/plugins/two-factor"
```
NOT `from "better-auth/plugins"`.
**Popular plugins:** `twoFactor`, `organization`, `passkey`, `magicLink`, `emailOtp`, `username`, `phoneNumber`, `admin`, `apiKey`, `bearer`, `jwt`, `multiSession`, `sso`, `oauthProvider`, `oidcProvider`, `openAPI`, `genericOAuth`.
Client plugins go in `createAuthClient({ plugins: [...] })`.
---
## Client
Import from: `better-auth/client` (vanilla), `better-auth/react`, `better-auth/vue`, `better-auth/svelte`, `better-auth/solid`.
Key methods: `signUp.email()`, `signIn.email()`, `signIn.social()`, `signOut()`, `useSession()`, `getSession()`, `revokeSession()`, `revokeSessions()`.
---
## Type Safety
Infer types: `typeof auth.$Infer.Session`, `typeof auth.$Infer.Session.user`.
For separate client/server projects: `createAuthClient<typeof auth>()`.
---
## Common Gotchas
1. **Model vs table name** - Config uses ORM model name, not DB table name
2. **Plugin schema** - Re-run CLI after adding plugins
3. **Secondary storage** - Sessions go there by default, not DB
4. **Cookie cache** - Custom session fields NOT cached, always re-fetched
5. **Stateless mode** - No DB = session in cookie only, logout on cache expiry
6. **Change email flow** - Sends to current email first, then new email
---
## Resources
- [Docs](https://better-auth.com/docs)
- [Options Reference](https://better-auth.com/docs/reference/options)
- [LLMs.txt](https://better-auth.com/llms.txt)
- [GitHub](https://github.com/better-auth/better-auth)
- [Init Options Source](https://github.com/better-auth/better-auth/blob/main/packages/core/src/types/init-options.ts)
@@ -0,0 +1,101 @@
---
name: brainstorming
description: 'You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.'
---
# Brainstorming Ideas Into Designs
## Overview
Help turn ideas into fully formed designs and specs through natural collaborative dialogue.
Start by understanding the current project context, then ask questions one at a time to refine the idea. Once you understand what you're building, present the design and get user approval.
<HARD-GATE>
Do NOT invoke any implementation skill, write any code, scaffold any project, or take any implementation action until you have presented a design and the user has approved it. This applies to EVERY project regardless of perceived simplicity.
</HARD-GATE>
## Anti-Pattern: "This Is Too Simple To Need A Design"
Every project goes through this process. A todo list, a single-function utility, a config change — all of them. "Simple" projects are where unexamined assumptions cause the most wasted work. The design can be short (a few sentences for truly simple projects), but you MUST present it and get approval.
## Checklist
You MUST create a task for each of these items and complete them in order:
1. **Explore project context** — check files, docs, recent commits
2. **Ask clarifying questions** — one at a time, understand purpose/constraints/success criteria
3. **Propose 2-3 approaches** — with trade-offs and your recommendation
4. **Present design** — in sections scaled to their complexity, get user approval after each section
5. **Write design doc** — save to `docs/plans/YYYY-MM-DD-<topic>-design.md` and commit
6. **Transition to implementation** — invoke writing-plans skill to create implementation plan
## Process Flow
```dot
digraph brainstorming {
"Explore project context" [shape=box];
"Ask clarifying questions" [shape=box];
"Propose 2-3 approaches" [shape=box];
"Present design sections" [shape=box];
"User approves design?" [shape=diamond];
"Write design doc" [shape=box];
"Invoke writing-plans skill" [shape=doublecircle];
"Explore project context" -> "Ask clarifying questions";
"Ask clarifying questions" -> "Propose 2-3 approaches";
"Propose 2-3 approaches" -> "Present design sections";
"Present design sections" -> "User approves design?";
"User approves design?" -> "Present design sections" [label="no, revise"];
"User approves design?" -> "Write design doc" [label="yes"];
"Write design doc" -> "Invoke writing-plans skill";
}
```
**The terminal state is invoking writing-plans.** Do NOT invoke frontend-design, mcp-builder, or any other implementation skill. The ONLY skill you invoke after brainstorming is writing-plans.
## The Process
**Understanding the idea:**
- Check out the current project state first (files, docs, recent commits)
- Ask questions one at a time to refine the idea
- Prefer multiple choice questions when possible, but open-ended is fine too
- Only one question per message - if a topic needs more exploration, break it into multiple questions
- Focus on understanding: purpose, constraints, success criteria
**Exploring approaches:**
- Propose 2-3 different approaches with trade-offs
- Present options conversationally with your recommendation and reasoning
- Lead with your recommended option and explain why
**Presenting the design:**
- Once you believe you understand what you're building, present the design
- Scale each section to its complexity: a few sentences if straightforward, up to 200-300 words if nuanced
- Ask after each section whether it looks right so far
- Cover: architecture, components, data flow, error handling, testing
- Be ready to go back and clarify if something doesn't make sense
## After the Design
**Documentation:**
- Write the validated design to `docs/plans/YYYY-MM-DD-<topic>-design.md`
- Use elements-of-style:writing-clearly-and-concisely skill if available
- Commit the design document to git
**Implementation:**
- Invoke the writing-plans skill to create a detailed implementation plan
- Do NOT invoke any other skill. writing-plans is the next step.
## Key Principles
- **One question at a time** - Don't overwhelm with multiple questions
- **Multiple choice preferred** - Easier to answer than open-ended when possible
- **YAGNI ruthlessly** - Remove unnecessary features from all designs
- **Explore alternatives** - Always propose 2-3 approaches before settling
- **Incremental validation** - Present design, get approval before moving on
- **Be flexible** - Go back and clarify when something doesn't make sense
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,73 @@
---
name: brand-guidelines
description: Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
license: Complete terms in LICENSE.txt
---
# Anthropic Brand Styling
## Overview
To access Anthropic's official brand identity and style resources, use this skill.
**Keywords**: branding, corporate identity, visual identity, post-processing, styling, brand colors, typography, Anthropic brand, visual formatting, visual design
## Brand Guidelines
### Colors
**Main Colors:**
- Dark: `#141413` - Primary text and dark backgrounds
- Light: `#faf9f5` - Light backgrounds and text on dark
- Mid Gray: `#b0aea5` - Secondary elements
- Light Gray: `#e8e6dc` - Subtle backgrounds
**Accent Colors:**
- Orange: `#d97757` - Primary accent
- Blue: `#6a9bcc` - Secondary accent
- Green: `#788c5d` - Tertiary accent
### Typography
- **Headings**: Poppins (with Arial fallback)
- **Body Text**: Lora (with Georgia fallback)
- **Note**: Fonts should be pre-installed in your environment for best results
## Features
### Smart Font Application
- Applies Poppins font to headings (24pt and larger)
- Applies Lora font to body text
- Automatically falls back to Arial/Georgia if custom fonts unavailable
- Preserves readability across all systems
### Text Styling
- Headings (24pt+): Poppins font
- Body text: Lora font
- Smart color selection based on background
- Preserves text hierarchy and formatting
### Shape and Accent Colors
- Non-text shapes use accent colors
- Cycles through orange, blue, and green accents
- Maintains visual interest while staying on-brand
## Technical Details
### Font Management
- Uses system-installed Poppins and Lora fonts when available
- Provides automatic fallback to Arial (headings) and Georgia (body)
- No font installation required - works with existing system fonts
- For best results, pre-install Poppins and Lora fonts in your environment
### Color Application
- Uses RGB color values for precise brand matching
- Applied via python-pptx's RGBColor class
- Maintains color fidelity across different systems
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1,137 @@
---
name: canvas-design
description: Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.
license: Complete terms in LICENSE.txt
---
These are instructions for creating design philosophies - aesthetic movements that are then EXPRESSED VISUALLY. Output only .md files, .pdf files, and .png files.
Complete this in two steps:
1. Design Philosophy Creation (.md file)
2. Express by creating it on a canvas (.pdf file or .png file)
First, undertake this task:
## DESIGN PHILOSOPHY CREATION
To begin, create a VISUAL PHILOSOPHY (not layouts or templates) that will be interpreted through:
- Form, space, color, composition
- Images, graphics, shapes, patterns
- Minimal text as visual accent
### THE CRITICAL UNDERSTANDING
- What is received: Some subtle input or instructions by the user that should be taken into account, but used as a foundation; it should not constrain creative freedom.
- What is created: A design philosophy/aesthetic movement.
- What happens next: Then, the same version receives the philosophy and EXPRESSES IT VISUALLY - creating artifacts that are 90% visual design, 10% essential text.
Consider this approach:
- Write a manifesto for an art movement
- The next phase involves making the artwork
The philosophy must emphasize: Visual expression. Spatial communication. Artistic interpretation. Minimal words.
### HOW TO GENERATE A VISUAL PHILOSOPHY
**Name the movement** (1-2 words): "Brutalist Joy" / "Chromatic Silence" / "Metabolist Dreams"
**Articulate the philosophy** (4-6 paragraphs - concise but complete):
To capture the VISUAL essence, express how the philosophy manifests through:
- Space and form
- Color and material
- Scale and rhythm
- Composition and balance
- Visual hierarchy
**CRITICAL GUIDELINES:**
- **Avoid redundancy**: Each design aspect should be mentioned once. Avoid repeating points about color theory, spatial relationships, or typographic principles unless adding new depth.
- **Emphasize craftsmanship REPEATEDLY**: The philosophy MUST stress multiple times that the final work should appear as though it took countless hours to create, was labored over with care, and comes from someone at the absolute top of their field. This framing is essential - repeat phrases like "meticulously crafted," "the product of deep expertise," "painstaking attention," "master-level execution."
- **Leave creative space**: Remain specific about the aesthetic direction, but concise enough that the next Claude has room to make interpretive choices also at a extremely high level of craftmanship.
The philosophy must guide the next version to express ideas VISUALLY, not through text. Information lives in design, not paragraphs.
### PHILOSOPHY EXAMPLES
**"Concrete Poetry"**
Philosophy: Communication through monumental form and bold geometry.
Visual expression: Massive color blocks, sculptural typography (huge single words, tiny labels), Brutalist spatial divisions, Polish poster energy meets Le Corbusier. Ideas expressed through visual weight and spatial tension, not explanation. Text as rare, powerful gesture - never paragraphs, only essential words integrated into the visual architecture. Every element placed with the precision of a master craftsman.
**"Chromatic Language"**
Philosophy: Color as the primary information system.
Visual expression: Geometric precision where color zones create meaning. Typography minimal - small sans-serif labels letting chromatic fields communicate. Think Josef Albers' interaction meets data visualization. Information encoded spatially and chromatically. Words only to anchor what color already shows. The result of painstaking chromatic calibration.
**"Analog Meditation"**
Philosophy: Quiet visual contemplation through texture and breathing room.
Visual expression: Paper grain, ink bleeds, vast negative space. Photography and illustration dominate. Typography whispered (small, restrained, serving the visual). Japanese photobook aesthetic. Images breathe across pages. Text appears sparingly - short phrases, never explanatory blocks. Each composition balanced with the care of a meditation practice.
**"Organic Systems"**
Philosophy: Natural clustering and modular growth patterns.
Visual expression: Rounded forms, organic arrangements, color from nature through architecture. Information shown through visual diagrams, spatial relationships, iconography. Text only for key labels floating in space. The composition tells the story through expert spatial orchestration.
**"Geometric Silence"**
Philosophy: Pure order and restraint.
Visual expression: Grid-based precision, bold photography or stark graphics, dramatic negative space. Typography precise but minimal - small essential text, large quiet zones. Swiss formalism meets Brutalist material honesty. Structure communicates, not words. Every alignment the work of countless refinements.
_These are condensed examples. The actual design philosophy should be 4-6 substantial paragraphs._
### ESSENTIAL PRINCIPLES
- **VISUAL PHILOSOPHY**: Create an aesthetic worldview to be expressed through design
- **MINIMAL TEXT**: Always emphasize that text is sparse, essential-only, integrated as visual element - never lengthy
- **SPATIAL EXPRESSION**: Ideas communicate through space, form, color, composition - not paragraphs
- **ARTISTIC FREEDOM**: The next Claude interprets the philosophy visually - provide creative room
- **PURE DESIGN**: This is about making ART OBJECTS, not documents with decoration
- **EXPERT CRAFTSMANSHIP**: Repeatedly emphasize the final work must look meticulously crafted, labored over with care, the product of countless hours by someone at the top of their field
**The design philosophy should be 4-6 paragraphs long.** Fill it with poetic design philosophy that brings together the core vision. Avoid repeating the same points. Keep the design philosophy generic without mentioning the intention of the art, as if it can be used wherever. Output the design philosophy as a .md file.
---
## DEDUCING THE SUBTLE REFERENCE
**CRITICAL STEP**: Before creating the canvas, identify the subtle conceptual thread from the original request.
**THE ESSENTIAL PRINCIPLE**:
The topic is a **subtle, niche reference embedded within the art itself** - not always literal, always sophisticated. Someone familiar with the subject should feel it intuitively, while others simply experience a masterful abstract composition. The design philosophy provides the aesthetic language. The deduced topic provides the soul - the quiet conceptual DNA woven invisibly into form, color, and composition.
This is **VERY IMPORTANT**: The reference must be refined so it enhances the work's depth without announcing itself. Think like a jazz musician quoting another song - only those who know will catch it, but everyone appreciates the music.
---
## CANVAS CREATION
With both the philosophy and the conceptual framework established, express it on a canvas. Take a moment to gather thoughts and clear the mind. Use the design philosophy created and the instructions below to craft a masterpiece, embodying all aspects of the philosophy with expert craftsmanship.
**IMPORTANT**: For any type of content, even if the user requests something for a movie/game/book, the approach should still be sophisticated. Never lose sight of the idea that this should be art, not something that's cartoony or amateur.
To create museum or magazine quality work, use the design philosophy as the foundation. Create one single page, highly visual, design-forward PDF or PNG output (unless asked for more pages). Generally use repeating patterns and perfect shapes. Treat the abstract philosophical design as if it were a scientific bible, borrowing the visual language of systematic observation—dense accumulation of marks, repeated elements, or layered patterns that build meaning through patient repetition and reward sustained viewing. Add sparse, clinical typography and systematic reference markers that suggest this could be a diagram from an imaginary discipline, treating the invisible subject with the same reverence typically reserved for documenting observable phenomena. Anchor the piece with simple phrase(s) or details positioned subtly, using a limited color palette that feels intentional and cohesive. Embrace the paradox of using analytical visual language to express ideas about human experience: the result should feel like an artifact that proves something ephemeral can be studied, mapped, and understood through careful attention. This is true art.
**Text as a contextual element**: Text is always minimal and visual-first, but let context guide whether that means whisper-quiet labels or bold typographic gestures. A punk venue poster might have larger, more aggressive type than a minimalist ceramics studio identity. Most of the time, font should be thin. All use of fonts must be design-forward and prioritize visual communication. Regardless of text scale, nothing falls off the page and nothing overlaps. Every element must be contained within the canvas boundaries with proper margins. Check carefully that all text, graphics, and visual elements have breathing room and clear separation. This is non-negotiable for professional execution. **IMPORTANT: Use different fonts if writing text. Search the `./canvas-fonts` directory. Regardless of approach, sophistication is non-negotiable.**
Download and use whatever fonts are needed to make this a reality. Get creative by making the typography actually part of the art itself -- if the art is abstract, bring the font onto the canvas, not typeset digitally.
To push boundaries, follow design instinct/intuition while using the philosophy as a guiding principle. Embrace ultimate design freedom and choice. Push aesthetics and design to the frontier.
**CRITICAL**: To achieve human-crafted quality (not AI-generated), create work that looks like it took countless hours. Make it appear as though someone at the absolute top of their field labored over every detail with painstaking care. Ensure the composition, spacing, color choices, typography - everything screams expert-level craftsmanship. Double-check that nothing overlaps, formatting is flawless, every detail perfect. Create something that could be shown to people to prove expertise and rank as undeniably impressive.
Output the final result as a single, downloadable .pdf or .png file, alongside the design philosophy used as a .md file.
---
## FINAL STEP
**IMPORTANT**: The user ALREADY said "It isn't perfect enough. It must be pristine, a masterpiece if craftsmanship, as if it were about to be displayed in a museum."
**CRITICAL**: To refine the work, avoid adding more graphics; instead refine what has been created and make it extremely crisp, respecting the design philosophy and the principles of minimalism entirely. Rather than adding a fun filter or refactoring a font, consider how to make the existing composition more cohesive with the art. If the instinct is to call a new function or draw a new shape, STOP and instead ask: "How can I make what's already here more of a piece of art?"
Take a second pass. Go back to the code and refine/polish further to make this a philosophically designed masterpiece.
## MULTI-PAGE OPTION
To create additional pages when requested, create more creative pages along the same lines as the design philosophy but distinctly different as well. Bundle those pages in the same .pdf or many .pngs. Treat the first page as just a single page in a whole coffee table book waiting to be filled. Make the next pages unique twists and memories of the original. Have them almost tell a story in a very tasteful way. Exercise full creative freedom.
@@ -0,0 +1,93 @@
Copyright 2012 The Arsenal Project Authors ([email protected])
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2019 The Big Shoulders Project Authors (https://github.com/xotypeco/big_shoulders)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2024 The Boldonse Project Authors (https://github.com/googlefonts/boldonse)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2022 The Bricolage Grotesque Project Authors (https://github.com/ateliertriay/bricolage)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2018 The Crimson Pro Project Authors (https://github.com/Fonthausen/CrimsonPro)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2020 The DM Mono Project Authors (https://www.github.com/googlefonts/dm-mono)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,94 @@
Copyright (c) 2011 by LatinoType Limitada ([email protected]),
with Reserved Font Names "Erica One"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2022 The Gloock Project Authors (https://github.com/duartp/gloock)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright © 2017 IBM Corp. with Reserved Font Name "Plex"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright (c) 2011, Santiago Orozco ([email protected]), with Reserved Font Name "Italiana".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2019 The Jura Project Authors (https://github.com/ossobuffo/jura)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2012 The Libre Baskerville Project Authors (https://github.com/impallari/Libre-Baskerville) with Reserved Font Name Libre Baskerville.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2011 The Lora Project Authors (https://github.com/cyrealtype/Lora-Cyrillic), with Reserved Font Name "Lora".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2025 The National Park Project Authors (https://github.com/benhoepner/National-Park)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright (c) 2010, Kimberly Geswein (kimberlygeswein.com)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,93 @@
Copyright 2021 The Outfit Project Authors (https://github.com/Outfitio/Outfit-Fonts)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Some files were not shown because too many files have changed in this diff Show More