Skip to content

Commit 0aebbc0

Browse files
docs: review local development full experience as on production (#381)
Signed-off-by: David Dal Busco <david.dalbusco@outlook.com>
1 parent d60c6d1 commit 0aebbc0

7 files changed

Lines changed: 249 additions & 153 deletions

File tree

docs/guides/local-development.mdx

Lines changed: 63 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,25 @@ description: Set-up the local emulator with Docker
66

77
# Local Development
88

9-
The tooling is designed with local-first development in mind. Whether you're using the official [plugins](../reference/plugins.md) (Next.js, Vite) or creating a new project with `npm create juno@latest`, local development is the default experience.
9+
Juno offers something most platforms don’t: a full local development environment that closely mirrors production.
1010

11-
When running `npm run dev` (or `start`), your app connects to a locally simulated Satellite via the provided emulator — so you can build and test your backend logic without deploying to the live network.
11+
When you develop locally, you're running an emulator that includes the well known infrastructure services — including the actual administration Console UI.
1212

13-
For continuous integration workflows or advanced setups, this guide shows how to run a Docker-based sandbox that closely mirrors the production environment.
13+
This enables:
14+
15+
- A development experience that mirrors mainnet, helping you build with confidence
16+
- A smooth dev loop, from prototype to deployment
17+
- A unique way to build, debug, and validate smart contract logic and frontend behavior — all in one place
18+
19+
![A screenshot of the DEV Console UI login screen](../img/dev-console/login.webp)
1420

1521
---
1622

1723
## Before you begin
1824

19-
Make sure you have Docker installed on your machine ([Windows](https://docs.docker.com/desktop/install/windows-install/), [MacOS](https://docs.docker.com/desktop/install/mac-install/), or [Linux](https://docs.docker.com/desktop/install/linux-install/)).
25+
Docker is used to run a self-contained local environment with all services, replicas, and the Console UI.
26+
27+
Make sure the tool is installed on your machine ([Windows](https://docs.docker.com/desktop/install/windows-install/), [MacOS](https://docs.docker.com/desktop/install/mac-install/), or [Linux](https://docs.docker.com/desktop/install/linux-install/)).
2028

2129
:::note
2230

@@ -42,7 +50,7 @@ Then, in your project folder, start the local emulator with:
4250
juno dev start
4351
```
4452

45-
This will launch a local Satellite along with a local Internet Identity, allowing you to develop and test without deploying anything live.
53+
This will launch the emulator along with all the services needed to develop your project.
4654

4755
We recommend running this in a dedicated terminal window or tab, while your frontend project (e.g. using Vite or Next.js) runs separately using npm run dev or similar.
4856

@@ -54,6 +62,43 @@ juno dev stop
5462

5563
---
5664

65+
## Available Images
66+
67+
Juno supports two main environments for running your project locally, each tailored to different use cases.
68+
69+
| Image | Description | Includes Console UI | Best for |
70+
| --------------------- | -------------------------------------------- | ------------------- | --------------------------- |
71+
| `junobuild/skylab` | All-in-one local environment like production || End-to-end dev, exploration |
72+
| `junobuild/satellite` | Lightweight setup running a single Satellite || CI, focused app testing |
73+
74+
Both variants run on a local network, services and support live-reloading for serverless functions written in Rust or TypeScript.
75+
76+
- Use **Skylab** for the full experience, including the Console UI and supporting infrastructure.
77+
- Use **Satellite** when you want a faster, minimal setup for a specific app or automated tests.
78+
79+
The table below shows which modules are available in each image and helps clarify what’s included when running locally with Skylab or Satellite.
80+
81+
| Module | Skylab ✅ | Satellite ✅ |
82+
| ------------------------------------------- | --------- | ------------ |
83+
| Console (Backend) |||
84+
| Console (UI) |||
85+
| Create Satellites / Orbiters via Console UI |||
86+
| Default (auto-deployed) Satellite |||
87+
| Observatory |||
88+
| Internet Identity |||
89+
| ICP Ledger |||
90+
| ICP Index |||
91+
| NNS Governance |||
92+
| Cycles Minting (CMC) |||
93+
94+
:::note
95+
96+
The default (auto-deployed) Satellite is available with a predefined canister ID `jx5yt-yyaaa-aaaal-abzbq-cai`.
97+
98+
:::
99+
100+
---
101+
57102
## Hot Reload
58103

59104
The local container supports live reloading. When you modify your [configuration](#configuration) or build custom [Functions](../build/functions/index.md) to enhance Juno's capabilities with serverless features, those changes will be automatically redeployed.
@@ -68,7 +113,11 @@ Modify the following information of the `docker-compose.yml` file to tweak the c
68113

69114
The default port `5987` is used for communication with the locally deployed satellites and other modules in the local environment (replica). This is the primary port for interaction with the application.
70115

71-
The container also exposes a small admin server for internal management on port `5999`.
116+
The container also exposes:
117+
118+
- a small admin server for internal management on port `5999`
119+
120+
- the Console UI on port `5866`
72121

73122
If you want to use a different port, such as 8080, update for example the mapping from `5987:5987` to `8080:5987`, where the first value (8080) is the port you can call, and the second (5987) is the actual container port.
74123

@@ -80,20 +129,19 @@ The Docker Compose feature automatically creates the volume, so all you need to
80129

81130
Naming the volume is particularly useful when developing multiple dApps locally, as it allows you to maintain separate states for each project.
82131

83-
Replace `my_dapp` in the configuration with another volume name to suit your needs.
84-
85132
For example, if you are developing a "Hello World" project, you could change the volume name to "hello_world".
86133

87134
```yml title="docker-compose.yml"
88135
services:
89-
juno-satellite:
90-
image: junobuild/satellite:latest
136+
juno-skylab:
137+
image: junobuild/skylab:latest
91138
ports:
92139
- 5987:5987
93140
- 5999:5999
141+
- 5866:5866
94142
volumes:
95143
- hello_world:/juno/.juno # <-------- hello_world modified here
96-
- ./juno.dev.config.json:/juno/juno.dev.config.json
144+
- ./juno.config.ts:/juno/juno.config.ts
97145
- ./target/deploy:/juno/target/deploy/
98146

99147
volumes:
@@ -102,120 +150,6 @@ volumes:
102150
103151
---
104152
105-
## Configuration
106-
107-
The behavior of the Satellite running in the Docker container can be configured with the help of a local configuration file commonly named `juno.dev.config.json`.
108-
109-
This configuration file enables you to define the collections of the Datastore and Storage that run locally, but it also allows for defining additional controllers for your satellite.
110-
111-
The definition is as follows:
112-
113-
```typescript
114-
export type PermissionText = "public" | "private" | "managed" | "controllers";
115-
export type MemoryText = "heap" | "stable";
116-
export type RulesType = "db" | "storage";
117-
118-
export interface Rule {
119-
collection: string;
120-
read: PermissionText;
121-
write: PermissionText;
122-
memory: MemoryText;
123-
createdAt?: bigint;
124-
updatedAt?: bigint;
125-
maxSize?: number;
126-
maxCapacity?: number;
127-
mutablePermissions: boolean;
128-
maxTokens?: number;
129-
}
130-
131-
export type SatelliteDevDbCollection = Omit<
132-
Rule,
133-
"createdAt" | "updatedAt" | "maxSize"
134-
>;
135-
136-
export type SatelliteDevStorageCollection = Omit<
137-
Rule,
138-
"createdAt" | "updatedAt" | "maxCapacity"
139-
>;
140-
141-
export interface SatelliteDevCollections {
142-
db?: SatelliteDevDbCollection[];
143-
storage?: SatelliteDevStorageCollection[];
144-
}
145-
146-
export interface SatelliteDevController {
147-
id: string;
148-
scope: "write" | "admin";
149-
}
150-
151-
export interface SatelliteDevConfig {
152-
collections: SatelliteDevCollections;
153-
controllers?: SatelliteDevController[];
154-
}
155-
156-
export interface JunoDevConfig {
157-
satellite: SatelliteDevConfig;
158-
}
159-
```
160-
161-
### Example
162-
163-
If, for example, we want to configure a "metadata" collection in the Datastore, a "content" collection in the Storage, and provide an additional controller, we could use the following configuration:
164-
165-
```json title="juno.dev.config.json"
166-
{
167-
"satellite": {
168-
"collections": {
169-
"db": [
170-
{
171-
"collection": "metadata",
172-
"read": "managed",
173-
"write": "managed",
174-
"memory": "stable",
175-
"mutablePermissions": true
176-
}
177-
],
178-
"storage": [
179-
{
180-
"collection": "content",
181-
"read": "public",
182-
"write": "public",
183-
"memory": "stable",
184-
"mutablePermissions": true
185-
}
186-
]
187-
},
188-
"controllers": [
189-
{
190-
"id": "535yc-uxytb-gfk7h-tny7p-vjkoe-i4krp-3qmcl-uqfgr-cpgej-yqtjq-rqe",
191-
"scope": "admin"
192-
}
193-
]
194-
}
195-
}
196-
```
197-
198-
### Path and name
199-
200-
The configuration can be placed in a location other than next to the compose file and can be named whatever suits your needs. If you do so, make sure to adapt the compose file accordingly.
201-
202-
```yml title="docker-compose.yml"
203-
services:
204-
juno-satellite:
205-
image: junobuild/satellite:latest
206-
ports:
207-
- 5987:5987
208-
- 5999:5999
209-
volumes:
210-
- my_dapp:/juno/.juno
211-
- /your/custom/path/your_config_file.json:/juno/juno.dev.config.json # <-------- Modify location and file name of the left hand part
212-
213-
volumes:
214-
my_dapp:
215-
```
216-
217-
---
218-
219153
## Usage
220154
221155
During local development, your app connects to the local emulator (container) by default — no extra configuration needed.
@@ -258,6 +192,10 @@ The admin server running on port `5999` provides a variety of internal managemen
258192

259193
### Get ICP
260194

195+
If you're using the full environment, the Console UI includes a "Get ICP" button in the wallet. It’s a quick way to get ICP out of the box.
196+
197+
![A screenshot of the wallet with the Get ICP call to action of Console UI in dev mode](../img/dev-console/wallet.webp)
198+
261199
You might want to transfer some ICP from the ledger to a specified principal, which can be particularly useful when you're just getting started developing your app and no users currently own ICP. This can be achieved by querying:
262200

263201
```
@@ -279,31 +217,3 @@ fi
279217
# Make a transfer request to the admin server
280218
curl "http://localhost:5999/ledger/transfer/?to=$PRINCIPAL"
281219
```
282-
283-
---
284-
285-
## Tips and Tricks
286-
287-
In the local environment, several modules (also known as "canisters" on the Internet Computer) are automatically spun up. This ensures that developers have everything they need to start building right out of the box. Thanks to built-in plugins and tooling, these modules are automatically integrated into the environment, eliminating the need for devs to manually manage their bindings.
288-
289-
However, in some cases, it may be useful to explicitly reference module IDs. Below is a list of the modules and their respective IDs that are automatically mounted.
290-
291-
:::note
292-
293-
Except for the Satellite ID, which differs from your production environment, all other IDs match the actual smart contract IDs on the mainnet.
294-
295-
:::
296-
297-
| Module | ID |
298-
| ------------------------------------------------------------------------------------------------ | ----------------------------- |
299-
| Satellite (local only) | `x5yt-yyaaa-aaaal-abzbq-cai` |
300-
| [Internet Identity](https://dashboard.internetcomputer.org/canister/rdmx6-jaaaa-aaaaa-aaadq-cai) | `rdmx6-jaaaa-aaaaa-aaadq-cai` |
301-
| [ICP Ledger](https://dashboard.internetcomputer.org/canister/ryjl3-tyaaa-aaaaa-aaaba-cai) | `ryjl3-tyaaa-aaaaa-aaaba-cai` |
302-
| [ICP Index](https://dashboard.internetcomputer.org/canister/qhbym-qaaaa-aaaaa-aaafq-cai) | `qhbym-qaaaa-aaaaa-aaafq-cai` |
303-
304-
If you're using the Docker image intended for developing the Console, you get access to some extra modules that we may eventually merge into the development container. Let us know if you're interested!
305-
306-
| Module | ID |
307-
| --------------------------------------------------------------------------------------------- | ----------------------------- |
308-
| [CMC](https://dashboard.internetcomputer.org/canister/rkp4c-7iaaa-aaaaa-aaaca-cai) | `rkp4c-7iaaa-aaaaa-aaaca-cai` |
309-
| [NNS Governance](https://dashboard.internetcomputer.org/canister/rrkah-fqaaa-aaaaa-aaaaq-cai) | `rrkah-fqaaa-aaaaa-aaaaq-cai` |

docs/img/dev-console/login.webp

65.9 KB
Loading

docs/img/dev-console/wallet.webp

96.1 KB
Loading
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Infrastructure
2+
3+
In the local environment, several modules (also known as "canisters" on the Internet Computer) are automatically spun up. This ensures that developers have everything they need to start building right out of the box. Thanks to built-in plugins and tooling, these modules are automatically integrated into the environment, eliminating the need for devs to manually manage their bindings.
4+
5+
However, in some cases, it may be useful to explicitly reference module IDs. Below is a list of the modules and their respective IDs that are automatically mounted.
6+
7+
| Module | ID |
8+
| ------------------------------------------------------------------------------------------------ | ----------------------------- |
9+
| [Internet Identity](https://dashboard.internetcomputer.org/canister/rdmx6-jaaaa-aaaaa-aaadq-cai) | `rdmx6-jaaaa-aaaaa-aaadq-cai` |
10+
| [ICP Ledger](https://dashboard.internetcomputer.org/canister/ryjl3-tyaaa-aaaaa-aaaba-cai) | `ryjl3-tyaaa-aaaaa-aaaba-cai` |
11+
| [ICP Index](https://dashboard.internetcomputer.org/canister/qhbym-qaaaa-aaaaa-aaafq-cai) | `qhbym-qaaaa-aaaaa-aaafq-cai` |
12+
| [CMC](https://dashboard.internetcomputer.org/canister/rkp4c-7iaaa-aaaaa-aaaca-cai) | `rkp4c-7iaaa-aaaaa-aaaca-cai` |
13+
| [NNS Governance](https://dashboard.internetcomputer.org/canister/rrkah-fqaaa-aaaaa-aaaaq-cai) | `rrkah-fqaaa-aaaaa-aaaaq-cai` |

0 commit comments

Comments
 (0)