GitBook: [2.0.0] 24 pages and 33 assets modified
BIN
.gitbook/assets/image (21).png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
.gitbook/assets/image (22).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (23).png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
.gitbook/assets/image (24).png
Normal file
After Width: | Height: | Size: 385 KiB |
BIN
.gitbook/assets/image (25).png
Normal file
After Width: | Height: | Size: 132 KiB |
BIN
.gitbook/assets/image (26).png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
.gitbook/assets/image (27).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (28).png
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
.gitbook/assets/image (29).png
Normal file
After Width: | Height: | Size: 432 KiB |
BIN
.gitbook/assets/image (30).png
Normal file
After Width: | Height: | Size: 486 KiB |
BIN
.gitbook/assets/image (31).png
Normal file
After Width: | Height: | Size: 486 KiB |
BIN
.gitbook/assets/image (32).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (33).png
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
.gitbook/assets/image (34).png
Normal file
After Width: | Height: | Size: 409 KiB |
BIN
.gitbook/assets/image (35).png
Normal file
After Width: | Height: | Size: 549 KiB |
BIN
.gitbook/assets/image (36).png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
.gitbook/assets/image (37).png
Normal file
After Width: | Height: | Size: 195 KiB |
BIN
.gitbook/assets/image (38).png
Normal file
After Width: | Height: | Size: 595 KiB |
BIN
.gitbook/assets/image (39).png
Normal file
After Width: | Height: | Size: 502 KiB |
BIN
.gitbook/assets/image (40).png
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
.gitbook/assets/image (41).png
Normal file
After Width: | Height: | Size: 385 KiB |
BIN
.gitbook/assets/image (42).png
Normal file
After Width: | Height: | Size: 409 KiB |
BIN
.gitbook/assets/image (43).png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
.gitbook/assets/image (44).png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
.gitbook/assets/image (45).png
Normal file
After Width: | Height: | Size: 578 KiB |
BIN
.gitbook/assets/image (46).png
Normal file
After Width: | Height: | Size: 578 KiB |
BIN
.gitbook/assets/image (47).png
Normal file
After Width: | Height: | Size: 296 KiB |
BIN
.gitbook/assets/image (48).png
Normal file
After Width: | Height: | Size: 438 KiB |
BIN
.gitbook/assets/image (49).png
Normal file
After Width: | Height: | Size: 483 KiB |
BIN
.gitbook/assets/image (50).png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
.gitbook/assets/image (51).png
Normal file
After Width: | Height: | Size: 418 KiB |
BIN
.gitbook/assets/image (52).png
Normal file
After Width: | Height: | Size: 502 KiB |
BIN
.gitbook/assets/image (53).png
Normal file
After Width: | Height: | Size: 595 KiB |
@ -3,7 +3,10 @@
|
||||
* [Introduction](README.md)
|
||||
* [Thinking In Aquamarine](p2p.md)
|
||||
* [Concepts](concepts.md)
|
||||
* [Quick Start](quick-start.md)
|
||||
* [Quick Start](quick-start/README.md)
|
||||
* [1. Browser-to-Browser](quick-start/1.-browser-to-browser-1.md)
|
||||
* [2. Hosted Services](quick-start/2.-hosted-services.md)
|
||||
* [3. Browser-to-Service](quick-start/3.-browser-to-service.md)
|
||||
* [Aquamarine](knowledge_aquamarine/README.md)
|
||||
* [Aqua](knowledge_aquamarine/hll.md)
|
||||
* [Marine](knowledge_aquamarine/marine/README.md)
|
||||
|
66
quick-start/1.-browser-to-browser-1.md
Normal file
@ -0,0 +1,66 @@
|
||||
# 1. Browser-to-Browser
|
||||
|
||||
The first example demonstrates how to communicate between two client peers, i.e. browsers, with local services. The project is based on a create-react-app template with slight modifications to integrate Fluence. The primary focus is the integration itself and React could be swapped with any framework of your choice.
|
||||
|
||||
In your VSCode container terminal, make sure you are in the `examples/quickstart/1-browser-to-browser` directory to install the dependencies:
|
||||
|
||||
```text
|
||||
cd examples/quickstart/1-browser-to-browser
|
||||
npm install
|
||||
```
|
||||
|
||||
Run the app with `npm start` :
|
||||
|
||||
```text
|
||||
npm start
|
||||
```
|
||||
|
||||
Which opens a new tab in your browser at `http://localhost:3000`. Depending on your VSCode settings, you may have to confirm your choice.
|
||||
|
||||
The browser tab, representing the client peer, wants you to pick a relay node the browser client can connected to and, of course, allows the peer to respond to the browser client. Select any one of the offered relays:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
The client peer is now connected to the relay and and ready for business:
|
||||
|
||||

|
||||
|
||||
Let's follow the instructions, open another browser tab, i.e. client peer, using `http://localhost:3000` , select any one of the relays and copying the ensuing peer id and relay peer id to the first client peer, i.e. the first browser tab, and click the `say hello` button:
|
||||
|
||||
|
||||

|
||||
|
||||
Congratulations, you just sent messages between two browsers over the Fluence peer-to-peer network, which is pretty cool ! Even cooler, however, is how we got here using Aqua, Fluence's distributed network and application composition language.
|
||||
|
||||
In your VSCode workspace, navigate to the `aqua` directory and open the \``getting-started.aqua` file in VSCode:
|
||||
|
||||

|
||||
|
||||
And yes, fewer than ten lines \(!!\) are required for a client peer, like our browser, to connect to the network and start composing the local `HelloPeer` service to send messages.
|
||||
|
||||
In broad strokes, the Aqua code breaks down as follows:
|
||||
|
||||
* Import the Aqua [standard library](https://github.com/fluencelabs/aqua-lib) into our application \(1\)
|
||||
* Create a service interface binding to the local service \(see below\) with the `HelloPeer` namespace and `hello` function \(4-5\)
|
||||
* Create the composition function `sayHello` that executes the `hello` call on the provided `targetPeerId` via the provided `targetRelayPeerId` and returns the result \(7-10\). Recall the copy and paste job you did earlier in the browser tab for the peer and relay id ? Well, you just found the consumption place for these two parameters.
|
||||
|
||||
Not only is Aqua rather succinct in allowing you to seamlessly program both network routes and distributed application workflows but also provides the ability to compile Aqua to Typescript stubs wrapping compiled Aqua, called AIR -- short for Aqua Intermediate Representation, into ready to use code blocks. Navigate to the `src/_aqua` directory and open the `getting-started.ts` file in VSCode:
|
||||
|
||||

|
||||
|
||||
Which can now be imported into our `App.tsx` file:
|
||||
|
||||

|
||||
|
||||
Lest it be overlooked, we wrote a little more than a handful of lines of code in Aqua and ended up with a deployment ready code block that includes both the network routing and compute logic to facilitate browser-to-browser messaging over a peer-to-peer network.
|
||||
|
||||
The local \(browser\) service `HelloPeer` is also implemented in the `App.tsx` file:
|
||||
|
||||

|
||||
|
||||
To summarize, we run an app that facilities messaging between two browsers over a peer-to-peer network. At the core of this capability is Aqua which allowed us in just a few lines of code to program both the network topology and the application workflow in barely more than a handful of lines of code. Hint: You should be excited. For more information on Aqua, see the [Aqua Book](https://app.gitbook.com/@fluence/s/aqua-book/).
|
||||
|
||||
In the next section, we develop a Wasm module and deploy it as a hosted service to the Fluence peer-to-peer network.
|
||||
|
186
quick-start/2.-hosted-services.md
Normal file
@ -0,0 +1,186 @@
|
||||
# 2. Hosted Services
|
||||
|
||||
In the previous example we used a local, browser-native service to facilitate the string generation and communication with another browser. The real power of the Fluence solution, however, is that services can be hosted one one or more nodes, easily reused and composed into decentralized applications with Aqua.
|
||||
|
||||
### Creating A Wasm Module
|
||||
|
||||
In this section, we develop a simple `HelloWorld` service and host it on a peer-to-peer node of the Fluence testnet. In your VSCode IDE, change to the `2-hosted-services` directory and open the `src/main.rs` file:
|
||||
|
||||

|
||||
|
||||
Fluence hosted services are comprised of WebAssembly modules implemented in Rust and compiled to [wasm32-wasi](https://doc.rust-lang.org/stable/nightly-rustc/rustc_target/spec/wasm32_wasi/index.html). Let's have look at our code:
|
||||
|
||||
```text
|
||||
// quickstart/2-hosted-services/src/main.rs
|
||||
use marine_rs_sdk::marine;
|
||||
use marine_rs_sdk::module_manifest;
|
||||
|
||||
module_manifest!();
|
||||
|
||||
pub fn main() {}
|
||||
|
||||
#[marine]
|
||||
pub struct HelloWorld {
|
||||
pub msg: String,
|
||||
pub reply: String,
|
||||
}
|
||||
|
||||
#[marine]
|
||||
pub fn hello(from: String) -> HelloWorld {
|
||||
HelloWorld {
|
||||
msg: format!("Hello from: \n{}", from),
|
||||
reply: format!("Hello back to you, \n{}", from),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
At the core of our implementation is the `hello` function which takes a string parameter and returns the `HelloWorld` struct consisting of the `msg` and `reply` field, respectively. We can use the `build.sh` script in the `scripts` directory, `./scripts/build.sh` , to compile the code to the Wasm target from the VSCode terminal:
|
||||
|
||||

|
||||
|
||||
Aside from some housekeeping, the `build.sh` script gives the compile instructions with [marine](https://crates.io/crates/marine), `marine build --release` , and copies the resulting Wasm module, `hello_world.wasm`, to the `artifacts` directory for easy access.
|
||||
|
||||
### Testing And Exploring Wasm Code
|
||||
|
||||
So far, so good. Of course, we want to test our code and we have a couple of test functions in our `main.rs` file:
|
||||
|
||||
```text
|
||||
// quickstart/2-hosted-services/src/main.rs
|
||||
use marine_rs_sdk::marine;
|
||||
use marine_rs_sdk::module_manifest;
|
||||
|
||||
//<snip>
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use marine_rs_sdk_test::marine_test;
|
||||
|
||||
#[marine_test(config_path = "../configs/Config.toml", modules_dir = "../artifacts")]
|
||||
fn non_empty_string() {
|
||||
let actual = hello_world.hello("SuperNode".to_string());
|
||||
assert_eq!(actual.msg, "Hello from: \nSuperNode".to_string());
|
||||
}
|
||||
|
||||
#[marine_test(config_path = "../configs/Config.toml", modules_dir = "../artifacts")]
|
||||
fn empty_string() {
|
||||
let actual = hello_world.hello("".to_string());
|
||||
assert_eq!(actual.msg, "Hello from: \n");
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
To run our tests, we can use the familiar[`cargo test`](https://doc.rust-lang.org/cargo/commands/cargo-test.html) . However, we don't really care all that much about our native Rust functions being tested but want to test our WebAssembly functions. This is where the extra code in the test module comes into play. In short., we are running `cargo test` against the exposed interfaces of the `hello_world.wasm` module and in order to do that, we need the `marine_test` macro and provide it with both the modules directory, i.e., the `artifacts` directory, and the location of the `Config.toml` file. Note that the `Config.toml` file specifies the module meta data and optional module linking data. Moreover, we need to call our Wasm functions from the module namespace, i.e. `hello_world.hello` instead of the standard `hello` -- see lines 13 and 19 above.
|
||||
|
||||
From the VSCode terminal, we now run our tests with the`cargo +nightly test --release` command. Please note that if `nightly` is your default, you don't need it in your `cargo test` command.
|
||||
|
||||

|
||||
|
||||
Well done -- our tests check out. Before we deploy our service to the network, we can interact with it locally using the [Marine REPL](https://crates.io/crates/mrepl). In your VSCode terminal the `2-hosted-services` directory run:
|
||||
|
||||
```text
|
||||
mrepl configs/Config.toml
|
||||
```
|
||||
|
||||
which puts us in the REPL:
|
||||
|
||||
```text
|
||||
Welcome to the Marine REPL (version 0.8.0)
|
||||
Minimal supported versions
|
||||
sdk: 0.6.0
|
||||
interface-types: 0.20.0
|
||||
|
||||
New version is available! 0.8.0 -> 0.9.0
|
||||
To update run: cargo +nightly install mrepl --force
|
||||
|
||||
app service was created with service id = 72531b56-8856-4d91-8ff3-f2e55f4717c4
|
||||
elapsed time 80.6251ms
|
||||
|
||||
1> i
|
||||
Loaded modules interface:
|
||||
data HelloWorld:
|
||||
msg: string
|
||||
reply: string
|
||||
|
||||
hello_world:
|
||||
fn hello(from: string) -> HelloWorld
|
||||
|
||||
2> call hello_world hello ["Fluence"]
|
||||
result: Object({"msg": String("Hello from: \nFluence"), "reply": String("Hello back to you, \nFluence")})
|
||||
elapsed time: 278.5µs
|
||||
|
||||
3>
|
||||
```
|
||||
|
||||
We can explore the available interfaces with the `i` command and see that the interfaces we marked with the `marine` macro in our Rust code above are indeed exposed and available for consumption. Using the `call` command, still in the REPL, we can access any available function in the module namespace, e.g., `call hello_word hello [<string arg>]`. You can exit the REPL with the `ctrl-c` command.
|
||||
|
||||
### Exporting Wasm Interfaces To Aqua
|
||||
|
||||
In anticipation of future needs, note that `marine` allows us to export the Wasm interfaces ready for use in Aqua. In your VSCode terminal, navigate to the \`\` directory
|
||||
|
||||
```text
|
||||
marine aqua artifacts/hello_world.wasm
|
||||
```
|
||||
|
||||
Which gives us the Aqua-ready interfaces:
|
||||
|
||||
```text
|
||||
data HelloWorld:
|
||||
msg: string
|
||||
reply: string
|
||||
|
||||
service HelloWorld:
|
||||
hello(from: string) -> HelloWorld
|
||||
```
|
||||
|
||||
That can be piped directly into an aqua file , e.g., \``marine aqua my_wasm.wasm >> my_aqua.aqua`.
|
||||
|
||||
### Deploying A Wasm Module To The Network
|
||||
|
||||
Looks like all is in order with our module and we are ready to deploy our `HelloWorld` service to the world by means of the Fluence peer-to-peer network. For this to happen, we need two things: the peer id of our target node\(s\) and a way to deploy the service. The latter can be accomplished with the `fldist` command line tool and with respect to the former, we can get a peer from one of the Fluence testnets also with `fldist` . In your VSCode terminal:
|
||||
|
||||
```text
|
||||
fldist env
|
||||
```
|
||||
|
||||
Which gets us a list of network peers:
|
||||
|
||||
```text
|
||||
/dns4/kras-00.fluence.dev/tcp/19990/wss/p2p/12D3KooWSD5PToNiLQwKDXsu8JSysCwUt8BVUJEqCHcDe7P5h45e
|
||||
/dns4/kras-00.fluence.dev/tcp/19001/wss/p2p/12D3KooWR4cv1a8tv7pps4HH6wePNaK6gf1Hww5wcCMzeWxyNw51
|
||||
/dns4/kras-01.fluence.dev/tcp/19001/wss/p2p/12D3KooWKnEqMfYo9zvfHmqTLpLdiHXPe4SVqUWcWHDJdFGrSmcA
|
||||
/dns4/kras-02.fluence.dev/tcp/19001/wss/p2p/12D3KooWHLxVhUQyAuZe6AHMB29P7wkvTNMn7eDMcsqimJYLKREf
|
||||
/dns4/kras-03.fluence.dev/tcp/19001/wss/p2p/12D3KooWJd3HaMJ1rpLY1kQvcjRPEvnDwcXrH8mJvk7ypcZXqXGE
|
||||
/dns4/kras-04.fluence.dev/tcp/19001/wss/p2p/12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi
|
||||
/dns4/kras-05.fluence.dev/tcp/19001/wss/p2p/12D3KooWCMr9mU894i8JXAFqpgoFtx6qnV1LFPSfVc3Y34N4h4LS
|
||||
/dns4/kras-06.fluence.dev/tcp/19001/wss/p2p/12D3KooWDUszU2NeWyUVjCXhGEt1MoZrhvdmaQQwtZUriuGN1jTr
|
||||
/dns4/kras-07.fluence.dev/tcp/19001/wss/p2p/12D3KooWEFFCZnar1cUJQ3rMWjvPQg6yMV2aXWs2DkJNSRbduBWn
|
||||
/dns4/kras-08.fluence.dev/tcp/19001/wss/p2p/12D3KooWFtf3rfCDAfWwt6oLZYZbDfn9Vn7bv7g6QjjQxUUEFVBt
|
||||
/dns4/kras-09.fluence.dev/tcp/19001/wss/p2p/12D3KooWD7CvsYcpF9HE9CCV9aY3SJ317tkXVykjtZnht2EbzDPm
|
||||
```
|
||||
|
||||
Let's use the peer`12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi` as our deployment target and deploy our service from the VSCode terminal. In the `quickstart/2-hosted-services` directory run:
|
||||
|
||||
```text
|
||||
fldist --node-id 12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi \
|
||||
new_service \
|
||||
--ms artifacts/hello_world.wasm:configs/hello_world_cfg.json \
|
||||
--name hello-world
|
||||
```
|
||||
|
||||
Which gives us a unique service id:
|
||||
|
||||
```text
|
||||
service id: 1e740ce4-81f6-4dd4-9bed-8d86e9c2fa50
|
||||
service created successfully
|
||||
```
|
||||
|
||||
Take note of the service id, `1e740ce4-81f6-4dd4-9bed-8d86e9c2fa50` in this examples but different for you, as we need it to use the service with Aqua.
|
||||
|
||||
Congratulations, we just deployed our first reusable service to the Fluence network and we can admire our handiwork on the Fluence [Developer Hub](https://dash.fluence.dev/):
|
||||
|
||||

|
||||
|
||||
With our newly created service ready to roll, let's move on and put it to work.
|
||||
|
45
quick-start/3.-browser-to-service.md
Normal file
@ -0,0 +1,45 @@
|
||||
# 3. Browser-to-Service
|
||||
|
||||
In the first section, we explored browser-to-browser messaging using local, i.e. browser-native, services and the Fluence network for message transport. In the second section, we developed a `HelloWorld` Wasm module and deployed it as a hosted service on the testnet peer `12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi` with service id `1e740ce4-81f6-4dd4-9bed-8d86e9c2fa50` . We can now extend our browser-to-browser messaging application with our hosted service.
|
||||
|
||||
Let's navigate to the `3-browser-to-service` directory in the VSCode terminal and install the dependencies:
|
||||
|
||||
```text
|
||||
npm install
|
||||
```
|
||||
|
||||
And run the application with:
|
||||
|
||||
```text
|
||||
npm start
|
||||
```
|
||||
|
||||
Which will open a new browser tab at `http://localhost:3000` . Following the instructions we connect to any one of the displayed relay ids, open another browser tab also at `http://localhost:3000`, select a relay and copy and paste the client peer id and relay id into corresponding fields in the first tab and press the `say hello` button.
|
||||
|
||||

|
||||
|
||||
The result looks familiar, so what's different ? Let's have a look at the Aqua file. Navigate to the `aqua/getting_started.aqua` file in your IDE:
|
||||
|
||||

|
||||
|
||||
And let's work it from the top:
|
||||
|
||||
* Import the the Aqua standard library \(1\)
|
||||
* Provide the hosted service peer id \(3\) and service id \(4\)
|
||||
* Specify the `HelloWorld` struct interface binding \(6-8\) for the hosted service from the `marine aqua` export
|
||||
* Specify the `HelloWorld` interface and function binding \(11-12\) for the hosted service from the `marine aqua` export
|
||||
* Specify the `HelloPeer` interface and function binding \(15-16\) for the local service
|
||||
* Create the Aqua workflow function `sayHello` \(18-29\)
|
||||
|
||||
Before we dive into the `sayHelo` function, let's look at why we still need a local service even though we deployed a hosted service. The reason for that lies in the need for the browser client to be able to consume the message sent from the other browser through the relay peer. With that out of the way, let's dig in:
|
||||
|
||||
* The function signature \(18\) takes two arguments: `targetPeerId`, which is the client peer id of the other browser and the `targetelayPeerId`, which is the relay id -- both parameters are the values you copy and pasted from the second browser tab into the first browser tab
|
||||
* The first step is to call on the hosted service `HelloWorld` on the host peer `helloWorldPeerId` , which we specified in line 1
|
||||
* We bind the `HelloWorld` interface, on the peer `helloWorldPeerId`, i.e.,`12D3KooWFEwNWcHqi9rtsmDhsYcDbRUCDXH84RC4FW6UfsFWaoHi`, to the service id of the hosted service `helloWorldServiceId` , i.e. `1e740ce4-81f6-4dd4-9bed-8d86e9c2fa50`, which takes the %init\__peer\__id% parameter, i.e., the peer id of the peer that initiated the request, and pushes the result into `comp` \(20-22\)
|
||||
* We now want to send a result back to the target browser \(peer\) \(25-26\) using the local service via the `targetRelayPeerId` in the background as a `co` routine.
|
||||
* Finally, we send the `comp` result to the initiating browser
|
||||
|
||||
A little more involved than our first example but we are again getting a lot done with very little code. Of course, there could be more than one hosted service in play and we could implement, for example, hosted spell checking, text formatting and so much more without much extra effort to express additional workflow logic in our Aqua script.
|
||||
|
||||
This brings us to the end of this quick start tutorial. We hope you are as exited as we are to put Aqua and the Fluence stack to work. To continue your Fluence journey, have a look at the remainder of this book, take a deep dive into Aqua with the [Aqua book](https://doc.fluence.dev/aqua-book/) or dig into Marine and Aqua examples in the [repo](https://github.com/fluencelabs/examples).
|
||||
|
49
quick-start/README.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Quick Start
|
||||
|
||||
Welcome to our quick-start tutorials which guide you through the necessary steps to
|
||||
|
||||
1. Create a browser-to-browser messaging web application
|
||||
2. Create and deploy a hosted service
|
||||
3. Create a browser-to-service messaging web application
|
||||
|
||||
For your development convenience, Fluence provides a [docker-based development environment](https://github.com/fluencelabs/devcontainer) that comes with the necessary dependencies, tooling and quick-start code pre-installed.
|
||||
|
||||
### Fluence Devcontainer
|
||||
|
||||
Fluence's devcontainer is a ready to use dockerized development environment with VSCode integration containing the following tools:
|
||||
|
||||
* [`aqua-cli`](https://www.npmjs.com/package/@fluencelabs/aqua-cli) to compile [Aqua](https://doc.fluence.dev/aqua-book/) to AIR or wrapped in Typescript
|
||||
* [`fldist`](https://www.npmjs.com/package/@fluencelabs/fldist) to manage services and optionally execute compiled Aqua from the command line
|
||||
* [`marine`](https://crates.io/crates/marine) to compile services developed in Rust to the wasm32-wasi target
|
||||
* [`mrepl`](https://crates.io/crates/mrepl) to run, test and debug WebAssembly \(Wasm\) services locally
|
||||
|
||||
### How to install
|
||||
|
||||
Docker and optionally VSCode need to be available on your system. For Docker installation, follow the [Get Docker](https://docs.docker.com/get-docker/) instructions for your OS. For VSCode, see [VSCocde](https://code.visualstudio.com/) for instructions.
|
||||
|
||||
With Docker and VSCode in place:
|
||||
|
||||
* Install Remote-Containers extension in VSCode
|
||||
|
||||

|
||||
|
||||
* `Run Remote-Containers: Clone Repository in Container Volume...` via the command palette \(F1 or Cmd-Shift-P\)
|
||||
|
||||

|
||||
|
||||
* Enter `fluencelabs/devcontainer`
|
||||
|
||||

|
||||
|
||||
* When asked for branch, press enter \(main\)
|
||||
* When asked for volume, press enter \(unique\)
|
||||
* open Terminal within VSCode \(ctrl-\`\)
|
||||
|
||||

|
||||
|
||||
Congratulations, you now have a fully functional Fluence development environment. For a variety of container management options, click on the `Dev Container: Fluence` button in the lower left of your tool bar:
|
||||
|
||||

|
||||
|
||||
If you encounter any problems or have suggestions, please open an issue or submit a PR. You can also reach out in [Discord](https://fluence.chat) or [Telegram](https://t.me/fluence_project). For more detailed reference resources, see the [Fluence documentation](https://doc.fluence.dev/docs/) and [Aqua book](https://doc.fluence.dev/aqua-book/).
|
||||
|