Grida is a open source Design tool that aims to provide high-performance, configurable canvas-based editor.
Mission
- Build a high performance interactive graphics engine and its ecosystem
Currently, we have below features / modules.
- canvas
- forms
- database
When entering an unfamiliar directory, always check for
README.mdandAGENTS.mdfirst. These files contain domain-specific context, conventions, and constraints that override general assumptions. The table below lists the known ones, but sub-directories and individual packages may have their own as well.
| directory | README | AGENTS | notes |
|---|---|---|---|
| docs | - | docs/AGENTS.md |
the docs directory |
| format | format/README.md |
format/AGENTS.md |
grida file formats & schemas |
| editor | - | editor/AGENTS.md |
the editor directory |
| crates | - | - | the rust crates directory |
| packages | - | - | shared packages |
| desktop | desktop/README.md |
- | the electron desktop app |
| supabase | supabase/README.md |
supabase/AGENTS.md |
the supabase project |
| apps | - | - | micro sites for Grida |
| library | library/README.md |
- | hosted library workers |
| jobs | jobs/README.md |
- | hosted jobs |
| test | test/README.md |
test/AGENTS.md |
manual test cases & UX behavior specs |
| .legacy | - | - | will be removed (fully ignore this directory) |
Languages
- Node.js 24 LTS - main runtime for most apps
- TypeScript 5 - main language for most apps
- Python 3.12 - partially used for tasks / jobs, that are independent, e.g.
/library - Deno - partially used for tasks / jobs, that shares the codebase, e.g.
/jobs - Rust (2024 edition) - used for wasm builds, mostly for graphics core.
Database
Grida heavily relies on Supabase (PostgreSQL).
- Supabase
Web
- React.js 19
- Next.js 16
UI
- Tailwind CSS 4
- Shadcn UI
- Lucide / Radix Icons
Graphics Backend
- DOM - plain dom as canvas - for website builder canvas. (binded with react)
- Skia - the graphics backend - for 2D graphics. (binded with skia-safe)
Desktop
- electron with electron-forge
- vite
Tooling
- Turborepo - monorepo build orchestration
- oxfmt (oxc) - code formatter (JS/TS)
- oxlint (oxc) - linter (JS/TS), replaces ESLint
- cargo fmt (rustfmt) - code formatter (Rust)
- just - command runner (see
justfileat repo root) - lefthook - git hooks (
lefthook.yml)
Documentation files are located in the ./docs directory.
This directory contains the docs as-is, the deployment of the docs are handled by apps/docs. A docusaurus project that syncs the docs content to its directory. When writing docs, the root ./docs directory is the source of truth.
See docs/AGENTS.md for the docs contribution scope (we only actively maintain docs/wg/** and docs/reference/**).
When linking docs to editor pages, prefer universal routing (https://grida.co/_/<path>). See docs/wg/platform/universal-docs-routing.md.
Importance: High
monorepo rust crates.
The rust implementation of the Grida Canvas. this is rapidly under development. - it will serve as our new rendering backend once it is stable.
Importance: Very high
The editor is a monorepo nextjs project that contains the codebase for the editor.
grida.co and [tenant].grida.site domains are connected.
/editor/appthe nextjs app directory, no shared root layout, each has its own root layout.(api)/(public)/v1contains the public api routes.(api)/privatecontains the private, editor only api routes.(auth)contains the auth specific flow routes. do not modify.(insiders)contains the insiders, local-only routes. e.g. Grida does not allow email signups, the insiders locally can.(library)contains the Grida Library (open assets) specific pages.(preview)contains the embed-purpose slave preview pages, maily used by the playground.(site)similar to(www), but contains pages that are not seo-purpose.(tenant)contains the tenant-site rendered pages.(tools)contains the standalone tools and editor pages, like playground, etc.(workbench)contains the workbench, the main editor page.(workspace)similar to(workbench), but contains the dashboard, not the actual editor.(www)contains the landing page, seo-purpose static pages. when to add new webpages, this is the root directory.sitemap.tscontains the sitemap.xml generator. this contains the sitemap for the public pages, usually under(www)directory.
/wwwcontains the landing page specific components./componentscontains the generally reusable components./components/uicontains the shadcn ui components./scaffoldscontains the feature-specific larger components / pages / editors./libcontains the core, strictly designed modules with non-opinionated, reusable, and stable modules. - all of them must be worthy to be promoted to<root>/packagesdirectory./grida-*aims to isolate the modules to a domain-specific scope. once reasonably well-defined, they will be promoted to<root>/packagesdirectory.
Importance: Low
The desktop is a electron app that runs a hosted version of the editor. we choose this way to make things maintainable. We choose electron for stability, consistency, and relies on chrome-specific functions.
Importance: Very high
We use supabase for database, auth, and storage.
-
/supabase
/functions- we are not using supabase edge functions.- /migrations - applied migration sqls.
- /schema - human friendly organized schema sqls.
-
To run supabase locally, follow the instructions in the supabase docs.
-
To suggest a new feature, use
supabase migration new <feature-name>. -
To apply migrations, use
supabase migration up.
In any cases, bots will never have access to the main (production) database.
Importance: Low
Jobs are hosted on railway.com
Importance: Low
Library workers are hosted on railway.com
Importance: High
monorepo node packages
/packages/grida-canvas-*
Packages that powers the canvas. (some are published to npm, some are not)
Since our project is in a rapid development, some large modules still lives under the /editor directory. Which will progressively move to /packages directory, once things are sorted out and fully defined with the good models.
For each individual package, refer to the README of its own.
We use turborepo (except few isolated packages).
Manual test cases for UX behaviors that are impractical to automate live in test/. When fixing a UX bug or implementing interaction-heavy features, check for relevant TCs there and add new ones when appropriate (see test/AGENTS.md).
To run test, build, and dev, use below commands.
# format the entire repo (JS/TS + Rust) — run this regularly, especially before committing
just fmt
# run tests (all, not recommended. requires crates build)
turbo test
# run tests for packages
turbo test --filter='./packages/*'
# build packages (required for typecheck for its dependants)
turbo build --filter='./packages/*'
# build packages in watch mode
pnpm dev:packages
# run tests except for rust crates
turbo test --filter='!./crates/*'
# run lint (oxlint)
pnpm lint
# run build (all, not recommended)
turbo build
# run dev
turbo dev
# run typecheck (always run)
turbo typecheck # fallback when build fails due to network issues (nextjs package might fail due to font fetching issues)
# for crates specific tests
cargo test
# for crates specific check
cargo check
# for crates (with long build time deps, e.g. skia)
cargo clippy --no-deps
# for crates specific build
cargo build
# format crates only
cargo fmt --allImportant for agents: Formatting and linting run automatically on commit via lefthook pre-commit hooks (
oxfmt,oxlint,cargo fmt,clippy). You can also runjust fmtmanually. Bothoxfmt(JS/TS) andcargo fmt(Rust) are enforced in CI — PRs will fail format checks if code is not formatted.
Note: typecheck still rely on packages build artifacts, so it will fail if the build fails.
To handle this, you can build the /packages/*, then run typecheck.
pnpm typecheck depends on compiled packages and the editor's Next.js env
file. After cloning the repo or installing dependencies, run the following
steps before executing pnpm typecheck:
pnpm install
# build shared packages and the wasm bundle
pnpm build:packages
pnpm turbo build --filter @grida/canvas-wasm
# finally, run the repository-wide typecheck
pnpm typecheck
# run test (only packages and editor)
pnpm turbo test --filter='./packages/*' --filter=editorThis project supports git worktrees. When working in a fresh worktree, run the following setup:
# 1. Initialize git submodules (e.g. emsdk for WASM builds)
git submodule update --init
# 2. Install node dependencies
pnpm install- Cargo / Rust works out of the box — the
target/directory is resolved via relative paths and shared across worktrees. - Rustup targets (e.g.
wasm32-unknown-emscripten) are installed globally and do not need per-worktree setup.