# Apps and Plugins
`App` owns everything: the ECS world, resources, the registered systems, and the runner that drives the main loop. You build one by chaining calls, then hand it off:
```rust
use pebble::prelude::*;
fn main() {
App::new()
.add_plugin(MyWindowPlugin)
.add_plugin(MyBackendPlugin)
.add_plugin(MyGamePlugin)
.build()
.run();
}
```
## Plugins are the unit of composition
A `Plugin` is anything implementing one method:
```rust
pub trait Plugin {
fn build(&self, app: &mut App);
}
```
That's the entire extension point. Windowing, the graphics backend, every asset type, and your own game-specific setup are all just plugins. `build` receives `&mut App` and can add resources, register systems, or queue further plugins — plugins can register other plugins, and `App::build()` keeps draining the queue (up to a hard limit of 64 passes, to catch an accidental registration cycle) until nothing new shows up.
Here's a minimal one, from the `orbit_camera` example:
```rust
struct TimePlugin;
impl Plugin for TimePlugin {
fn build(&self, app: &mut App) {
app.add_resource(Time {
time: Instant::now(),
last_time: Instant::now(),
delta_time: 0.0,
})
.add_system(SystemStage::PreUpdate, update_delta_time);
}
}
```
Nothing here is special-cased by the framework — `TimePlugin` uses exactly the two calls (`add_resource`, `add_system`) available to any other code with a `&mut App`. Writing your own plugins is how you organize a real project: one plugin per subsystem (input, camera, physics, UI), each self-contained, added to `App` in `main` in whatever order makes sense.
## What `build()` actually does
Three things, in order:
1. Runs every queued plugin's `build`, repeating until no plugin queues another.
2. **Validates resource requirements.** Every system's declared dependencies (see [Resources](./resources.md)) are checked against what plugins have declared they'll eventually provide. A system requiring a resource that nothing will ever insert is a near-certain bug — `build()` panics immediately, naming every offending system and resource, rather than letting it surface as a runtime panic several ticks into `run()`.
3. **Settles the asset pipeline as far as it can go synchronously** (see [The Asset Pipeline and Handles](./the-asset-pipeline.md)) — so resources that don't need to wait for anything asynchronous (a GPU backend arriving on another thread, say) are ready the moment `build()` returns, not one tick later.
`run()` is deliberately thin: it hands `self` to whatever runner is currently installed and does nothing else. The default runner just loops `app.update()` forever; a window plugin normally replaces it with one that also pumps the OS event loop (see [Windows and Backends](./windows-and-backends.md)).
## There is no "Startup" stage
Pebble has a `Startup` stage for one-time initialization. Anything that should run once anywhere else is an ordinary system that returns `Option<()>`, covered in [Systems and Stages](./systems-and-stages.md#run-once) — `Some(())` retires the system permanently, `None` retries next tick.