A complete starter template for building Calimero applications with a TypeScript/JavaScript logic and React frontend. This repository demonstrates how to build a key-value store application on the Calimero network.
The architecture is designed to be easily extensible—modify the logic in logic/src/index.ts and update the frontend in app/src/ to match your needs.
This repository contains two independent projects that work together:
kv-store-js/
├── logic/ # TypeScript smart (compiled to WASM)
│ ├── src/
│ │ └── index.ts # implementation
│ ├── res/ # Build output (WASM files, gitignored)
│ ├── package.json # dependencies
│ └── build.sh # Build script
│
├── app/ # React frontend (Vite)
│ ├── src/
│ │ ├── App.tsx # Main app with CalimeroProvider
│ │ ├── api/ # Generated TypeScript client (from ABI)
│ │ ├── pages/ # React pages (home, login)
│ │ └── features/ # Feature modules
│ └── package.json # Frontend dependencies
│
├── scripts/ # Development automation scripts
│ ├── on-res-change.mjs # File watcher handler
│ ├── sync-wasm.sh # Sync WASM to Merobox nodes
│ └── registry-sync.sh # Sync WASM to local registry
│
├── workflows/ # Merobox workflow definitions
│ └── workflow-example.yml # Example local network setup
│
└── package.json # Root scripts and workspace config
-
Logic Layer (
logic/): TypeScript smart using@calimero-network/calimero-sdk-js- Written in TypeScript with decorators (
@State,@Logic,@View,@Event) - Compiled to WebAssembly (WASM) using the Calimero SDK
- Outputs:
logic/res/service.wasm
- Written in TypeScript with decorators (
-
Frontend Layer (
app/): React application using@calimero-network/calimero-client- Uses generated TypeScript client from ABI
- Provides UI for interacting with the
- Handles authentication and connection to Calimero nodes
-
Development Tools: Automated watchers and sync scripts for seamless development
Before you begin, ensure you have:
- Node.js 18+ with WASI support
- pnpm (or npm) - Package manager
- Access to a Calimero node - Either:
- Local network via Merobox (recommended for development)
- Remote Calimero node URL
# Install root dependencies
pnpm install
# Install app dependencies
pnpm run app:installpnpm run logic:buildThis compiles the TypeScript to logic/res/service.wasm.
Option A: With Local Network (Recommended)
# Terminal 1: Start local Calimero network
pnpm run network:bootstrap
# Terminal 2: Start dev server with file watchers
pnpm run app:devOption B: Connect to Existing Node
# Just start the dev server
pnpm run app:devThen open http://localhost:5173 in your browser and connect to your Calimero node.
-
Start the development environment:
pnpm run app:dev
This starts:
- Vite dev server (frontend) on
http://localhost:5173 - File watcher for
logic/res/directory
- Vite dev server (frontend) on
-
Edit your :
- Modify
logic/src/index.ts - Rebuild:
pnpm run logic:build - The watcher automatically detects changes and syncs WASM files
- Modify
-
Update the frontend:
- Edit files in
app/src/ - Changes hot-reload automatically
- Edit files in
Root-level scripts (run from repository root):
| Script | Description |
|---|---|
pnpm run logic:build |
Build the TypeScript to WASM |
pnpm run logic:clean |
Clean build artifacts |
pnpm run logic:watch |
Watch logic/res/ for changes |
pnpm run logic:sync |
Sync WASM to Merobox nodes |
pnpm run app:dev |
Start dev server + file watcher |
pnpm run app:build |
Build production frontend |
pnpm run app:generate-client |
Generate TypeScript client from ABI |
pnpm run network:bootstrap |
Start local network via Merobox |
Logic scripts (run from logic/ directory):
| Script | Description |
|---|---|
pnpm build |
Build (called by logic:build) |
pnpm clean |
Clean build output |
App scripts (run from app/ directory):
| Script | Description |
|---|---|
pnpm dev |
Start Vite dev server |
pnpm build |
Build for production |
pnpm preview |
Preview production build |
The logic:watch script monitors logic/res/ for changes:
- On
*.wasmchange: Automatically syncs to Merobox nodes (ifSYNC_MEROBOX !== 'false') - On
abi.jsonchange: Logs the change (ABI codegen can be triggered manually if needed)
Note: The ABI is typically generated during the build process. If you need to regenerate the TypeScript client, run
pnpm run app:generate-client.
The KV Store provides the following operations:
set(key: string, value: string): void- Set a key-value pair- Emits
Insertedevent if key is new - Emits
Updatedevent if key exists
- Emits
remove(key: string): string- Remove a key, returns the removed value- Emits
Removedevent
- Emits
clear(): void- Clear all entries- Emits
Clearedevent
- Emits
get(key: string): string | null- Get value by key (returns null if not found)get_unchecked(key: string): string- Get value by key (throws if not found)get_result(key: string): string | {error: {kind: "NotFound", data: string}}- Get value with error resultentries(): Record<string, string>- Get all key-value pairs as JSONlen(): number- Get the number of entries
The emits the following events:
Inserted(key: string, value: string)- New key-value pair addedUpdated(key: string, value: string)- Existing key-value pair updatedRemoved(key: string)- Key-value pair removedCleared()- All entries cleared
The app connects to Calimero in app/src/App.tsx:
<CalimeroProvider
packageName="com.calimero.kvstore"
registryUrl="https://apps.calimero.network"
mode={AppMode.SingleContext}
>
{/* Your app */}
</CalimeroProvider>The workflows/workflow-example.yml file defines the Merobox workflow for local development. It:
- Creates 2 local Calimero nodes
- Installs the on node 1
- Creates a context
- Sets up node 2 as a member
- Demonstrates calls and state synchronization
"WASM file not found"
# Ensure you've built the first
pnpm run logic:build
# Check that logic/res/service.wasm exists"Missing dependencies"
# Install root dependencies
pnpm install
# Install app dependencies
pnpm run app:install"Watcher not working"
# Ensure dev dependencies are installed
pnpm add -D concurrently chokidar-cli
# Restart the dev server
pnpm run app:dev"ABI codegen fails"
# Ensure ABI file exists (generated during build)
# Manually regenerate client if needed
pnpm run app:generate-client"Cannot connect to node"
- Verify your Calimero node is running
- Check the node URL in
app/src/App.tsxor connection settings - For local development, ensure Merobox network is running:
pnpm run network:bootstrap
"Merobox network fails to start"
- Ensure Docker is running (Merobox uses Docker)
- Check that ports are not in use
- Review
workflows/workflow-example.ymlfor configuration
This is a starter template. Feel free to:
- Fork and customize for your own projects
- Submit improvements via pull requests
- Report issues or suggest enhancements