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
| Path | What it is | Edited by |
|---|---|---|
tokens/ | tokens.json, components.tokens.json and their JSON schemas | hand |
components/ | Component contracts (YAML) and component.schema.json | hand |
icons/ | Transit icon SVGs; rules in icons/README.md | hand |
brand/signal/ | The Signal mark and lockups | hand |
docs-src/ | This site: nav.json (sidebar and redirects), pages/ (page bodies), partials/, assets/ (shell CSS and scripts) | hand |
docs/BRAND.md, docs/INTEGRATION.md | Brand rules; rendered as the Brand pages | hand |
docs/shots/ | Reference screenshots of the iOS app | hand |
platforms/ | Web CSS system and Swift package | mostly generated |
docs/ (everything else) | The built site | generated |
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
- Edit
tokens/tokens.json(ortokens/components.tokens.jsonfor a component token). go generate ./...go test ./...- Commit the token and every regenerated file together.
Add a component
- Write
components/<component>.yamlagainstcomponents/component.schema.json: anatomy, states, accessibility, the tokens each part reads, platform implementations. Write values no token covers as literals with anote. Screenshot paths are relative todocs/. - Add any component tokens to
tokens/components.tokens.jsonand, for a web CSS component, its stylesheet inplatforms/web/components/reading each token through an override. - Add the component name to the list in
Generate(scripts/designtokens/outputs.go) so it is bundled intocomponents.json, and add its page todocs-src/nav.json. go generate ./...andgo 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:
| Directive | Renders |
|---|---|
<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 ./....