Anatomy of a Clarinet project
Understand the complete structure and configuration of a Clarinet project
A Clarinet project follows a carefully designed structure that separates contracts, tests, and configuration. Understanding this structure helps you organize code effectively and configure tools for optimal development workflow.
Core project layout
Every Clarinet project contains these essential directories and files:
Each component serves a specific purpose in your development workflow. Let's explore how they work together to create a complete development environment.
The project manifest
Clarinet.toml
The Clarinet.toml file is the heart of your project. It defines project metadata and tracks all contracts:
[project]name = "defi-protocol"description = "Decentralized finance protocol for Stacks"authors = ["alice@example.com"]telemetry = truerequirements = []boot_contracts = ["traits", "token", "pool"][contracts.traits]path = "contracts/traits.clar"clarity_version = 3epoch = 3.1[contracts.token]path = "contracts/token.clar"clarity_version = 3epoch = 3.1depends_on = ["traits"][contracts.pool]path = "contracts/pool.clar"clarity_version = 3epoch = 3.1depends_on = ["traits", "token"]
The manifest handles several critical functions:
- Contract registration: Every contract must be listed here
- Dependency management: Defines deployment order through
depends_on
- Version control: Specifies Clarity version and epoch for each contract
- Boot sequence: Lists contracts to deploy on
clarinet devnet start
Testing infrastructure
Package configuration
The package.json defines your testing environment and dependencies:
{"name": "my-clarinet-project","version": "1.0.0","scripts": {"test": "vitest run","test:watch": "vitest","test:coverage": "vitest run --coverage","test:report": "vitest run --reporter=verbose"},"devDependencies": {"@hirosystems/clarinet-sdk": "^2.9.0","@stacks/transactions": "^7.0.0","@types/node": "^22.10.2","chokidar-cli": "^3.0.0","typescript": "^5.7.2","vite": "^6.0.3","vitest": "^3.0.1","vitest-environment-clarinet": "^2.2.0"},"type": "module"}
Package | Purpose |
---|---|
@hirosystems/clarinet-sdk | WebAssembly-compiled Clarinet for Node.js |
@stacks/transactions | Clarity value manipulation in TypeScript |
vitest | Modern testing framework with native TypeScript support |
vitest-environment-clarinet | Simnet bootstrapping for tests |
Vitest configuration
The vitest.config.js configures the testing framework:
/// <reference types="vitest" />import { defineConfig } from "vite";import { vitestSetupFilePath, getClarinetVitestsArgv } from "@hirosystems/clarinet-sdk/vitest";export default defineConfig({test: {environment: "clarinet",pool: "forks",poolOptions: {forks: { singleFork: true }},setupFiles: [vitestSetupFilePath,"./tests/setup.ts" // Custom setup],environmentOptions: {clarinet: {...getClarinetVitestsArgv(),manifest: "./Clarinet.toml",coverageReports: ["lcov", "html"]}}}});
This configuration enables:
- Clarinet environment: Automatic
simnet
setup for each test - Single fork mode: Efficient test execution with proper isolation
- Coverage tracking: Generate reports in multiple formats
- Custom setup: Add project-specific test utilities
TypeScript configuration
The tsconfig.json provides TypeScript support:
{"compilerOptions": {"target": "ESNext","module": "ESNext","moduleResolution": "bundler","strict": true,"skipLibCheck": true,"resolveJsonModule": true,"esModuleInterop": true,"types": ["node", "vitest/globals"],"baseUrl": ".","paths": {"@/*": ["./tests/*"],"@contracts/*": ["./contracts/*"]}},"include": ["node_modules/@hirosystems/clarinet-sdk/vitest-helpers/src","tests/**/*","contracts/**/*.ts"]}
Path aliases simplify imports in tests:
import { accounts } from "@/helpers";import { TokenErrors } from "@contracts/token-types";
Network configurations
Environment settings
Each network has its own configuration file in the settings directory:
[network]name = "devnet"deployment_fee_rate = 10chain_id = 2147483648orchestrator_port = 20445bitcoin_node_p2p_port = 18444bitcoin_node_rpc_port = 18443stacks_node_p2p_port = 20444stacks_node_rpc_port = 20443stacks_api_port = 3999stacks_api_events_port = 3700bitcoin_explorer_port = 8001stacks_explorer_port = 8000postgres_port = 5432postgres_username = "postgres"postgres_password = "postgres"postgres_database = "postgres"bitcoin_node_username = "devnet"bitcoin_node_password = "devnet"miner_mnemonic = "twice kind fence tip hidden..."miner_derivation_path = "m/44'/5757'/0'/0/0"faucet_mnemonic = "shadow private easily thought..."faucet_derivation_path = "m/44'/5757'/0'/0/0"[accounts.deployer]mnemonic = "twice kind fence tip hidden..."balance = 100_000_000_000_000[accounts.wallet_1]mnemonic = "sell invite acquire kitten..."balance = 10_000_000_000_000
These settings control:
- Network ports: API, RPC, and explorer endpoints
- Account configuration: Test wallets with STX balances
- Chain parameters: Network-specific blockchain settings
Never commit mainnet private keys or mnemonics. Use environment variables for production credentials.
Common issues
Next steps
Now that you understand project structure:
- Create your first project with the quickstart guide
- Learn about contract development
- Explore testing strategies