Modular form builder & renderer for React.
eSheet is a TypeScript-first Nx monorepo providing composable packages for embedding a visual form builder and renderer into any React application — no lock-in, no required backend.
- Live Demo — builder + renderer playground
- Documentation — full API & usage docs
| Package | Description |
|---|---|
@esheet/core |
Zod schemas, Zustand stores, conditional logic engine — no React |
@esheet/fields |
19 built-in field components (text, choice, scale, matrix, rich, layout) |
@esheet/builder |
Drag-and-drop visual form builder (<EsheetBuilder />) |
@esheet/renderer |
Read-only React form renderer (<EsheetRenderer />) with auto-detection of SurveyJS/MCP |
@esheet/adapters |
SurveyJS ↔ eSheet converters, MCP import/export, AI system prompt |
@esheet/renderer-standalone |
Standalone mount API and global registration |
@esheet/renderer-blaze |
Meteor Blaze template integration |
All packages are versioned together and published to npm under the @esheet scope.
# Builder (includes fields + core as peer deps)
npm install @esheet/builder
# Renderer only
npm install @esheet/renderer
# Optional integrations
npm install @esheet/renderer-standalone
npm install @esheet/renderer-blazeimport { EsheetBuilder } from '@esheet/builder';
import '@esheet/builder/dist/index.css';
function App() {
const [definition, setDefinition] = useState(emptyForm);
return <EsheetBuilder definition={definition} onChange={setDefinition} />;
}import { EsheetRenderer, EsheetRendererHandle } from '@esheet/renderer';
function App() {
const rendererRef = useRef<EsheetRendererHandle>(null);
return (
<>
<EsheetRenderer formDataInput={definition} ref={rendererRef} />
<button onClick={() => console.log(rendererRef.current?.getResponse())}>
Submit
</button>
</>
);
}mSheet/
├── packages/
│ ├── core/ # @esheet/core — types, stores, logic (no React)
│ ├── fields/ # @esheet/fields — 19 field components
│ ├── builder/ # @esheet/builder — visual builder UI
│ ├── renderer/ # @esheet/renderer — form renderer (auto-detects SurveyJS/MCP)
│ ├── adapters/ # @esheet/adapters — SurveyJS/MCP converters, AI prompt
│ ├── renderer-standalone/ # @esheet/renderer-standalone — standalone integration
│ └── renderer-blaze/ # @esheet/renderer-blaze — blaze integration
└── apps/
├── demo/ # Vite playground (builder + renderer routes)
└── docs/ # Docusaurus documentation site
@esheet/core
↑
@esheet/fields @esheet/adapters
↑ ↑ ↑
@esheet/builder @esheet/renderer
↑ ↑
@esheet/renderer-standalone @esheet/renderer-blaze
This workspace uses Nx. All tasks run through Nx — do not invoke tsc, vite, or vitest directly.
- Node.js ≥ 20
- npm workspaces (builtin)
npm install# Build all packages
npx nx run-many -t build
# Run tests across all packages
npx nx run-many -t test
# Lint all projects
npx nx run-many -t lint
# Type-check all projects
npx nx run-many -t typecheck
# Serve the demo app locally
npx nx serve demo
# Run only tasks affected by your changes
npx nx affected -t lint,test,build# Build a single package
npx nx build @esheet/core
npx nx build @esheet/builderBefore committing, test your changes locally using gh act. This validates formatting, linting, tests, and (optionally) deployment.
Quick commands:
# Test CI workflow (lint, test, build, typecheck)
gh act push -W .github/workflows/ci.yml --pull=false
# Test release workflow (all checks + dry-run release — does not publish)
gh act push -W .github/workflows/release.yml --pull=false
# Test PR title validation
printf '{"pull_request":{"title":"fix(core): my change","number":1}}\n' > /tmp/pr-event.json
gh act pull_request -e /tmp/pr-event.json -W .github/workflows/pr-title-check.yml --pull=falseFor full setup instructions, deploy testing against a local Docker container, and troubleshooting, see .github/workflows/TESTING-LOCALLY.md.
npx nx serve demo
# → http://localhost:4200npx nx serve docs
# → http://localhost:3000npx nx run-many -t dev -p app-*
# Demo → http://localhost:4200
# Docs → http://localhost:3000This runs both local dev servers at the same time in one terminal. Use Ctrl+C to stop both.
chmod +x deploy/scripts/manual/setup-nginx.sh
./deploy/scripts/manual/setup-nginx.sh
chmod +x deploy/scripts/workflow/atomic-deploy.sh
./deploy/scripts/workflow/atomic-deploy.sh- Nginx config in repo:
deploy/nginx/default.conf - Deploy script in repo:
deploy/scripts/workflow/atomic-deploy.sh - Setup helper in repo:
deploy/scripts/manual/setup-nginx.sh - Runbook in repo:
deploy/RUNBOOK-nginx-atomic.md
Cloudflare Pages publishes the same combined URL layout as the Nginx deployment:
- Documentation at
/ - Demo at
/demo/
Use npm run build:cf as the build command and dist as the output directory. See the Cloudflare Pages runbook for the complete project settings, environment variables, routing behavior, and verification steps.
Packages are versioned together using nx release with conventional commits.
| Commit prefix | Version bump |
|---|---|
fix: |
patch |
feat: |
minor |
feat!: or BREAKING CHANGE: |
major |
# Preview what would change (no files written)
npx nx release --dry-run
# First-ever release (before any git tag exists)
npx nx release --first-release
# Subsequent releases (bump auto-determined from commits since last tag)
npx nx releaseA GitHub Release and CHANGELOG.md are generated automatically. Set GITHUB_TOKEN in your environment before running nx release to enable GitHub Release creation.
- Fork and clone the repo
npm install- Create a branch:
git checkout -b feat/my-feature - Make changes — run
npx nx affected -t lint,test,buildbefore committing - Use conventional commits in your commit messages
- Open a pull request
MIT © MIE