Building on blockchain doesn’t need to be complicated. Flow was designed by application developers who wanted infrastructure that actually works for real products. No byzantine setup processes. No fighting with tooling. Just clean developer experience from day one.
This guide walks you through setting up your Flow development environment, deploying your first smart contract, and understanding the fundamentals. By the end, you’ll have working code running on Flow’s local emulator and the knowledge to build real applications.
Let’s start building.
What You’re Building Toward
Flow development centers on smart contracts. These are programs that run on the blockchain, managing data and logic that can’t be tampered with or taken down.
Flow supports two approaches:
- Cadence: Flow’s resource-oriented language, designed specifically for digital assets and consumer applications
- Solidity: Ethereum’s smart contract language, fully supported on Flow EVM since the Crescendo upgrade
This guide focuses on Cadence. It’s Flow-native, safer for asset management, and designed for the platform’s unique architecture. If you’re coming from Ethereum and prefer Solidity, Flow’s EVM documentation has you covered. But learning Cadence unlocks Flow’s full potential.
Install the Flow CLI
The Flow Command Line Interface is your primary development tool. It manages accounts, deploys contracts, runs the local blockchain emulator, sends transactions, and queries state. Everything flows through the CLI.
If you have Homebrew (Mac/Linux):
bash
brew install flow-cli
For other systems: Visit Flow CLI Installation Guide for Windows, Linux, and alternative installation methods.
Verify installation:
bash
flow version
You should see output showing your Flow CLI version. If not, check the installation guide for troubleshooting.
Set Up Your Code Editor
Install the Flow Cadence VSCode Extension from the Visual Studio Code marketplace. This provides:
- Syntax highlighting for Cadence
- Inline error checking
- Auto-completion
- Code snippets
- Direct integration with Flow CLI
You can develop without VSCode, but the extension makes Cadence development significantly smoother. If you use a different editor, syntax highlighting plugins may be available for Vim, Emacs, or others, check the Flow community resources.
Create Your First Project
Flow CLI includes project scaffolding. Initialize a new project:
bash
flow init
This generates a basic project structure with:
- flow.json: Central configuration file containing accounts, contracts, deployments, and network settings
- emulator-account.pkey: Private key for the default emulator account (safe to commit for local dev)
- Basic directory structure for contracts, transactions, and scripts
Alternatively, you can create a more complete project template:
bash
flow setup hello-world –scaffold
Select “Basic Cadence project (no dependencies)” when prompted. This creates:
/contracts: Where your Cadence smart contracts live/transactions: Code that modifies blockchain state/scripts: Code that reads blockchain state (no modifications)/tests: Test files for your contracts
The scaffold sets up a complete structure immediately usable for development.
Understanding flow.json
The
flow.json file is your project’s configuration center. It defines:Networks: Where your code deploys (emulator, testnet, mainnet)
Accounts: Which accounts exist and their keys
Contracts: Which contracts deploy where
Deployments: Network-specific deployment configurations
A basic
flow.json looks like this:json
{
“networks”: {
“emulator”: “127.0.0.1:3569”
},
“accounts”: {
“emulator-account”: {
“address”: “f8d6e0586b0a20c7”,
“key”: “…”
}
},
“contracts”: {},
“deployments”: {}
}
The emulator account (
f8d6e0586b0a20c7) is the default account that signs transactions on your local emulator. Its private key is safe to commit because the emulator wipes state on restart. Never commit keys for testnet or mainnet.Start the Flow Emulator
The Flow emulator is a local blockchain that runs on your machine. It’s fast, deterministic, and perfect for development. No testnet tokens required. No network latency. Full control.
Start the emulator:
bash
flow emulator start
The emulator runs on http://localhost:8888 by default. Keep this terminal window open. The emulator needs to stay running while you develop.
You’ll see output indicating the emulator started successfully and is listening for transactions.
Write Your First Smart Contract
Create a simple counter contract. In your
/contracts directory, create Counter.cdc:cadence
access(all) contract Counter {
// Storage for the counter value
access(all) var count: Int
// Initialize the counter at 0
init() {
self.count = 0
}
// Function to increment the counter
access(all) fun increment() {
self.count = self.count + 1
}
// Function to get the current count
access(all) fun getCount(): Int {
return self.count
}
}
This contract does three things:
- Stores a counter value
- Provides a function to increment it
- Provides a function to read it
Simple, but it demonstrates the fundamental pattern: state storage and functions to modify or read that state.
Deploy Your Contract
Update
flow.json to include your contract:json
{
“contracts”: {
“Counter”: “./contracts/Counter.cdc”
},
“deployments”: {
“emulator”: {
“emulator-account”: [“Counter”]
}
}
}
This tells Flow CLI:
- The Counter contract exists at
./contracts/Counter.cdc - On the emulator network, deploy Counter to the emulator-account
Deploy the contract:
bash
flow project deploy –network emulator
You’ll see output confirming the contract deployed successfully. The emulator now has your Counter contract live and ready for interaction.
Read Data with Scripts
Scripts read blockchain state without modifying it. They’re free (no gas fees) and return results immediately.
Create
/scripts/get_counter.cdc:cadence
import Counter from “../contracts/Counter.cdc”
access(all) fun main(): Int {
return Counter.getCount()
}
Run the script:
bash
flow scripts execute ./scripts/get_counter.cdc –network emulator
Output:
Result: 0The counter starts at 0 because that’s what the contract’s
init() function sets. The script confirmed deployment worked and the contract’s state is accessible.Modify State with Transactions
Transactions change blockchain state. They cost gas fees (on mainnet/testnet) and require account authorization.
Create
/transactions/increment_counter.cdc:cadence
import Counter from “../contracts/Counter.cdc”
transaction {
prepare(acct: &Account) {
// Prepare phase handles authorization
// We don’t need the account for this simple transaction
}
execute {
Counter.increment()
}
}
Send the transaction:
bash
flow transactions send ./transactions/increment_counter.cdc –network emulator –signer emulator-account
The
--signer flag specifies which account signs (and pays for) the transaction. On emulator, the emulator-account signs by default.Run the get_counter script again:
bash
flow scripts execute ./scripts/get_counter.cdc –network emulator
Output:
Result: 1The counter incremented. You just modified blockchain state through a transaction.
Understanding the Development Cycle
Flow development follows a pattern:
- Write contracts defining state and logic
- Deploy contracts to emulator/testnet/mainnet
- Write scripts to read state (testing, debugging, frontend queries)
- Write transactions to modify state (user actions, admin functions)
- Test everything using Flow’s testing framework or manual verification
- Iterate based on results
The emulator makes this cycle fast. Write code, deploy, test, repeat. No waiting for block confirmations or testnet faucets.
Next Steps: Testing
Flow supports comprehensive testing. Create
/tests/Counter_test.cdc:cadence
import Test
access(all) let account = Test.createAccount()
access(all) fun testContract() {
let err = Test.deployContract(
name: “Counter”,
path: “../contracts/Counter.cdc”,
arguments: []
)
Test.expect(err, Test.beNil())
}
Run tests:
bash
flow test ./tests/Counter_test.cdc
Tests verify your contracts work as expected before deploying to testnet or mainnet. Flow’s testing framework supports comprehensive test scenarios, from basic functionality to edge cases and error handling.
Building a Frontend
Contracts deployed. Transactions working. Next step: connect a frontend.
Flow provides
@onflow/react-sdk for React applications (or @onflow/fcl for framework-agnostic JavaScript). These SDKs handle wallet connections, transaction signing, and blockchain queries.Basic setup in a React app:
javascript
import { FlowProvider } from ‘@onflow/react-sdk’
function App() {
return (
<FlowProvider
config={{
“flow.network”: “emulator”,
“accessNode.api”: “http://localhost:8888”,
“0xCounter”: “f8d6e0586b0a20c7”
}}
>
{/* Your app components */}
</FlowProvider>
)
}
The FlowProvider configures your app to connect to the local emulator and maps contract addresses. From there, you can use hooks to query state and submit transactions directly from React components.
Full frontend integration is beyond this guide’s scope, but Flow’s documentation provides complete tutorials: Building a Frontend App
Moving to Testnet
Local development is fast. But eventually, you deploy to testnet for real network testing.
Get testnet FLOW: Flow provides 100,000 testnet FLOW tokens (not real value) through the Flow Faucet. No drip limits. No waiting.
Create a testnet account:
bash
flow accounts create –network testnet
Update flow.json with your testnet account details:
json
{
“accounts”: {
“testnet-account”: {
“address”: “YOUR_TESTNET_ADDRESS”,
“key”: “YOUR_PRIVATE_KEY”
}
},
“deployments”: {
“testnet”: {
“testnet-account”: [“Counter”]
}
}
}
Deploy to testnet:
bash
flow project deploy –network testnet
Your contract is now live on Flow’s public testnet, accessible to anyone.
Key Resources
Official Documentation:
- Flow Developer Portal: Comprehensive docs covering everything
- Cadence Language Reference: Detailed language documentation
- Flow CLI Docs: CLI command reference
Learning Platforms:
- Emerald Academy: Free courses on Flow development
- CryptoKitties: ARCADE!: Gamified Cadence learning
- Flow Playground: Browser-based Cadence editor (no setup required)
Community:
- Flow Discord: Active developer community, real-time help
- Flow Forum: Technical discussions and proposals
- Developer Office Hours: Weekly sessions with Flow team
Development Tools:
- Flow Block Explorers: View transactions, contracts, accounts
- @onflow/react-sdk: React integration
- Flow Testnet Faucet: Get testnet tokens
Common Gotchas
Emulator state resets on restart. Contracts and accounts disappear when you stop the emulator. That’s intentional, clean state every time.
Private keys in flow.json: Safe for emulator. Never commit testnet/mainnet keys.
Account addresses differ by network. Same contract, different addresses on emulator vs testnet vs mainnet. flow.json handles this with deployment configurations.
Resource-oriented thinking takes adjustment. If you’re coming from Solidity, Cadence’s resource model feels different. Resources can’t be copied or lost. That’s the safety mechanism.
Imports reference deployment locations. When importing contracts, the address comes from flow.json configurations.
import Counter from 0xCounter resolves based on the network you’re using.Final Thought
You’ve set up a complete Flow development environment. Installed CLI. Created a project. Deployed a contract. Ran scripts and transactions. Verified everything works.
This is the foundation. From here, you can build NFT platforms, DeFi protocols, games, or consumer applications. The patterns stay consistent: contracts define logic, transactions modify state, scripts read state, frontends connect it all.
Flow was built for applications that scale. The infrastructure handles millions of users. The developer experience makes building practical. The tooling removes friction.
Now start building.













