Skip to content
Signal

Getting started

Contributing

Where each source of truth lives, how to regenerate, and what the tests check.

Requirements: Go 1.24+, the Swift 6 toolchain (Xcode 16+) for the package, Node for Wrangler.

Where things live

PathWhat it isEdited by
tokens/tokens.json, components.tokens.json and their JSON schemashand
components/Component contracts (YAML) and component.schema.jsonhand
icons/Transit icon SVGs; rules in icons/README.mdhand
brand/signal/The Signal mark and lockupshand
docs-src/This site: nav.json (sidebar and redirects), pages/ (page bodies), partials/, assets/ (shell CSS and scripts)hand
docs/BRAND.md, docs/INTEGRATION.mdBrand rules; rendered as the Brand pageshand
docs/shots/Reference screenshots of the iOS apphand
platforms/Web CSS system and Swift packagemostly generated
docs/ (everything else)The built sitegenerated

Regenerate and test

go generate ./...                  # tokens/, components/, icons/, brand/, docs-src/ → platforms/ and docs/
go test ./...                      # schemas, contracts, raw-value checks, freshness, docs links
swift build                        # builds the Signal package
npx wrangler@4 dev                 # preview this site locally
npx wrangler@4 deploy --dry-run    # checks the docs site bundle

go test ./... fails if a generated file is stale, a token breaks its schema, a component stylesheet hard-codes a colour or size, a contract's alias doesn't resolve, a named web function, CSS rule or screenshot is missing, a docs page carries an inline style, or an internal link doesn't resolve.

Change a token

  1. Edit tokens/tokens.json (or tokens/components.tokens.json for a component token).
  2. go generate ./...
  3. go test ./...
  4. Commit the token and every regenerated file together.

Add a component

  1. Write components/<component>.yaml against components/component.schema.json: anatomy, states, accessibility, the tokens each part reads, platform implementations. Write values no token covers as literals with a note. Screenshot paths are relative to docs/.
  2. Add any component tokens to tokens/components.tokens.json and, for a web CSS component, its stylesheet in platforms/web/components/ reading each token through an override.
  3. Add the component name to the list in Generate (scripts/designtokens/outputs.go) so it is bundled into components.json, and add its page to docs-src/nav.json.
  4. go generate ./... and go test ./....

Change a docs page

Edit the page body in docs-src/pages/<path>.html (or the Markdown it names in nav.json) and run go generate ./.... The shell, sidebar, pager, search index and redirects are generated. Never edit files in docs/ except BRAND.md, INTEGRATION.md, shots/, the PNG favicons and favicon.ico. Bodies can use these directives:

DirectiveRenders
<signal-demo-code>The markup of the page's live example rows as a snippet
<signal-component-tokens name>A component's tokens from components.tokens.json
<signal-contract name>A contract's states, anatomy, accessibility and platforms from components/*.yaml
<signal-utilities file match>The utility classes in a platforms/web stylesheet
<signal-tokens-reference>Every token as tables
<signal-shots>Every screenshot in docs/shots

Use Signal classes (ct-*) for everything on a page. Page-local CSS is only the shell (docs-src/assets/docs.css); the migrated app mockups keep their stylesheets (spec.css, ios.css, gallery.css), scoped under .legacy. A style attribute in a body is moved into the generated /site/hoisted.css, so no page ships an inline style.

Change an icon

Follow icons/README.md, then go generate ./....