|
1 | 1 | # Contributing to Semiotic |
2 | 2 |
|
3 | | -Welcome! We're glad you're here. |
| 3 | +Semiotic is a React data visualization library with canvas-first chart rendering, server-side SVG rendering, AI/MCP tooling, and a Parcel-powered documentation site. This guide describes the current repository workflow; package scripts and CI are the source of truth. |
4 | 4 |
|
5 | | -## Getting started |
| 5 | +## Getting Started |
6 | 6 |
|
7 | 7 | ```bash |
8 | 8 | git clone https://github.com/nteract/semiotic.git |
9 | 9 | cd semiotic |
10 | | -npm install --legacy-peer-deps |
11 | | -npm test # 628 unit tests (Jest) |
12 | | -npm run dist # build all bundles (Rollup) |
13 | | -npm run typescript # type check |
| 10 | +npm install |
| 11 | +npm test |
| 12 | +npm run typescript |
| 13 | +npm run dist |
14 | 14 | ``` |
15 | 15 |
|
16 | | -Requires Node 18+. See `.node-version`. |
| 16 | +The repo pins Node with Volta in `package.json`. Use that version when possible. |
17 | 17 |
|
18 | | -## Project structure |
| 18 | +## Project Structure |
19 | 19 |
|
20 | | -``` |
| 20 | +```text |
21 | 21 | src/ |
22 | 22 | components/ |
23 | | - StreamXYFrame.tsx, StreamOrdinalFrame.tsx, StreamNetworkFrame.tsx # core Frames |
| 23 | + StreamXYFrame.tsx, StreamOrdinalFrame.tsx, StreamNetworkFrame.tsx, StreamGeoFrame.tsx |
24 | 24 | charts/ |
25 | 25 | xy/ # LineChart, AreaChart, Scatterplot, etc. |
26 | 26 | ordinal/ # BarChart, StackedBarChart, PieChart, etc. |
27 | 27 | network/ # ForceDirectedGraph, SankeyDiagram, TreeDiagram, etc. |
28 | | - shared/ # colorUtils, hooks, validateChartData, validateProps |
29 | | - server/ # renderToStaticSVG |
| 28 | + geo/ # ChoroplethMap, FlowMap, DistanceCartogram, etc. |
| 29 | + realtime/ # push-driven realtime charts |
| 30 | + shared/ # shared HOC helpers, validation, metadata |
| 31 | + server/ # static SVG, image, dashboard, and export utilities |
30 | 32 | processing/ # data pipelines and layout algorithms |
31 | | -ai/ # schema.json, MCP server, CLI, system prompt, examples |
32 | | -scripts/ # build.mjs, release scripts |
33 | | -docs/ # website source (Parcel) |
| 33 | +ai/ # schema, MCP server, CLI, prompts, examples, metadata |
| 34 | +docs/ # documentation site source |
| 35 | +integration-tests/# Playwright fixtures and specs |
| 36 | +scripts/ # build, release, validation, and generated-doc scripts |
34 | 37 | ``` |
35 | 38 |
|
36 | | -## Development workflow |
| 39 | +## Development Workflow |
| 40 | + |
| 41 | +1. Create a branch from `main`. |
| 42 | +2. Make focused changes. |
| 43 | +3. Run the narrow tests or checks that cover your change. |
| 44 | +4. Run broader release checks for shared behavior, public API changes, SSR, AI contracts, or docs changes. |
| 45 | +5. Open a PR against `main` with the checks you ran. |
| 46 | + |
| 47 | +## Toolchain |
37 | 48 |
|
38 | | -1. Create a branch from `main` |
39 | | -2. Make your changes |
40 | | -3. Run `npm test` and `npm run dist` to verify |
41 | | -4. Open a PR against `main` |
42 | | -5. CI runs tests, build, and type check automatically |
| 49 | +- **Rollup** via `scripts/build.mjs` for library bundles. |
| 50 | +- **Parcel** for the docs website. |
| 51 | +- **TypeScript 6** for type checking and declarations. |
| 52 | +- **Vitest** for unit, integration, and benchmark tests. |
| 53 | +- **Playwright** for browser and visual regression coverage. |
| 54 | +- **esbuild** for the bundled MCP server. |
| 55 | +- **size-limit** for bundle budgets. |
43 | 56 |
|
44 | | -## Build toolchain |
| 57 | +## Common Commands |
45 | 58 |
|
46 | | -- **Rollup 4** — library bundles (`npm run dist`) |
47 | | -- **Parcel** — docs website (`npm start`) |
48 | | -- **TypeScript 5** — type checking (`npm run typescript`) |
49 | | -- **Jest** — unit tests (`npm test`) |
50 | | -- **Playwright** — integration tests (`npm run test:dist`) |
| 59 | +```bash |
| 60 | +# Core checks |
| 61 | +npm test |
| 62 | +npm run typescript |
| 63 | +npm run typescript:mcp |
| 64 | +npm run lint |
| 65 | + |
| 66 | +# Builds |
| 67 | +npm run dist |
| 68 | +npm run dist:prod |
| 69 | +npm run build:mcp |
| 70 | + |
| 71 | +# Browser and visual tests |
| 72 | +npm run test:dist |
| 73 | +npm run test:visual:update |
| 74 | + |
| 75 | +# Docs |
| 76 | +npm run docs:dev |
| 77 | +npm run website:build |
| 78 | +npm run docs:api:json |
| 79 | +npm run check:docs-routes |
| 80 | + |
| 81 | +# AI and public-surface contracts |
| 82 | +npm run check:chart-specs |
| 83 | +npm run check:claude-md-coverage |
| 84 | +npm run check:mcp-registry |
| 85 | +npm run check:surface |
| 86 | +npm run check:ai-contracts |
| 87 | +npm run check:ai-examples-coverage |
| 88 | + |
| 89 | +# Release-oriented checks |
| 90 | +npm run check:ssr |
| 91 | +npm run check:test-quality |
| 92 | +npm run check:jsdoc-coverage |
| 93 | +npm run size |
| 94 | +npm run check:pack |
| 95 | +npm run release:check |
| 96 | +``` |
51 | 97 |
|
52 | 98 | ## Architecture |
53 | 99 |
|
54 | | -Semiotic has three layers: |
| 100 | +Semiotic has three main user-facing layers: |
55 | 101 |
|
56 | 102 | | Layer | Purpose | Example | |
57 | | -|---|---|---| |
58 | | -| **HOC Charts** | Simple props, sensible defaults | `<LineChart data={d} xAccessor="x" yAccessor="y" />` | |
59 | | -| **Frames** | Full control over rendering and interaction | `<XYFrame lines={d} customLineMark={...} />` | |
60 | | -| **Utilities** | Axes, legends, annotations, brushes | Used internally by Frames | |
| 103 | +| --- | --- | --- | |
| 104 | +| **HOC charts** | Focused chart APIs with sensible defaults | `<LineChart data={d} xAccessor="x" yAccessor="y" />` | |
| 105 | +| **Stream Frames** | Lower-level rendering, interaction, streaming, and SSR behavior | `<StreamXYFrame ... />` | |
| 106 | +| **Utilities and AI tooling** | Validation, serialization, themes, server rendering, MCP, and assistant contracts | `validateProps`, `renderChart`, `semiotic-ai` | |
61 | 107 |
|
62 | | -HOC charts wrap Frames. Every HOC accepts `frameProps` to pass through to |
63 | | -the underlying Frame for advanced use cases. |
| 108 | +HOC charts wrap Stream Frames. Every HOC accepts `frameProps` for advanced pass-through behavior. |
64 | 109 |
|
65 | | -## Testing |
| 110 | +## Testing Guidance |
66 | 111 |
|
67 | | -- Unit tests live next to source files: `ComponentName.test.tsx` |
68 | | -- Run a single test: `npx jest --testPathPattern=LineChart` |
69 | | -- Integration tests: `npm run test:dist` (requires build first) |
| 112 | +- Unit and integration tests live next to source files as `*.test.{ts,tsx,jsx}`. |
| 113 | +- Use `npx vitest run path/to/file.test.tsx` for focused runs. |
| 114 | +- Browser and visual tests live under `integration-tests`. |
| 115 | +- Build dist before Playwright when the test expects packaged output. |
| 116 | +- Exact test counts change as coverage grows; use current command output rather than hard-coded counts. |
70 | 117 |
|
71 | | -## Code style |
| 118 | +## Code Style |
72 | 119 |
|
73 | | -- TypeScript, no `any` in new code where avoidable |
74 | | -- Prettier handles formatting (see `.prettierrc`) |
75 | | -- ESLint for linting (`npm run lint`) |
76 | | -- No semicolons, double quotes, trailing commas |
| 120 | +- TypeScript is preferred for new source files. |
| 121 | +- Avoid `any` in new code unless there is a clear boundary reason. |
| 122 | +- Prettier and ESLint define formatting and lint rules. |
| 123 | +- Existing style uses no semicolons and double quotes. |
77 | 124 |
|
78 | | -## Publishing releases |
| 125 | +## Before Opening a PR |
| 126 | + |
| 127 | +Run the checks that match the change. For shared library changes, public API changes, release work, generated AI contracts, or SSR behavior, `npm run release:check` is the best local approximation of CI. |
| 128 | + |
| 129 | +For docs-only changes, run at least: |
| 130 | + |
| 131 | +```bash |
| 132 | +npm run check:claude-md-coverage |
| 133 | +npm run check:ai-contracts |
| 134 | +npm run check:docs-routes |
| 135 | +``` |
79 | 136 |
|
80 | | -Releases are automated via GitHub Actions. The workflow: |
| 137 | +Add `npm run website:build` when routes, examples, generated API docs, or public docs pages change. |
81 | 138 |
|
82 | | -1. Update `version` in `package.json` |
83 | | -2. Update `CHANGELOG.md` |
84 | | -3. Commit: `git commit -m "chore(release): v3.0.0"` |
85 | | -4. Tag: `git tag v3.0.0` |
86 | | -5. Push: `git push && git push --tags` |
87 | | -6. CI builds, tests, and publishes to npm automatically |
| 139 | +## Publishing Releases |
88 | 140 |
|
89 | | -The `NPM_TOKEN` secret must be configured in the repo's GitHub settings. |
| 141 | +Releases are automated through GitHub Actions and npm credentials configured in the repository. Release PRs should update `package.json`, `CHANGELOG.md`, and any generated artifacts required by the release checks before tagging. |
90 | 142 |
|
91 | 143 | ## Community |
92 | 144 |
|
93 | | -This project follows the nteract |
94 | | -[Code of Conduct](https://github.com/nteract/nteract/blob/main/CODE_OF_CONDUCT.md). |
| 145 | +This project follows the nteract [Code of Conduct](https://github.com/nteract/nteract/blob/main/CODE_OF_CONDUCT.md). |
0 commit comments