Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
### Context
<!--- Why is this change required? What problem does it solve? -->

### Types of changes
<!--- Put an `x` in the boxes that apply -->
- [ ] New example
- [ ] Update to an existing example
- [ ] README / documentation change
- [ ] Demo runner (`runner/`) change
- [ ] CI / tooling change

### How was this verified?
<!--- e.g. "ran `pnpm build` and `pnpm dev` in examples/react", a live demo link, a screenshot -->

### Checklist
- [ ] New/renamed example: added to `runner/config/frameworks.json` (see [CONTRIBUTING.md](CONTRIBUTING.md)); otherwise it won't appear on demos.handsontable.com
- [ ] New example: added a row to the tables in [README.md](README.md)
- [ ] Ran `pnpm build` (and `pnpm dev`) in the affected example/server-example locally

### Related issue(s):
1.
22 changes: 22 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# AGENTS.md, handsontable/examples

This repository holds runnable Handsontable example projects (`examples/`,
`server-examples/`) and the self-hosted demo runner behind
demos.handsontable.com (`runner/`, see [`runner/AGENTS.md`](./runner/AGENTS.md)
for that subsystem specifically).

## Adding or changing an example

Follow [CONTRIBUTING.md](./CONTRIBUTING.md), in particular registering a new
example in `runner/config/frameworks.json` so it appears on the live demo
site. Skipping that step fails silently (no error, the example just never
shows up on demos.handsontable.com), so don't assume it's covered by CI
passing.

## Opening a pull request

Always fill in [`.github/PULL_REQUEST_TEMPLATE.md`](./.github/PULL_REQUEST_TEMPLATE.md),
including its Context, Types of changes, How was this verified, Checklist, and
Related issue(s) sections. Do not leave GitHub's default blank PR body, and do
not compose a PR description that skips the template. This applies equally to
PRs opened by an AI agent and PRs opened by a person.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
47 changes: 47 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Contributing to handsontable/examples

Thanks for wanting to add or improve an example.

## Adding a new example

1. Create `examples/<name>/` (or `server-examples/<name>/`) as a self-contained
project: its own `package.json`, its own lockfile, its own README describing
what it shows. Use an existing example's README as the template rather than
starting from scratch, e.g. [`examples/react/README.md`](./examples/react/README.md).
2. Give it a `build` script and commit a `pnpm-lock.yaml`.
[`.github/workflows/examples-build.yml`](./.github/workflows/examples-build.yml)
discovers example folders at CI runtime by scanning for exactly that
combination. No workflow file needs editing to get build coverage.
3. Add a row for it to the relevant table in [README.md](./README.md).

### Register it with the live demo runner (easy to miss)

A new `examples/<name>/` folder does **not** automatically show up on
[demos.handsontable.com](https://demos.handsontable.com). The demo runner only
imports frameworks that have a matching key in
[`runner/config/frameworks.json`](./runner/config/frameworks.json).
`runner/pipeline/import.mjs` reads that file's keys, not the `examples/`
directory. Miss this step and the folder still builds fine in CI, but stays
invisible on the live demo site: no error, it just never appears.

- Add an entry for your example to `runner/config/frameworks.json` (tier,
engine/container, entry file, dev/build commands, etc.), copying the shape
of a similar existing entry.
- If it's a Tier-2 (container-based, e.g. meta-framework) example, also
regenerate the container assets: `node runner/scripts/prepare-container.mjs`.
- The demo catalog then regenerates automatically the next time a push to
`master` touches `examples/**`
([`.github/workflows/import-starters.yml`](./.github/workflows/import-starters.yml)
opens a `chore/starter-example-buckets` PR), or you can run it locally from
`runner/`: `node pipeline/import.mjs`.

## Updating an existing example

Same rules apply: keep it self-contained, keep its README accurate, and
re-run `node pipeline/import.mjs` (or push to `master`) if you changed anything
the runner reads from `frameworks.json`.

## Pull requests

Fill in `.github/PULL_REQUEST_TEMPLATE.md` when you open the PR, in particular
the `frameworks.json` checklist item; that's the step people forget.
89 changes: 55 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,60 @@
# Handsontable examples

Runnable code examples for [Handsontable](https://handsontable.com), the JavaScript
data grid. Every example here is a real, self-contained project you can clone, run,
<div align="center">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/handsontable/handsontable/develop/resources/handsontable-logo-black.svg"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/handsontable/handsontable/develop/resources/handsontable-logo-white.svg"/>
<img width="280" alt="Logo of Handsontable data grid" src="https://raw.githubusercontent.com/handsontable/handsontable/develop/resources/handsontable-logo-black.svg"/>
</picture>
<h3>Runnable code examples for the Handsontable JavaScript data grid.</h3>

<a href="https://handsontable.com">Website</a>
&nbsp;•&nbsp;
<a href="https://handsontable.com/docs">Documentation</a>
&nbsp;•&nbsp;
<a href="https://demos.handsontable.com">Live demos</a>
&nbsp;•&nbsp;
<a href="https://github.com/handsontable/handsontable/discussions">Community</a>
</div>

<br>

Every example here is a real, self-contained project you can clone, run,
and copy into your own codebase.

The same examples power the live demos in the
[Handsontable documentation](https://handsontable.com/docs) and at
**[demos.handsontable.com](https://demos.handsontable.com)**, where you can open any
of them in the browser, edit the code, switch the Handsontable version, and share a
permanent link — no install needed.
permanent link. No install needed.

## Client examples

Each folder in [`examples/`](./examples) is an independent project with its own
`package.json` and lockfile. Install and run one on its own; there is no root
install step.

| Example | What it shows |
|---------|---------------|
| [`example1`](./examples/example1) | Vanilla TypeScript (Vite)the general-purpose feature tour |
| [`javascript`](./examples/javascript) | Plain JavaScript (Vite) |
| [`typescript`](./examples/typescript) | TypeScript (Vite) |
| [`react`](./examples/react) | React with TypeScript (Vite) |
| [`react-js`](./examples/react-js) | React with JavaScript (Vite) |
| [`vue`](./examples/vue) | Vue 3 (Vite) |
| [`angular`](./examples/angular) | Angular |
| [`next.js`](./examples/next.js) | Next.js, App Router |
| [`next-shadcn.js`](./examples/next-shadcn.js) | Next.js with shadcn/ui |
| [`nuxt`](./examples/nuxt) | Nuxt 3 |
| [`astro`](./examples/astro) | Astro |
| [`remix`](./examples/remix) | Remix |
| [`ant-design`](./examples/ant-design) | Handsontable themed to match Ant Design |
| [`mui`](./examples/mui) | Handsontable themed to match MUI |
| [`base-web`](./examples/base-web) | Handsontable themed to match Base Web |
| [`fluent-ui`](./examples/fluent-ui) | Handsontable themed to match Fluent UI |
| Example | What it shows | Live demo |
|---------|---------------|-----------|
| [`example1`](./examples/example1) | Vanilla TypeScript (Vite), the general-purpose feature tour | [Open](https://demos.handsontable.com/?example=example1) |
| [`javascript`](./examples/javascript) | Plain JavaScript (Vite) | [Open](https://demos.handsontable.com/?example=javascript) |
| [`typescript`](./examples/typescript) | TypeScript (Vite) | [Open](https://demos.handsontable.com/?example=typescript) |
| [`react`](./examples/react) | React with TypeScript (Vite) | [Open](https://demos.handsontable.com/?example=react) |
| [`react-js`](./examples/react-js) | React with JavaScript (Vite) | [Open](https://demos.handsontable.com/?example=react-js) |
| [`vue`](./examples/vue) | Vue 3 (Vite) | [Open](https://demos.handsontable.com/?example=vue) |
| [`angular`](./examples/angular) | Angular | [Open](https://demos.handsontable.com/?example=angular) |
| [`next.js`](./examples/next.js) | Next.js, App Router | [Open](https://demos.handsontable.com/?example=next.js) |
| [`next-shadcn.js`](./examples/next-shadcn.js) | Next.js with shadcn/ui | [Open](https://demos.handsontable.com/?example=next-shadcn.js) |
| [`nuxt`](./examples/nuxt) | Nuxt 3 | [Open](https://demos.handsontable.com/?example=nuxt) |
| [`astro`](./examples/astro) | Astro | [Open](https://demos.handsontable.com/?example=astro) |
| [`remix`](./examples/remix) | Remix | [Open](https://demos.handsontable.com/?example=remix) |
| [`ant-design`](./examples/ant-design) | Handsontable themed to match Ant Design | [Open](https://demos.handsontable.com/?example=ant-design) |
| [`mui`](./examples/mui) | Handsontable themed to match MUI | [Open](https://demos.handsontable.com/?example=mui) |
| [`base-web`](./examples/base-web) | Handsontable themed to match Base Web | [Open](https://demos.handsontable.com/?example=base-web) |
| [`fluent-ui`](./examples/fluent-ui) | Handsontable themed to match Fluent UI | [Open](https://demos.handsontable.com/?example=fluent-ui) |

## Server examples

Each folder in [`server-examples/`](./server-examples) is a full stack a backend
plus a Handsontable frontend demonstrating server-side **pagination, sorting,
Each folder in [`server-examples/`](./server-examples) is a full stack: a backend
plus a Handsontable frontend, demonstrating server-side **pagination, sorting,
filtering and CRUD** through the `dataProvider` plugin. Useful when your dataset is
too large to send to the browser at once.

Expand Down Expand Up @@ -66,7 +82,7 @@ pnpm dev # then open the URL it prints

Every example has `dev` and `build`; most also have `preview` to serve the built
output. Run `pnpm run` in an example folder to see its own scripts, and check its
README for anything specific Angular, for instance, also answers to `pnpm start`
README for anything specific. Angular, for instance, also answers to `pnpm start`
and serves on a different port.

## Copying an example to a separate repo
Expand All @@ -78,7 +94,7 @@ The examples are deliberately standalone, so this is mostly a copy:
cp -R examples/react ~/my-handsontable-app
cd ~/my-handsontable-app
```
2. Edit `package.json` set `name`, `version` and `description` to your own, and
2. Edit `package.json`: set `name`, `version` and `description` to your own, and
drop the `license` field or replace it with yours.
3. Initialise a repository and install:
```bash
Expand All @@ -98,12 +114,12 @@ with it.
**[demos.handsontable.com](https://demos.handsontable.com)** runs every example in
this repository live, in the browser:

- **Any Handsontable version** switch versions and watch the same code re-render.
- **Two runtimes behind one editor** simple examples bundle in the browser with
- **Any Handsontable version**: switch versions and watch the same code re-render.
- **Two runtimes behind one editor**: simple examples bundle in the browser with
the open-source [Sandpack](https://sandpack.codesandbox.io/) bundler; the
meta-framework examples (Next.js, Nuxt, Astro, Remix, Angular) run a real dev
server in a container, so SSR behaves the way it does locally.
- **Permanent share links** save an edited demo and link to it.
- **Permanent share links**: save an edited demo and link to it.

It also renders every code example from the Handsontable documentation guides. The
system is self-hosted and lives in [`runner/`](./runner); its
Expand All @@ -116,18 +132,23 @@ system is self-hosted and lives in [`runner/`](./runner); its
| `examples/` | The 16 client examples above. Independent projects. |
| `server-examples/` | The 7 server-side stacks above. Independent projects. |
| `runner/` | The self-hosted demo runner behind demos.handsontable.com. |
| `runner/apps/authoring/public/docs-examples/` | **Generated** — a snapshot of every documentation-guide example, imported from the docs repository. Do not edit by hand; it is the bulk of this repository's size. |
| `runner/apps/authoring/public/docs-examples/` | **Generated**: a snapshot of every documentation-guide example, imported from the docs repository. Do not edit by hand; it is the bulk of this repository's size. |

## Contributing

Want to add a new example, or fix one? See [CONTRIBUTING.md](./CONTRIBUTING.md).
There's a registration step that's easy to miss and fails silently if skipped.

## License

The example code in this repository is MIT-licensed see [LICENSE](./LICENSE). Copy
The example code in this repository is MIT-licensed, see [LICENSE](./LICENSE). Copy
it, change it, ship it.

Handsontable itself is separate, commercial software, dual-licensed:

- **Free** for non-commercial use such as teaching, academic research and
evaluation [read the license](https://github.com/handsontable/handsontable/blob/master/handsontable-non-commercial-license.pdf).
- **Commercial**, with support and maintenance see [pricing](https://handsontable.com/pricing).
evaluation: [read the license](https://github.com/handsontable/handsontable/blob/master/handsontable-non-commercial-license.pdf).
- **Commercial**, with support and maintenance: see [pricing](https://handsontable.com/pricing).

The examples install Handsontable under the non-commercial evaluation terms. Using
one as the basis for a commercial product means buying a license.
Expand Down
Loading