# Development
Your new bare-bones project includes minimal organization with a single `main.rs` file and a few assets.
```
project/
├─ assets/ # Any assets that are used by the app should be placed here
├─ src/
│ ├─ main.rs # main.rs is the entry point to your application and currently contains all components for the app
├─ Cargo.toml # The Cargo.toml file defines the dependencies and feature flags for your project
```
### Serving Your App
Run the following command in the root of your project to start developing with the default platform:
```bash
dx serve
```
To run for a different platform, use the `--platform platform` flag. E.g.
```bash
dx serve --platform desktop
```
## Configuration (appsettings.json and WASM fast-path)
This project supports an `appsettings.json`-style configuration that is loaded at runtime.
- Native (desktop/server): the app tries to read `appsettings.json` from the working directory.
- WASM (web): the loader will first try a small HTML-injection fast-path (see below). If that
is not present it will fetch `appsettings.json` from the hosting origin.
Example `appsettings.json`:
```json
{
"server": {
"stun_server": "stun:stun.l.google.com:19302"
}
}
```
HTML injection fast-path (for embedding a small config directly in `index.html`):
```html
```
This is useful for static hosting scenarios where you want to provide a different runtime
configuration without rebuilding the WASM artifact.
## Consuming the Config in the UI (Dioxus)
The Dioxus app provides a `Signal` via the hooks context. Child components can consume
it with:
```rust
let cfg_signal = use_context::>();
let cfg = cfg_signal.get(); // or cfg_signal.read()/() depending on the signal API
// use cfg.server.stun_server
```
The app uses an async loader (via `use_resource`) and overwrites the initial default config when
the runtime-loaded config becomes available. This gives instant sensible defaults while still
allowing runtime overrides.
### Example: Provider + Consumer (Dioxus)
Below is a minimal example showing how the app creates a `Signal` provider and how a
child component consumes it. This pattern gives children an immediately-available default
config while an async fetch can replace it at runtime.
```rust
use dioxus::prelude::*;
use dioxus_hooks::use_resource;
use niom_webrtc::config;
#[allow(non_snake_case)]
fn ConfigProvider(cx: Scope) -> Element {
// synchronous immediate default
let default_cfg = config::load_config_sync_or_default();
// a reactive signal holding the current config
let cfg_signal = use_state(cx, || default_cfg.clone());
// async resource that loads runtime config (WASM fetch or native file)
let resource = use_resource(cx, (), |_| async move { config::load_config_or_default().await });
// when resource completes, update the signal so children react
if let Some(cfg) = resource.value() {
cfg_signal.set(cfg.clone());
}
// provide the signal to descendants
use_context_provider(cx, || cfg_signal.clone());
cx.render(rsx! { children(&cx) })
}
fn SomeChild(cx: Scope) -> Element {
let cfg_signal = use_context::>(cx);
let cfg = cfg_signal.get();
cx.render(rsx!(div { "STUN: {cfg.server.stun_server}" }))
}
```
Notes:
- `load_config_sync_or_default()` returns a sensible default immediately (plus HTML fast-path on WASM).
- `load_config_or_default()` is async and will perform a network fetch on WASM if the HTML fast-path wasn't present.