- Overview
- Why This Template?
- Features
- Architecture
- Quick Start
- Project Structure
- Development Guide
- Documentation
- License
This template provides a complete, production-ready foundation for building decentralized applications on the Midnight blockchain. It showcases the full integration stack from smart contracts to frontend, with a focus on developer experience and best practices.
This template uses a simple counter contract to demonstrate the core patterns you'll need for any Midnight dApp:
- β Smart contract development in Compact
- β Cross-platform API (Browser + Node.js)
- β React frontend with wallet integration
- β Interactive CLI tools
- β Comprehensive testing setup
- β Turborepo monorepo configuration
Building a Midnight dApp from scratch requires understanding:
- Compact smart contracts
- Zero-knowledge proof generation
- Wallet integration (Browser + Node.js)
- Cross-platform provider configuration
- Complex build tooling and monorepo setup
This template gives you a working reference implementation that you can:
- Fork and start building immediately
- Learn from clean, documented code
- Extend without fighting the existing architecture
Perfect for: New Midnight developers, hackathons, proof-of-concepts, and production dApps.
- Zero-knowledge proof generation
- Private state management
- Public ledger state
- Frontend: React + Tailwind CSS with Midnight Lace wallet
- Backend: Node.js CLI with comprehensive testing
- Contract: Compact smart contract with type-safe bindings
- Single API codebase works in both browser and Node.js
- Environment abstraction layer
- Platform-specific optimizations
- Turborepo for fast, cached builds
- TypeScript everywhere
- Hot reload for development
- Comprehensive error handling
- Contract simulation tests
- API integration tests
- Type-safe test patterns
βββββββββββββββββββββββ βββββββββββββββββββββββ
β Web Frontend β β CLI Interface β
β β β β
β β’ React + Tailwind β β β’ Interactive Menu β
β β’ Wallet Connect β β β’ Contract Deploy β
β β’ Real-time State β β β’ State Queries β
βββββββββββββββββββββββ βββββββββββββββββββββββ
β β
ββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββ
β Unified API β
β β
β β’ Type-Safe β
β β’ Cross-Platform β
β β’ Provider Pattern β
βββββββββββββββββββββββ
β
βββββββββββββββββββββββ
β Counter Contract β
β β
β β’ Compact Language β
β β’ Public State β
β β’ ZK Circuits β
βββββββββββββββββββββββ
β
βββββββββββββββββββββββ
β Midnight Network β
βββββββββββββββββββββββ
- Monorepo with Turborepo: Fast, cached builds across all packages
- Unified API Layer: Single codebase for browser and Node.js
- Environment Abstraction: Platform-specific code isolated and testable
- Contract-First Design: Type safety flows from contract to UI
- Node.js v18 or higher
- Yarn v1.22+
- Midnight Lace Wallet (for web interface)
# Install dependencies
yarn install
# Build all packages
yarn buildyarn start
# Access at http://127.0.0.1:8080/# Interactive CLI with testnet
yarn cli
# Wallet options:
# 1. Create a new wallet (generates and displays seed)
# 2. Import wallet from seed (for existing wallets)
# After wallet setup:
# 1. Deploy a new counter contract
# 2. Increment counter by 1
# 3. Increment counter by custom amount
# 4. View counter value
# 5. Join an existing counter contract
# 6. Exit# Test smart contract
yarn test-contract
# Test API
yarn test-api
# Lint all packages
yarn lintmidnight-dapp-template/
βββ apps/
β βββ web/ # React web application
β βββ src/
β β βββ ui/
β β β βββ components/ # React components
β β β βββ contexts/ # State management
β β β βββ hooks/ # Custom React hooks
β β β βββ config/ # App configuration
β β βββ main.tsx # Entry point
β βββ vite.config.ts # Vite build config
β
βββ packages/
β βββ contracts/ # Smart contracts
β β βββ src/
β β β βββ counter.compact # Counter contract
β β β βββ index.ts # Contract exports
β β β βββ witnesses.ts # Witness functions
β β β βββ test/ # Contract tests
β β βββ package.json
β β
β βββ api/ # Unified API layer
β β βββ src/
β β β βββ common/ # Shared code
β β β βββ browser/ # Browser-specific
β β β βββ node/ # Node.js-specific
β β βββ package.json
β β
β βββ cli/ # CLI tools
β β βββ src/
β β β βββ cli.ts # Interactive CLI
β β βββ package.json
β β
β βββ compact/ # Contract compilation
β βββ ui/ # Shared UI components
β βββ eslint-config/ # Shared ESLint config
β βββ typescript-config/ # Shared TypeScript config
β
βββ turbo.json # Turborepo configuration
βββ package.json # Root package.json
βββ README.md # This file
The counter contract is located at packages/contracts/src/counter.compact:
export ledger counter: Counter;
export circuit increment(): [] {
counter.increment(1);
}
export circuit incrementBy(amount: Uint<32>): [] {
assert(amount > 0, "Amount must be greater than 0");
counter.increment(amount);
}
To modify the contract:
- Edit
counter.compact - Run
yarn compactto compile - Run
yarn test-contractto test - Update API types if needed
The API provides a unified interface for both browser and Node.js:
// Deploy a contract
const counterApi = await CounterAPI.deploy(providers);
// Increment the counter
await counterApi.increment();
// Get current value
const value = await counterApi.getCounter();
// Subscribe to state changes
counterApi.state$.subscribe((state) => {
console.log(`Counter: ${state.counter}`);
});Key patterns:
packages/api/src/common/- Shared logicpackages/api/src/browser/- Browser-specific (Lace wallet)packages/api/src/node/- Node.js-specific (CLI wallet)
The React app demonstrates:
- Wallet connection with Midnight Lace
- Real-time state subscriptions via RxJS
- Contract deployment and interaction
- Error handling and loading states
- Custom hooks for business logic separation
Architecture highlights:
useCounterAPIhook - Abstracts all CounterAPI logicuseMidnightWallethook - Manages wallet connection state- Component separation - UI components focus on presentation
To customize the UI:
- Edit
apps/web/src/ui/components/App.tsxfor UI - Edit
apps/web/src/ui/hooks/useCounterAPI.tsfor contract logic - Run
yarn startfor hot reload - Test in browser with Lace wallet
The CLI provides:
- Contract deployment
- Interactive operations
- State queries
- Wallet management
To add CLI commands:
- Edit
packages/cli/src/cli.ts - Add menu options and handlers
- Test with
yarn cli
- Contract Guide - Smart contract development
- API Reference - API usage and patterns
- CLI Usage - CLI commands and configuration
# Development
yarn compact # Compile smart contracts
yarn build # Build all packages
yarn start # Start web app
yarn cli # Run CLI
# Testing
yarn test-contract # Test smart contract
yarn test-api # Test API
yarn lint # Lint all packages
yarn format # Format code
# Specific builds
yarn build:contracts # Build only contracts
yarn build:api # Build only API
yarn build:cli # Build only CLI
yarn build:app # Build only web app- Add a circuit to
counter.compact - Update types in
packages/api/src/common/types.ts - Add API method in
packages/api/src/common/api.ts - Update UI/CLI to call the new method
- Add private state: Modify
witnesses.tsand contract - Add parameters: Update circuit signatures and API
- Add queries: Implement pure circuits for state reading
- Integrate external modules: Import from other contracts
Solution: Run yarn compact from the root directory. No COMPACT_PATH environment variable is required.
Issue: Node.js modules appearing in browser bundle
Solutions:
- Check Vite aliases in
apps/web/vite.config.ts - Verify import paths use environment-specific imports
- Add missing aliases or external declarations
- When adding Node.js dependencies to API, ensure they're:
- Excluded from browser builds in
optimizeDeps.exclude - Marked as external in
build.rollupOptions.external - Have browser alternatives aliased properly
- Excluded from browser builds in
Issue: "Cannot find module" in different environments
Solutions:
- Check package.json exports in
packages/api/package.json - Use correct import path (
browser-apivsnode-api) - See
packages/api/PATH_RESOLUTION.mdfor details
Issue: Cannot connect to testnet
Solutions:
- Check network configuration in
packages/cli/*.yml - Verify proof server availability
- Use
yarn cli(defaults to external proof server) - Check if testnet is working:
curl -s https://rpc.testnet-02.midnight.network \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"chain_getHeader","params":[],"id":1}' | jq '.result.number'If this returns an error or the same block number after waiting a few minutes, the testnet may be down. Check the Midnight Discord for status updates.
This project uses dual licensing:
-
π¨ Web App & Smart Contracts - MIT License
- Freely usable in commercial and proprietary projects
- Perfect for building your own dApps
-
π§ Infrastructure (API, CLI, tooling) - GPL-3.0
- Contains architectural patterns from the original midnight-kitties project
- Derivatives must remain open source
The web app and smart contracts are original work you'll want to customize for your product. We use MIT so you can use them freely without restrictions.
The underlying infrastructure (environment abstraction, provider patterns, build configs) is derived from midnight-kitties and respects its GPL-3.0 license.
See LICENSE for complete details and attribution.
Built with β€οΈ for the Midnight community
Documentation β’ Twitter