Default project template
Overview
The dfx new <project_name>
command creates a new project directory, template files, and a new <project_name>
Git repository for your project.
When creating new projects with dfx
, only alphanumeric characters and underscores should be used. This is to assure that project names are valid within Motoko, JavaScript, and other contexts.
Exploring the default project structure
By default, the project structure will resemble the following:
- Motoko
- Rust
- TypeScript
- Python
hello/
├── README.md # Default project documentation
├── dfx.json # Project configuration file
├── node_modules # Libraries for frontend development
├── package-lock.json
├── package.json
├── src # Source files directory
│ ├── hello_backend
│ │ └── main.mo
│ ├── hello_frontend
│ ├── assets
│ │ ├── logo.png
│ │ ├── main.css
│ │ └── sample-asset.txt
│ └── src
│ ├── index.html
│ └── index.js
└── webpack.config.js
hello/
├── README.md # Default project documentation
├── dfx.json # Project configuration file
├── node_modules # Libraries for frontend development
├── package-lock.json
├── package.json
├── src # Source files directory
│ ├── hello_backend
│ │ └── Cargo.toml
│ │ └── hello_backend.did
│ │ └── src
│ │ ├── lib.rs
│ ├── hello_frontend
│ ├── assets
│ │ ├── logo.png
│ │ ├── main.css
│ │ └── sample-asset.txt
│ └── src
│ ├── index.html
│ └── index.js
└── webpack.config.js
hello/
├── README.md # Default project documentation
├── dfx.json # Project configuration file
├── node_modules # Libraries for frontend development
├── package-lock.json
├── package.json
├── src # Source files directory
│ ├── hello_backend
│ │ └── package.json
│ │ └── hello_backend.did
│ │ └── src
│ │ ├── index.ts
│ ├── hello_frontend
│ ├── assets
| |── index.html
| |── package.json
│ └── src
│ ├── App.js
│ ├── index.scss
│ ├── logo2.svg
│ ├── main.js
│ └── vite-env.d.ts
| |── tsconfig.json
| |── vite.config.js
└── tsconfig.json
hello/
├── README.md # Default project documentation
├── dfx.json # Project configuration file
├── node_modules # Libraries for frontend development
├── package-lock.json
├── package.json
├── src # Source files directory
│ ├── hello_backend
│ │ └── hello_backend.did
│ │ └── src
│ │ ├── main.py
│ ├── hello_frontend
│ ├── assets
| |── index.html
| |── package.json
│ └── src
│ ├── App.js
│ ├── index.scss
│ ├── logo2.svg
│ ├── main.js
│ └── vite-env.d.ts
| |── tsconfig.json
| |── vite.config.js
└── tsconfig.json
In this directory, the following files and directories are notable:
README.md
: The default README file to be used for documenting your project.dfx.json
: The default configuration file used to set configurable options for your project.src/
: The source directory that contains all of your dapp's source files.hello_backend
: The source directory that contains your dapp's backend code files.hello_frontend
: The source directory that contains your dapp's frontend code files.
Why are there two canisters, hello_backend
and hello_frontend
?
The hello_frontend
canister is used to store the dapp's frontend assets, such as HTML, CSS, JavaScript, React, images, videos, and other media to be displayed in the app's user interface.
The hello_backend
canister is used to store the dapp's code and core logic.
A canister is capable of storing both the frontend assets and backend code, but using two canisters with a dedicated canister for the frontend means that any language can be used for the backend canister without needing a library for the assets storage API.
Reviewing the default configuration
By default, the dfx.json
file will contain automatically generated configuration settings for your new project. This file is used to configure the components of your project:
- Motoko
- Rust
- TypeScript
- Python
{
"canisters": {
"hello_backend": {
"main": "src/hello_backend/main.mo",
"type": "motoko"
},
"hello_frontend": {
"dependencies": [
"hello_backend"
],
"frontend": {
"entrypoint": "src/hello_frontend/src/index.html"
},
"source": [
"src/hello_frontend/assets",
"dist/hello_frontend/"
],
"type": "assets"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}
{
"canisters": {
"hello_backend": {
"candid": "src/hello_backend/hello_backend.did",
"package": "hello_backend",
"type": "rust"
},
"hello_frontend": {
"dependencies": [
"hello_backend"
],
"frontend": {
"entrypoint": "src/hello_frontend/src/index.html"
},
"source": [
"src/hello_frontend/assets",
"dist/hello_frontend/"
],
"type": "assets"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}%
{
"canisters": {
"hello_backend": {
"build": "npx azle hello_backend",
"candid": "src/hello_backend/hello_backend.did",
"gzip": true,
"main": "src/hello_backend/src/index.ts",
"type": "custom",
"wasm": ".azle/hello_backend/hello_backend.wasm"
},
"hello_frontend": {
"dependencies": [
"hello_backend"
],
"source": [
"src/hello_frontend/dist"
],
"type": "assets",
"workspace": "hello_frontend"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}
{
"canisters": {
"hello_backend": {
"build": "python -m kybra hello_backend src/hello_backend/src/main.py src/hello_backend/hello_backend.did",
"candid": "src/hello_backend/hello_backend.did",
"gzip": true,
"post_install": ".kybra/hello_backend/post_install.sh",
"type": "custom",
"wasm": ".kybra/hello_backend/hello_backend.wasm"
},
"hello_frontend": {
"dependencies": [
"hello_backend"
],
"source": [
"src/hello_frontend/dist"
],
"type": "assets",
"workspace": "hello_frontend"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}
Reviewing the default program code
The backend canister's code will be located in the src/hello_backend
subdirectory.
- Motoko
- Rust
- TypeScript
- Python
///src/hello_backend/main.mo
actor {
public query func greet(name : Text) : async Text {
return "Hello, " # name # "!";
};
};
///src/hello_backend/src/lib.rs
#[ic_cdk::query]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
import { Canister, query, text } from 'azle';
export default Canister({
greet: query([text], text, (name) => {
return `Hello, ${name}!`;
})
})
from kybra import query
@query
def greet(name: str) -> str:
return f"Hello, {name}!"
Next steps
To interact with this code, you first need to deploy the canister. To learn how to deploy to a local developer environment, see the documentation here: