Skip to content

Latest commit

Β 

History

History
88 lines (74 loc) Β· 7.06 KB

File metadata and controls

88 lines (74 loc) Β· 7.06 KB

Agents guide for the xstyled monorepo. Tool-agnostic. Update when a convention changes.

Repo

  • pnpm workspaces, Changesets for release. Seven packages under packages/: util, prop-types, system, core, emotion, styled-components, babel-preset-emotion-css-prop.
  • scripts/ holds repo-level tooling. website/ is the Gatsby docs site. benchmarks/ compares against styled-system.

Commands

  • pnpm install --frozen-lockfile for a CI-equivalent install.
  • pnpm build before pnpm check:types; the augmentation test resolves @xstyled/system through packages/system/dist/index.d.ts.
  • pnpm lint, pnpm test, pnpm check:types, pnpm bench:types, pnpm bench:runtime.

Type tests

  • Per package: src/__type-tests__/*.test-d.ts(x) + tsconfig.types.json (excluded from main tsconfig and from jest).
  • Module-augmentation test is isolated in packages/system/type-tests-aug/ with its own tsconfig.aug.json because declare module is project-wide.
  • Pair Expect<Equal | Assignable | NotAssignable<...>> positives with @ts-expect-error value-level negatives.
  • Hook calls inside type tests go inside a _useFooAssertions() helper so react-hooks/rules-of-hooks doesn't fire.
  • scripts/check-types.mjs chains all five projects.

Perf benches

  • scripts/bench-types.mjs: synthetic themes through tsc --extendedDiagnostics. Defaults to 50/200/500 color tokens; --sizes to override.
  • scripts/bench-runtime.mjs: compose() init and system(propsBag) throughput. Rerun 3x and take the median.
  • Hot paths: packages/system/src/style.ts, packages/util/src/index.ts (merge/assign/flattenStrings/get), packages/core/src/transform.ts, packages/emotion/src/createCssFunction.ts.

Module augmentation (consumer contract)

  • declare module '@xstyled/system' { export interface Theme { … } } from styled.d.ts. Augmenting any other module specifier won't reach the system types.

Type gotchas

  • useTheme in @xstyled/emotion returns @emotion/react's Theme, not @xstyled/system's. Emotion users augment @emotion/react separately.
  • Space<T> etc. union with {} via ThemeNamespaceValue, so negative tests on them are not enforceable. Color<T> is strict and negation tests work.
  • _ (base/no-breakpoint key) lives in screens, not states. ThemeVariants<T> does ThemeScreens<T> & Omit<ThemeStates<T>, '_'> to avoid the screens._: number vs states._: null collision.
  • SynthesizedPath<T, D = 6> is depth-bounded; past depth 6 the result widens to string. Numeric keys are preserved.

Commits and PRs

  • Conventional Commits (chore:, fix:, feat:, refactor:, perf:, test:, review:); scope optional.
  • Changesets drives versioning and changelogs. Run pnpm changeset to add one for any user-visible change to a public package; commit the generated .changeset/*.md with the change. Internal-only / repo-tooling changes don't need one.
  • Releases publish via .github/workflows/release.yml (changesets/action) using npm trusted publishing (OIDC). There is no NPM_TOKEN; the workflow needs id-token: write.
  • Fixes #n only when the diff genuinely resolves the issue. Refs for things mitigated, regression-locked by tests, or touched.
  • Don't open a PR unless asked. Pushing a branch is not opening a PR.
  • Be frugal with PR replies. Only post when a reply is genuinely needed; the diff is the record for routine fixes.

Voice

  • Machine-oriented markdown (this file, project notes, agent instructions): dashes for lists, no headers, no bold, no tables.
  • Human-facing markdown (READMEs, PRs, changesets, release notes): written for a human, no internal specifics, avoid point-in-time numbers that will go stale.
  • No em-dashes. Use a period, comma, parenthetical, or appropriate unicode punctuation.
  • Reference code with file_path:line_number.
  • Don't put "Generated by Claude" or any AI attribution on commits, PRs, files, or output.
  • Don't proactively create *.md files unless asked; this file is the exception.

How to think

  • Scientific method: hypothesis, hold variables constant, test one variable at a time, update.
  • Meticulous: observe, note, plan, act, reconcile against the plan. Keep a to-do list; append new requests unless told otherwise.
  • Gardener: handle unobjectionable cleanup as you pass through.
  • Question complexity. Propose simpler alternatives. Question assumptions; don't accept overengineering.
  • Don't silently work around issues; log them in a backlog rather than deferring invisibly.
  • Verify against first-party docs and current code before deciding. Training-data recall is a hypothesis, not a source of truth.

How to plan

  • Ask clarifying multiple-choice questions until the ask fits in one paragraph the user agrees with.
  • Present 2-3 directions with research-backed opinions, not a single decided plan.
  • Never give time estimates.

How to ship

  • Types are law. No as any, non-null assertions, or @ts-expect-error escape hatches except as deliberate negative-behavior tests, clearly differentiated.
  • Tests ship with features. Aim for branch coverage above 80% (no tooling threshold; aspirational). Cover happy paths, edge cases, failure modes. Prefer inline snapshots seeded empty. Use red/green to validate fix and test together. Local tests run well under 30s.
  • Comments explain non-obvious current behavior. Never narrate change history.
  • Hot-path code earns microbenchmarks before claiming optimization.
  • Run the build to verify changes; don't start a dev server unless asked.
  • Backward compatibility applies only to public API surfaces; internal code is rewritable when complexity warrants.
  • Errors carry typed metadata for context but never leak internals to users; full traces stay in server logs.
  • Dry-run destructive or batch operations and verify targeting before executing.
  • Subscribe to PR events and handle review comments and failing builds automatically.

Git discipline

  • Treat the working tree as ephemeral; commit when work is at a stable point.
  • git push -u origin <branch>; on transient network failure retry with exponential backoff, diagnose anything that fails repeatedly.
  • Confirm before destructive ops (push --force, reset --hard, branch -D, amending or rebasing pushed commits). Never force-push main.
  • Never bypass hooks (--no-verify) or disable signing (--no-gpg-sign). Fix the underlying failure.
  • Investigate unexpected state before deleting or overwriting; it may be the user's in-progress work.

Don't

  • Push to main directly.
  • Bump versions or publish to npm by hand; the release workflow does it from merged changesets.
  • Add new features in a modernize/triage PR.

CI

  • .github/workflows/ci.yml on push to main and PRs to main or next. Steps: checkout v4, pnpm/action-setup v4, setup-node v4 (.nvmrc, currently 22, cache: pnpm), pnpm install --frozen-lockfile, pnpm build, pnpm lint, pnpm check:types, pnpm test --coverage, Codecov and bundlewatch as continue-on-error.
  • .github/workflows/release.yml on push to main. Uses changesets/action@v1 with publish: pnpm release and id-token: write for npm trusted publishing.
  • .github/dependabot.yml groups npm and GitHub Actions updates.