Français | English
Vite-based React and TypeScript boilerplate for creating Grist custom widgets.
This boilerplate provides a robust foundation for building Grist custom widgets. By leveraging Vite.js for near-instant Hot Module Replacement (HMR) and TypeScript for end-to-end type safety, it ensures a superior developer experience. It also includes a dockerized Grist environment, allowing you to test widgets in a real Grist instance locally with zero manual setup. The architecture is highly flexible: it automatically manages your widget manifest and supports two build strategies (Standard vite for optimized assets spliting or SPA (single page application)) for your deployment needs.
Main features:
- Provide a ready‑to‑use environment for Grist custom widget developers
- Simplify local development, building, and previewing through dedicated scripts (
dev,buildandpreview). - Enable easy customization via the
gristfield inpackage.json.
- Docker (>= 28.4)
- Docker Compose (>= 2.39)
- Node.js (>= 20.20.x)
- pnpm (>= 10.28.x)
-
Clone the repository
git clone https://github.com/6i-software/grist-widget-vite-react-ts-template.git
-
Install dependencies using the pnpm package manager:
pnpm install
-
Configure your widget by editing the
gristfield in the rootpackage.json. This makes the widget available in your custom Grist widget catalog./** ./package.json **/ { "name": "@badi/grist-widget-title", "version": "0.0.1", "description": "A Grist widget for ...", "gristWidget": { "name": "Title widget (dev)", "url": "http://localhost:5173/index.html", "widgetId": "@badi/grist-widget-title", "published": true, "accessLevel": "none", "renderAfterReady": true, "description": "Lorem ipsum dolor sit amet.", "isGristLabsMaintained": false, "authors": [{"name": "v20100v", "url": "https://github.com/v20100v"}] } }
-
Start the local Grist development environment
pnpm dev
Tip: For more detailed output during startup, you can use the
--verboseor-vflag in commandpnpm dev --verbose. This is helpful for troubleshooting container orchestration or server initialization.This command launches a Grist Docker container at http://localhost:8484 and a Vite dev server at http://localhost:5173, which also serves the widget manifest at http://localhost:5173/manifest.json.
— Launch Grist custom widget development environmentTip: To separate vite logs and docker log, open two terminals and run:
- Terminal 1:
pnpm grist-up ; pnpm grist-logs - Terminal 2:
pnpm vite --debug
- Terminal 1:
-
Check local manifest availability. Ensure your widget is correctly exposed by checking the dynamically generated manifest.json at http://localhost:5173/manifest.json.
-
Use the widget into local Grist. Once the dev environment is running, open the local Grist instance at http://localhost:8484 in order to create a new document and add into a custom view.
— Local widget load into Grist instance localNote: You will notice that the local widget declared in the manifest.json (served at
:5173) is accessible. It appears automatically because theGRIST_WIDGET_LIST_URLdocker environment variable is configured to point Grist toward your local manifest. -
And there’s the final widget! Thanks to HMR (Hot Module Replacement) provides by Vite.js, your code changes are reflected instantly without a full page refresh. Unlike standard Live Reload, HMR updates only the modified modules. This preserves your widget’s current state and data, ensuring a seamless and lightning-fast development workflow.
The build process compiles your TypeScript source code and assets into a production-ready widget, optimizing for both performance and compatibility. It leverages Vite.js for asset bundling and the React Compiler for optimized rendering. The final artifacts are organized within the dist/ folder, ready for deployment.
pnpm buildTip: For more detailed output during startup, you can use the
--verboseor-vflag in commandpnpm build --verbose.
This tool supports two distinct architectural strategies. You can toggle between them using CLI flags or the VITE_BUILD_STRATEGY environment variable.
| Strategy | Command | Description |
|---|---|---|
| Standard | pnpm build --standard |
Default. Implements advanced code-splitting. Third-party libraries (like React) are bundled into separate vendor chunks to maximize browser cache hits and reduce load times. |
| SPA | pnpm build --spa |
To build a SPA (Single Page Application). It Utilizes vite-plugin-singlefile to inline all Javascript and CSS directly into a single HTML file. |
To determine which strategy to use, the build.js tools follows this hierarchy:
- CLI Shorthand flags (e.g.,
--spaor--standard) - Explicit CLI arguments (e.g.,
--VITE_BUILD_STRATEGY=SPA) - Environment variables (via
.envor system shell) - Use the default fallback (
STANDARD)
When you trigger a build, the following lifecycle events occur:
- Manifest Generation: The
generateGristManifestPluginextracts yourgristconfiguration frompackage.jsonto create a standard Gristmanifest.jsonin the public directory[cite: 5]. - Versioned Output: To prevent deployment conflicts, assets are placed in a versioned subdirectory based on the widget version, such as
dist/v1.0.0/. - Metadata post-processing: Once the bundle is closed, the
updateGristManifestDistPlugininjects the current version, and alastUpdatedAtISO timestamp.
Preview mode allows you to test the production-ready version of your widget (the compiled files in /dist) within a live Grist instance before deployment.
pnpm previewTip: For more detailed output during startup, you can use the
--verboseor-vflag in commandpnpm preview --verbose.
This command orchestrates four key stages:
-
Production build: Automatically triggers a build using
NODE_ENV: productionandPREVIEW_MODE: trueenvironment variables to ensure your assets are compiled specifically for the preview environment. -
Vite preview server: Starts a local web server on port 4173 (in strict mode) to serve the static files directly from the
dist/v.{x.y.z}/directory. -
Dockerized Grist: Launches a Grist container pre-configured to automatically recognize the production manifest stores in
dist/v.{x.y.z}/manifest.json -
Dynamic Linking: Injects the production manifest URL (http://host.docker.internal:4173/manifest.json) into the Grist environment via the
GRIST_WIDGET_LIST_URLvariable, making your widget instantly available in the Grist custom widget catalog.
Ideas, bug reports, reports a typo in documentation, comments, pull-request & Github stars are always welcome !
Release under MIT License,
Copyright (c) 2026 by 2o1oo vb20100bv@gmail.com
