Skip to main content
Version: Current

Flow App Quickstart


This guide is a simple walkthrough to get started building a web3 app using the Flow Client Library (FCL).

info

If you are looking for a scalfolds, check out scaffolds availabe in the Flow CLI.

This simple guide uses the "Hello World" scaffold, it is meant to provide all the code needed to get a web application up and running.

Introduction

Flow app anatomy

info

FCL (aka Flow Client Library) wraps the logic needed to communicate with the Flow blockchain. It's a npm package, More Information

This guide assumes a good understanding of React. The concepts are easy to understand and apply to other libraries and framework. A strong understanding of Cadence (Flow's smart contract language) is not required. More information on Cadence, learning the Cadence language.

This guide will interact with an existing smart contract on Flow's testnet known as the Profile Contract. This contract will create a new profile and edit the profile information.

FCL concepts covered:

For more help, Discord. See links at the end of this article for diving deeper into building on Flow.

Installation

Make sure you have Flow CLI installed. installation instructions.

The first step is to generate a React app using Next.js and create-next-app. From your terminal, run the following:


_10
npx create-next-app@latest flow-app
_10
cd flow-app

Configuration

Setting up Flow

Using the Flow CLI scaffold, create a basic hello world web project. This will create a new flow.json file in the hello-world folder. This file will contain the Flow configuration for your project.


_10
flow setup hello-world --scaffold
_10
# select scaffold 5
_10
cd hello-world
_10
npm install
_10
# run the app in a later step

We don't recommend keeping private keys in your flow.json, notice that Flow CLI already moved the emulator private key to a emulator.key file and point to it using the key/location pattern. This file should be added to your .gitignore file, so it won't be committed to your repository.

We won't be using emulator and running contracts locally in this quickstart, but FCL will complain if it finds private keys in your flow.json file.

Your flow.json file should look like this:


_17
{
_17
"networks": {
_17
"emulator": "127.0.0.1:3569",
_17
"mainnet": "access.mainnet.nodes.onflow.org:9000",
_17
"sandboxnet": "access.sandboxnet.nodes.onflow.org:9000",
_17
"testnet": "access.devnet.nodes.onflow.org:9000"
_17
},
_17
"accounts": {
_17
"emulator-account": {
_17
"address": "f8d6e0586b0a20c7",
_17
"key": {
_17
"type": "file",
_17
"location": "./emulator.key"
_17
}
_17
}
_17
}
_17
}

info

The flow.json file is used to keep track of deployed contracts and accounts. More Information

Configuring FCL

Next, notice @onflow/fcl has been added to the package.json and the web application is read to be run.

info

There are a lot of benefits to getting familiar with existing Flow CLI scaffolds. For example the hello-world scaffold already has fcl configuration settings to run on local emulator.

The hello-world web application comes with convenience npm commands to facilitate a quick start. The following command will preform:

  1. Start emulator
  2. Start dev wallet
  3. Start web app
info

Emulator is a local blockchain More Information. Emulator has all the features as testnet and mainnet blockchains


_10
npm run dev:local

Now that your app is running. FYI, fcl loads the configuration in config/fcl.ts This file contains configuration information for FCL, such as what Access Node and wallet discovery endpoint and which network to use (e.g. testnet or a local emulator).

The accessNode.api key specifies the address of a Flow access node. There are publically available access nodes, but have to rate limit. Alternatively, applications might want to run an Observer node Run a Node. discovery.wallet is an address that points to a service that lists FCL compatible wallets. Flow's FCL Discovery service is a service that FCL wallet providers can be added to, and be made 'discoverable' to any application that uses the discovery.wallet endpoint.

Also, notice that package.json uses NEXT_PUBLIC_FLOW_NETWORK=local for dev command, this is used to set the network in config/fcl.ts.

The main page for Next.js apps is located in pages/index.js. So let's finish configuring our app by going in the pages/ directory and importing the config file into the top of our index.js file. We'll then swap out the default component in index.js to look like this:


_35
import Head from 'next/head'
_35
import styles from '../styles/Home.module.css'
_35
import Links from '../components/Links'
_35
import Container from '../components/Container'
_35
import useCurrentUser from '../hooks/useCurrentUser'
_35
_35
export default function Home() {
_35
const { loggedIn } = useCurrentUser()
_35
_35
return (
_35
<div className={styles.container}>
_35
_35
<Head>
_35
<title>FCL Next Scaffold</title>
_35
<meta name="description" content="FCL Next Scaffold for the Flow Blockchain" />
_35
<link rel="icon" href="/favicon.ico" />
_35
</Head>
_35
_35
<main className={styles.main}>
_35
<h1 className={styles.title}>
_35
<a href="https://developers.flow.com/tools/fcl-js">FCL</a> Next Scaffold
_35
</h1>
_35
_35
<p className={styles.description}>
_35
For the Flow Blockchain
_35
</p>
_35
_35
{loggedIn && <Container />}
_35
_35
<Links />
_35
_35
</main>
_35
</div>
_35
)
_35
}

Now we're ready to start talking to Flow!

warning

The web app will run but there are no contracts deployed to local emulator. This is a step in Querying the Blockchain section.

Authenticating a User

User Login

Note: in above code useCurrentUser is used to determine if there is a user logged in.

There are two methods to allow the user to login. fcl.logIn() or fcl.authenticate() More Information on, authenticate

In components/Navbar.tsx a button wires up the authentication method fcl.authenticate(). It is used to bring up the list of supported wallets. See below

Once authenticated, FCL has a hook const user = useCurrentUser() to get the user data, when user is signed in loggedIn is true. For more information on the currentUser, read more here.


_32
import Head from 'next/head'import * as fcl from '@onflow/fcl'
_32
import useCurrentUser from '../hooks/useCurrentUser'
_32
import navbarStyles from '../styles/Navbar.module.css'
_32
import elementStyles from '../styles/Elements.module.css'
_32
_32
export default function Navbar() {
_32
const user = useCurrentUser()
_32
_32
return (
_32
<div className={navbarStyles.navbar}>
_32
{!user.loggedIn &&
_32
<button
_32
onClick={fcl.authenticate}
_32
className={elementStyles.button}>
_32
Log In With Wallet
_32
</button>
_32
}
_32
{user.loggedIn &&
_32
(
_32
<>
_32
<div className={navbarStyles.address}>{ user?.addr }</div>
_32
<button
_32
onClick={fcl.unauthenticate}
_32
className={elementStyles.button}>
_32
Log Out
_32
</button>
_32
</>
_32
)
_32
}
_32
</div>
_32
)
_32
}

You should now be able to log in or sign up a user and unauthenticate them. Upon logging in or signing up your users will see a popup where they can choose between wallet providers. Choose the dev wallet to use the same account that deployed the HelloWorld contract, this is needed for mutation. Upon completing authentication, you'll see the component change and the user's wallet address appear on the screen if you've completed this properly.

info

More on wallets, Lilico wallet is a Flow wallet.

Deploying contracts

Hello World scaffold does come with a Cadence contract. You will notice HelloWorld.cdc has been deployed when running npm run dev:local. Look at hello-world package.json to see the commands that get run, flow dev deploys contracts. In the flow.json make sure the emulator endpoint is correct. Look at the terminal the emulator is running,

Emulator Output

  1. Make sure the emulator is using the same port as gRPC and
  2. Configure deployment to add mapping of contract to account.

_12
...
_12
"networks": {
_12
"emulator": "127.0.0.1:3569",
_12
...
_12
},
_12
"deployments": {
_12
"emulator": {
_12
"default": [
_12
"HelloWorld"
_12
]
_12
}
_12
}

Verify that flow.json updates with HelloWorld contract information, contracts has the HelloWorld contract and deployments shows that HelloWorld has been deployed.


_30
{
_30
"contracts": {
_30
"HelloWorld": "cadence/contracts/HelloWorld.cdc"
_30
},
_30
"networks": {
_30
"emulator": "127.0.0.1:3569",
_30
"mainnet": "access.mainnet.nodes.onflow.org:9000",
_30
"testnet": "access.devnet.nodes.onflow.org:9000"
_30
},
_30
"accounts": {
_30
"default": {
_30
"address": "01cf0e2f2f715450",
_30
"key": "..."
_30
},
_30
"emulator-account": {
_30
"address": "f8d6e0586b0a20c7",
_30
"key": {
_30
"type": "file",
_30
"location": "./emulator.key"
_30
}
_30
}
_30
},
_30
"deployments": {
_30
"emulator": {
_30
"default": [
_30
"HelloWorld"
_30
]
_30
}
_30
}
_30
}

Query the Blockchain

Now that all pieces are in place. UI can query HelloWorld contract.

Query HelloWorld Contract

The script that queries the Hello World contract is located hello-world/cadence/scripts/ReadHelloWorld.cdc


_10
import "HelloWorld"
_10
_10
pub fun main(): String {
_10
return HelloWorld.greeting
_10
}

In components/Container.tsx file, fcl.query is used to set the Cadence script and query the contract.


_10
_10
const queryChain = async () => {
_10
const res = await fcl.query({
_10
cadence: ReadHelloWorld
_10
})
_10
_10
setChainGreeting(res)
_10
}

It is that simple!

Mutating the Blockchain

Update the HelloWorld contract greeting. Notice that Greeting gets changed when the transaction gets processed.

Update contract

In components/Container.tsx file, the mutateGreeting method fcl.mutate sends UpdateHelloWorld cadence which triggers a transaction that the user signs.


_14
const mutateGreeting = async (event) => {
_14
event.preventDefault()
_14
_14
if (!userGreetingInput.length) {
_14
throw new Error('Please add a new greeting string.')
_14
}
_14
_14
const transactionId = await fcl.mutate({
_14
cadence: UpdateHelloWorld,
_14
args: (arg, t) => [arg(userGreetingInput, t.String)],
_14
})
_14
_14
setLastTransactionId(transactionId)
_14
}

This guide covers flow-cli commands that make deploying contracts simple and using fcl to querying and mutating a contract.

More information

That's it! You now have a shippable Flow app that can auth, query, init accounts, and mutate the chain. This is just the beginning. There is so much more to know. Next steps:

Cadence

FCL Scaffolds

Full Stack NFT Marketplace Example

More FCL

Other