Asset canister overview
Dapps often utilize a frontend interface to facilitate user interaction with the application through elements such as a dashboard, account page, media player, or other assets that are displayed in the web browser. These assets may be in the form of HTML, JavaScript, CSS, or other frontend frameworks like React.
Application frontends are often referred to as asset canisters on ICP, since they are canisters defined as "type": "asset"
in the dfx.json
file for a project. Projects created by the dfx new
command have the option to include a default asset canister named using the project's name and the suffix _frontend
, such as hello_world_frontend
.
The terms 'asset canister' and 'frontend canister' are often used interchangeably.
Application frontends exist in the following forms:
A frontend canister that communicates with backend canister(s) to provide a full-stack dapp.
Backend canisters that communicate with an external frontend application that isn't hosted on ICP. To facilitate this communication, the ICP JavaScript agent can be used. Learn more about the JS request API.
A frontend canister that doesn't communicate with any backend canisters and only provides web assets.
How it works
To host web assets, a canister must implement a method that accepts and consumes an HTTP request, including URL, HTTP method, and header data, then returns an HTTP response, including request status, header data, and body content. This method can return HTML, CSS, and JavaScript content in the HTTP response.
When a canister is configured in a project's dfx.json
file as "type": "asset"
, it already contains the boilerplate code necessary to facilitate these HTTP requests. Once a frontend canister is deployed to the mainnet, the frontend interface can be accessed at http://<canister id>.icp0.io
and http://<canister id>.raw.icp0.io
.
Default settings
By default, all projects created with dfx new
have the option to include a frontend canister in the project. This default frontend canister is written in Rust and uses one of the following frontend frameworks: SvelteKit, React, Vue, or Vanilla JS. The user can choose the framework through the dfx new
interactive prompt in dfx
versions 0.17.0 and newer.
For asset canisters created by dfx new
, the default configuration will include:
"source": [ "src/hello_frontend/dist" ]
: The default subdirectories containing asset files. For assets to be served in the frontend canister, their directories must be included in thissource
list."type": "assets"
: Defines the canister type asassets
.
In dfx.json
, these default settings will resemble the following:
{
"canisters": {
"hello_backend": {
"main": "src/hello_backend/main.mo",
"type": "motoko"
},
"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
}
Motoko asset canisters
The Motoko server and certified HTTP packages can be used for creating asset canisters using the Motoko language.
Rust asset canisters
The ic-asset
Rust crate can be used to develop your project's frontend canister.
Additionally, the ic-http-certification crate can be used to:
Serve certified assets from the same canister as their primary “backend” canister.
Embed assets directly into a canister’s Wasm rather than uploading them at runtime.
Create custom routing logic, such as:
Serving 404 pages in multi-page apps.
Serving multiple frontends from the same canister.
Certify more complex caching or streaming scenarios.
Other third-party options for serving assets include:
TypesScript asset canisters
The Express HTTP server package via Azle can be used to create asset canisters in TypeScript.
Limitations
The frontend canister can host roughly 1GiB in static files. It is recommended that you distribute your files across multiple canisters if the total size of all your assets begins to exceed this amount. Once you exceed this figure, your canister may fail to upgrade.
Dynamic URLs
Dynamic URLs are currently not supported by the default frontend canister.
If a developer would like to support dynamic URLs, custom logic can be implemented using third-party options.
404 pages and aliasing
You can use the ic-http-certification
Rust crate for serving 404 pages or configuring redirects through the crate's wildcard function, such as:
use ic_http_certification::HttpCertificationPath;
let path = HttpCertificationPath::wildcard("/js");
404 pages can only be served as raw content currently.
Learn more about the HTTP certification library.
Resources
Using raw HTML and JavaScript to display a simple HTML entry page.
Using React and TypeScript to import CSS properties from an external file.
Vite + React + Motoko template example.
Vite + SvelteKit + Motoko template example.
Deploying an existing Next.js application as a frontend canister.
Next steps
Learn how to use and customize the default frontend canister.