If you started your tour of the DFINITY Canister Software Development Kit (SDK) with the Quick start, you have already seen the basic work flow for creating applications that run on the Internet Computer. Now, let's take a closer look at that work flow by exploring the default files and folders that are added to your workspace when you create a new project.
As a preview, the following diagram illustrates the development work flow when running the Internet Computer locally on you computer.
Before you start this tutorial, verify the following:
As discussed in the Quick start, applications for the Internet Computer start as projects that you create. You can create projects using the dfx
executable command-line interface (CLI).
To take a closer look at the files and folders that are included in a project by default, let's create a new project to work with.
To create a new project:
dfx new explore_hello
The dfx new explore_hello
command creates a new explore_hello
project, including a default project directory structure under the new project name and a new Git repository for your project. If you have node.js
installed locally, creating a new project also adds some template front-end code and dependencies. ls -l explore_hello
By default, the project directory structure includes at least one source subdirectory, a template README.md file, and a default dfx.json configuration file. Depending on whether you have node.js installed, your project directory might include some or all of the following files: explore_hello/
|-- README.md # default project documentation
|-- dfx.json # project configuration file
|-- node_modules # libraries for front-end development
|-- package-lock.json
|-- package.json
|-- src # source files directory
| |-- explore_hello
| | |-- main.mo
| |-- explore_hello_assets
| |-- assets
| | |-- logo.png
| | |-- main.css
| | |-- sample-asset.txt
| |-- src
| |-- index.html
| |-- index.js
|-- webpack.config.js
At a minimum, the default project directory includes the following folders and files: README
file for documenting your project in the repository.dfx.json
configuration file to set configurable options for your project.src
directory for all of the source files required by your application.src
directory includes a template main.mo
file that you can modify or replace to include your core programming logic. Because this tutorial focuses on the basics of getting started, you are only going to use the main.mo file. If you have node.js
installed, your project directory includes additional files and directories that you can use to define the front-end interface for your application. Front-end development and the template files in the assets
folder are discussed a little later.By default, creating a new project adds some template files to your project directory. You can edit these template files to customize the configuration settings for your project and to include your own code to speed up the development cycle.
To review the default configuration file for your project:
cd explore_hello
dfx.json
configuration file in a text editor to review the default settings.{
"canisters": {
"explore_hello": {
"main": "src/explore_hello/main.mo",
"type": "motoko"
},
"explore_hello_assets": {
"dependencies": [
"explore_hello"
],
"frontend": {
"entrypoint": "src/explore_hello_assets/src/index.js"
},
"source": [
"src/explore_hello_assets/assets",
"dist/explore_hello_assets/"
],
"type": "assets"
}
},
"defaults": {
"build": {
"packtool": ""
}
},
"dfx": "0.7.2",
"networks": {
"local": {
"bind": "127.0.0.1:8000",
"type": "ephemeral"
}
},
"version": 1
}
Let's take a look at a few of the default settings. canisters
section specifies the name of the WebAssembly module for your explore_hello
project is explore_hello
. canisters.explore_hello
key specifies that the main program to be compiled is located in the path specified by the main setting, in this case, src/explore_hello/main.mo
and the type
setting indicates that this is a motoko
program. canisters.explore_hello_assets
key specifies configuration details about front-end assets for this project. Let's skip those for now. dfx
setting is used to identify the version of the software used to create the project. networks
section specifies information about the networks to which you connect. The default settings bind the local Internet Computer network to the local host address 127.0.0.1
and port 8000
. networks
section can include network aliases and URLs for connecting to those providers. dfx.json
file to continue.New projects always include a template main.mo source code file. You can edit this file to include your own code to speed up the development cycle.
Let's take a look at the sample program in the default main.mo template file as a starting point for creating simple program using the Motoko programming language.
To review the default sample program for your project:
pwd
src/explore_hello/main.mo
file in a text editor and review the code in the template: actor {
public func greet(name : Text) : async Text {
return "Hello, " # name # "!";
};
};
Let's take a look at a few key elements of this program: actor
instead of a main
function, which some programming languages require. For Motoko, the main
function is implicit in the file itself.print
or println
function, that traditional program would not represent a typical use case for Motoko programs that run on the Internet Computer.actor
with a public greet
function that takes a name
argument with a type of Text
.async
keyword to indicate that the program returns an asynchronous message consisting of a concatenated text string constructed using "Hello, "
, the #
operator, the name
argument, and "!"
.actor
objects and asynchronous message handling more a little later. For now, you can continue to the next section.main.mo
file to continue.Before you can build the default project, you need to connect to the Internet Computer network either running locally in your development environment or running remotely on a subnet that you can access.
Starting the network locally requires a dfx.json
file, so you should be sure you are in your project's root directory. For this tutorial, you should have two separate terminal shells, so that you can start and see network operations in one terminal and manage your project in another.
To start the network locally:
dfx start
Depending on your platform and local security settings, you might see a warning displayed. If you are prompted to allow or deny incoming network connections, click Allow. After you start the local network, you have one terminal that displays messages about network operations and another for performing project-related tasks.After you connect to the Internet Computer network running locally in your development environment, you can register with the network to generate unique, network-specific canister identifiers for your project.
In the Quick start tutorial, this step was performed as part of the dfx deploy command work flow. This tutorial demonstrates how to perform each of the operations independently.
To register canister identifiers for the local network:
dfx canister create --all
The command displays the network-specific canister identifiers for the canisters defined in the dfx.json
configuration file. Creating a wallet canister on the local network. The wallet canister on the "local" network for user "pubs-id" is "rwlgt-iiaaa-aaaaa-aaaaa-cai" Creating canister "explore_hello"... "explore_hello" canister created with canister id: "rrkah-fqaaa-aaaaa-aaaaq-cai" Creating canister "explore_hello_assets"... "explore_hello_assets" canister created with canister id: "ryjl3-tyaaa-aaaaa-aaaba-cai"Because you are connected to the Internet Computer network running locally, these canister identifiers are only valid locally and are stored for the project in the .dfx/local/canister_ids.json file.
{
"explore_hello": {
"local": "rrkah-fqaaa-aaaaa-aaaaq-cai"
},
"explore_hello_assets": {
"local": "ryjl3-tyaaa-aaaaa-aaaba-cai"
}
}
Now that you have explored the default configuration settings and program code and have started the Internet Computer network, let's compile the default program into an executable WebAssembly module.
To build the program executable:
explore_hello
project directory. dfx build
command from within the project directory structure.dfx build
You should see output similar to the following: Building canisters...
Building frontend...
Because you are connected to the Internet Computer network running locally, the dfx build
command adds the canisters
directory under the .dfx/local/
directory for the project..dfx/local/canisters/explore_hello
directory created by the dfx build
command contains the WebAssembly and related application files by running the following command. ls -l .dfx/local/canisters/explore_hello/
For example, the command returns output similar to the following: -rw-r--r-- 1 pubs staff 178 Apr 6 14:25 explore_hello.d.ts
-rw-r--r-- 1 pubs staff 41 Apr 6 14:25 explore_hello.did
-rw-r--r-- 1 pubs staff 155 Apr 6 14:25 explore_hello.did.js
-rw-r--r-- 1 pubs staff 142 Apr 6 14:25 explore_hello.js
-rw-r--r-- 1 pubs staff 157613 Apr 6 14:25 explore_hello.wasm
The canisters/explore_hello
directory contains the following key files: explore_hello.did
file contains an interface description for your main program.explore_hello.did.js
file contains a JavaScript representation of the canister interface for the functions in your program.explore_hello.js
file contains a JavaScript representation of the canister interface for your program.explore_hello.wasm
file contains the compiled WebAssembly for the assets used in your project.canisters/explore_hello_assets
directory contains similar files to describe the front-end assets associated with your project. In addition to the files in the canisters/explore_hello
and the canisters/explore_hello_assets
directories, the dfx build
command creates an idl
directory.You've seen that the dfx build
command creates several artifacts in a canisters
directory for your project. The WebAssembly modules and the canister_manifest.json
file are required for your program to be deployed on the Internet Computer network.
To deploy locally:
explore_hello
project on the local network by running the following command: dfx canister install --all
The command displays output similar to the following: Installing code for canister explore_hello, with canister_id rrkah-fqaaa-aaaaa-aaaaq-cai
Installing code for canister explore_hello_assets, with canister_id ryjl3-tyaaa-aaaaa-aaaba-cai
Authorizing our identity (pubs-id) to the asset canister...
Uploading assets to asset canister...
/index.html 1/1 (480 bytes)
/index.js 1/1 (296836 bytes)
/main.css 1/1 (484 bytes)
/sample-asset.txt 1/1 (24 bytes)
/logo.png 1/1 (25397 bytes)
/index.js.map 1/1 (964679 bytes)
/index.js.LICENSE.txt 1/1 (499 bytes)
Run the dfx canister call
command and specify the program and function to call by running the following command: dfx canister call explore_hello greet everyone
This command specifies: explore_hello
as the name of the canister or application service you want to call.greet
as the specific method or function you want to call.everyone
as the argument to pass to the greet
function.greet
function. For example: ("Hello, everyone!")
If you have node.js
installed in your development environment, your project includes a simple front-end example that uses a template index.js
JavaScript file for accessing the explore_hello
program in a browser.
To explore the default front-end template:
explore_hello
project directory.src/explore_hello_assets/src/index.js
file in a text editor and review the code in the template script: import { Actor, HttpAgent } from '@dfinity/agent';
import { idlFactory as explore_hello_idl, canisterId as explore_hello_id } from 'dfx-generated/explore_hello';
const agent = new HttpAgent();
const explore_hello = Actor.createActor(explore_hello_idl, { agent, canisterId: explore_hello_id });
document.getElementById("clickMeBtn").addEventListener("click", async () => {
const name = document.getElementById("name").value.toString();
const greeting = await explore_hello.greet(name);
document.getElementById("greeting").innerText = greeting;
});
The template index.js
file uses two import
statements to explicitly create an agent instance and the actor for the explore_hello
canister generated by dfx
. This file works in conjunction with the template index.html
file to display an HTML page with an image asset, input field, and button for the greet
function.index.js
file to continue.ls -l .dfx/local/canisters/explore_hello_assets/
The command displays output similar to the following: drwxr-xr-x 9 pubs staff 288 Apr 6 14:25 assets
-r--r--r-- 1 pubs staff 2931 Dec 31 1969 assetstorage.did
-r--r--r-- 1 pubs staff 265823 Dec 31 1969 assetstorage.wasm
-rw-r--r-- 1 pubs staff 3651 Apr 6 14:25 explore_hello_assets.d.ts
-rw-rw-rw- 1 pubs staff 2931 Dec 31 1969 explore_hello_assets.did
-rw-r--r-- 1 pubs staff 4236 Apr 6 14:25 explore_hello_assets.did.js
-rw-r--r-- 1 pubs staff 149 Apr 6 14:25 explore_hello_assets.js
-rw-rw-rw- 1 pubs staff 265823 Dec 31 1969 explore_hello_assets.wasm
These files were generated automatically by the dfx build
command using node modules and the template index.js
file.local
network address and port number—127.0.0.1:8000
/—specified in the dfx.json
configuration file. To specify the canister you want the web server to display, add the canisterId
parameter and the explore_hello_assets
canister identifier to the URL using the following syntax: ?canisterId=<YOUR-CANISTER-IDENTIFIER>
For example, the full URL should look similar to the following: http://127.0.0.1:8000/?canisterId=rrkah-fqaaa-aaaaa-aaaaq-cai
You must use the case-sensitive canisterId parameter before the canister identifier.After you finish experimenting with your program, you can stop the local Internet Computer network so that it doesn't continue running in the background.
To stop the local network:
dfx stop