Conventions
Audience: LLM agents working in this repository. Companion doc: /design/principles Verified in: iter/docs-polish-dx
These are the coding and operational conventions enforced inside this monorepo. They complement the design rationale in /design/principles — that page explains why, this page explains what to do.
Naming and file style
- Use kebab-case for file names in SDK hooks and helpers (example:
use-grist-schema.ts). - Use clear exported symbol names that start with
useGristfor hooks andGristfor types/components. - Keep test files beside implementation when practical, named
*.test.tsor*.test.tsx.
API boundaries
- Only consume public exports from
grist-widget-sdkorgrist-widget-sdk/emulator. - Never import from package internals such as
grist-widget-sdk/src/.... - If a symbol should be public, export it from
packages/core/src/sdk/index.ts.
Preferred widget integration pattern
- Use
GristWidgetProvider+GristBoundary+useGrist()for primary widget behavior. - Use
useGristSchema()when schema/sample context is needed. - Use advanced hooks from
grist-widget-sdk/advancedonly when the primary API surface is insufficient.
Error and fallback handling
- Assume Grist context may be unavailable in local dev/tests.
- Handle booting, empty, and new-row states explicitly in UI.
- For write operations, prefer
w.table.*helpers fromuseGrist()over custom action payloads.
Documentation and change hygiene
- Update docs in
apps/docs/when changing exported API, command flows, or repo structure (including Replica document andpackages/core/README.mdwhenGristReplicaDocumentchanges). - Keep examples aligned with current package names and workspace IDs.
- Avoid stale path references (for example, use
apps/playground, not removed paths likeapps/demos).
Testing patterns
- Unit / hook tests live under
packages/core/tests/sdk/and run through theunitvitest project (jsdomenvironment). - Emulator-driven integration tests live under
packages/core/tests/emulator/and run through theemulatorproject. - Runnable doc examples are playground widgets under
apps/playground/src/widgets/<id>/WidgetApp.tsx. They are type-checked and bundled bypnpm --filter playground build:widgets(rootpnpm testruns this). That is the canonical proof that docs example code is valid — not a separate docs unit-test suite. - In guide pages, embed widget source with VitePress
<<< ../../playground/src/widgets/<id>/WidgetApp.tsx.pnpm --filter docs build(included in rootpnpm test) fails if an include path is wrong. Do not paste duplicate TSX into markdown. There is no separate docs unit-test suite — playground build + docs build are enough. renderWithGrist()fromgrist-widget-sdk/emulator/testingis the canonical primitive for any test that needs a real provider chain with a fake Grist host.