Tutorials & Beginner-First Jul 19, 2026

Your First Bevy 0.19 BSN Scene - One Evening 2026

Your first Bevy 0.19 BSN scene in one evening - bsn! macro, Children, scene functions, spawn_scene vs queue_spawn_scene, and the no .bsn loader caveat.

By GamineAI Team

Your First Bevy 0.19 BSN Scene - One Evening 2026

Pixel-art animal space series thumbnail - a calm first evening with Bevy Scene Notation

Spawning a nested Bevy UI tree used to feel like writing a packing list for a camping trip you did not want to take - every asset handle, every child tuple, every ..Default::default(), threaded through setup systems that knew too much. Bevy 0.19 (released June 19, 2026 per the official release notes) finally ships Next Generation Scenes and BSN (Bevy Scene Notation) so you can describe entity trees in a Rust-like bsn! macro and spawn them with spawn_scene instead of manual ECS soup.

This is a beginner-first evening tutorial, not an engine adoption lock and not a schedule-debug playbook. It teaches one honest path: install 0.19, write a bsn! scene, spawn it, understand Children and scene functions, then file a receipt. It also states the caveat release notes put in bold - Bevy 0.19 does not ship a first-party .bsn asset loader yet. Code-driven BSN is the 0.19 workflow; asset files come later.

Why this matters now: BSN is the headline of 0.19's scene rewrite. Feathers widgets migrated to BSN. Community coverage is already framing 0.19 as a Godot-contender moment for Rust indies. Micro-studios that wait for the .bsn loader before trying the macro miss the part that is already useful tonight.

Evidence note: Primary keyword bevy bsn. Demand signals include Bevy's GitHub engagement and 0.19 BSN-focused video coverage. SERP gap: official notes and migration guides explain the system; beginners need a one-evening path with the loader caveat, a UI spawn example, and gates - not another Bevy 0.17 platformer weekend or schedule hitch debug.

Non-repetition: Distinct from 0.17 required-components platformer work and from fest-demo schedule debugging. This URL owns 0.19 BSN first evening.

Who this evening is for

Audience Outcome
Creators / beginners A zero-to-window path with bsn!, Children, and .spawn()
Developers spawn_scene vs queue_spawn_scene, patches, SceneComponent intro, migration rename notes
Companies Diligence language for "we adopted BSN code-first; asset loader still pending"
Search Primary keyword bevy bsn with Bevy 0.19 and bsn! secondary intent

Time: about 2-3 hours for a first scene, including reading the caveats twice. Prerequisites: Rust toolchain, cargo, willingness to use Bevy 0.19 (not 0.17), and a blank project. If you are still on 0.17 required-components headaches, keep the required-components panic help nearby - different problem, different night.

What BSN is (30-second answer)

BSN (Bevy Scene Notation) is an ergonomic Rust-like scene syntax. In 0.19 you define it in Rust with the bsn! macro. The same notation is designed for future .bsn asset files, but the first-party asset loader is not in 0.19 yet (Next Generation Scenes notes and the source release notes).

A bsn! expression is essentially a list of components (and relationships) for an entity. Unlike a plain Bundle, BSN adds optional fields without ..Default::default(), first-class Children, composable patches, scene functions, templates for asset paths, and more.

Direct answer: Tonight you write bsn! { ... }, return impl Scene or impl SceneList, and spawn with commands.spawn_scene(...) or .spawn() on a scene function - you do not wait for a .bsn file on disk.

Prerequisites checklist

  • [ ] Rust + cargo installed
  • [ ] New crate with bevy = "0.19" (exact patch per crates.io when you start)
  • [ ] Read the 0.18 → 0.19 migration guide if upgrading an existing project
  • [ ] Accept the no first-party .bsn loader limit for this release
  • [ ] A named evening owner who will file the receipt

Beginner path - one evening to a spawned BSN scene

Step 1 - Create the project

cargo new bevy_bsn_evening
cd bevy_bsn_evening

In Cargo.toml:

[dependencies]
bevy = "0.19"

Run cargo build once so you feel the compile wall early, not at 11pm.

Step 2 - Minimal app with a SceneList

Bevy 0.19 ships a helper that turns a function returning Scene or SceneList into a Startup system via .spawn(). The official release notes show a fully self-contained pattern:

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, level.spawn())
        .run();
}

fn level() -> impl SceneList {
    bsn_list![
        Camera2d,
        // Add your first scene entities here
    ]
}

bsn_list! builds a list of entities. bsn! builds one entity. Start with a camera so the window is not a black void of confusion.

Step 3 - Your first bsn! entity with Children

Add a simple custom component and a child - this is the "I get it" moment from the official docs:

#[derive(Component, Default, Clone)]
struct Player {
    score: usize,
    coins: usize,
}

#[derive(Component, Default, Clone)]
struct Sword;

#[derive(Component, Default, Clone)]
struct Shield;

fn player() -> impl Scene {
    bsn! {
        Player { score: 0 }
        Children [
            Sword,
            Shield,
        ]
    }
}

Optional fields matter: you set score only; coins takes its default. No ..Default::default() ceremony.

Wire it into the level:

fn level() -> impl SceneList {
    bsn_list![
        Camera2d,
        { player() },
    ]
}

Or spawn from a Commands system if you prefer the explicit form shown throughout the release notes:

fn setup(mut commands: Commands) {
    commands.spawn_scene(player());
}

Step 4 - A UI-shaped Node tree (still code-driven)

BSN is especially nice for Bevy UI. Field position supports ergonomic helpers like px(2) for values that convert into UI types. A teaching-shaped panel (adjust exact UI components to match your 0.19 patch docs if names shift):

fn hud() -> impl Scene {
    bsn! {
        Node {
            width: percent(100),
            height: percent(100),
            justify_content: JustifyContent::Center,
            align_items: AlignItems::Center,
        }
        Children [
            Node {
                width: px(240),
                height: px(64),
                justify_content: JustifyContent::Center,
                align_items: AlignItems::Center,
            }
            BackgroundColor(Color::srgb(0.15, 0.2, 0.35))
            Children [
                Text::new("Hello BSN"),
            ]
        ]
    }
}

If Text::new vs Text("...") differs in your exact crate version, follow the compiler and the Bevy 0.19 notes Feathers examples - the point is the Children nesting, not winning a syntax trivia fight.

Add { hud() } to your bsn_list! and run:

cargo run

Pass: window opens, camera exists, Player/Sword/Shield hierarchy is queryable, HUD nodes appear. Fail: compile errors about missing Default/Clone on components - derive them; BSN templates lean on those for pass-through types.

Step 5 - File the evening receipt

Do not call the night done because the window opened. File bevy_019_bsn_scene_receipt_v1.json (schema below) and latch bevy_bsn_ok only when gates B1–B6 are green.

Observing events inside BSN

BSN can embed observer-style callbacks in the scene declaration. Official release notes show a button that logs on pointer press:

fn pressable_panel() -> impl Scene {
    bsn! {
        Node { width: px(100), height: px(50) }
        on(|press: On<Pointer<Press>>| {
            info!("panel pressed!");
        })
    }
}

That matters for indie evenings because it keeps "what exists" and "what happens on click" in one place instead of a spawn call plus a separate .observe(...) chain three functions away. Feathers widgets in 0.19 follow the same idea - caption, extra components, and observers can live in one bsn! block (Feathers + BSN section).

Teaching shape (names follow release-note examples - confirm against your patch):

bsn! {
    @FeathersCheckbox {
        @caption: bsn! { Text("Enable shadows") ThemedText }
    }
    MyCheckbox
    on(|change: On<ValueChange<bool>>, mut config: ResMut<ShadowConfig>| {
        config.enabled = change.value;
    })
}

You do not need Feathers to finish tonight. Treat this as the "evening two" preview once player() and hud() are green.

Entity references and Name shortcuts

BSN can name entities with #FirstPlayer syntax, which is sugar for a Name component and also enables references elsewhere in the same bsn! scope:

bsn! {
    #Root
    Children [
        // Custom component holding an Entity - requires FromTemplate when not Default+Clone pass-through
    ]
}

Use this when you are building small graphs (A points to B points to A) with bsn_list!. For night one, stick to Children. Reach for #Name when you catch yourself spawning anonymous entities you cannot find in a debugger.

Troubleshooting compile and runtime fails

Symptom Likely cause Fix
Missing Template / FromTemplate errors Component lacks Default+Clone and needs richer templates Derive Default, Clone first; derive FromTemplate only when you need template features
Scene asset path fails at spawn Using :"player.bsn" without a loader Stay code-driven in 0.19; do not fake asset files
Hierarchy empty after spawn Spawned a Bundle path by mistake, or forgot Children syntax Confirm spawn_scene / .spawn() and Children [ ... ]
UI invisible No camera, zero-size Node, or wrong color contrast Keep Camera2d in the bsn_list!; give Nodes explicit px sizes
Upgrade project will not compile Old scene crate names / glTF path assumptions Follow 0.18→0.19 migration; keep old serialization for round-trips

Also keep Bevy hot-reload PNG watcher help bookmarked if your evening expands into sprite assets - that is a 0.17-era symptom that still bites iteration loops.

BSN vs Bundle - when to switch

Situation Prefer
New UI tree or prefab with Children BSN
One-off three-component spawn in a tight system Bundle / tuple still fine
Need asset path strings inside the declaration BSN templates
Need World round-trip serialize today Old serialization path (migration guide)
Need glTF scene spawn today Old glTF path until ported to BSN

Rule for this evening: every new nested hierarchy you write after reading this post should be BSN unless you have a documented exception in the receipt.

Developer path - gates B1–B6

B1 - Version truth

Check Pass Fail
Bevy version 0.19.x 0.17/0.18 with "we'll pretend"
Fresh vs migrate New crate or migration guide followed Random plugin soup from 0.17 tutorials

B2 - Loader honesty

Check Pass Fail
Workflow Code-driven bsn! "We'll just drop a .bsn file in assets/"
Team message Asset loader pending upstream Promising editor .bsn round-trips in 0.19

Official language: 0.19 supports scene assets functionally, but does not ship a first-party .bsn loader yet. queue_spawn_scene waiting on "player.bsn" only helps once a loader exists (or you write one).

B3 - Spawn API choice

API Use when
commands.spawn_scene(scene) Immediate spawn; fails if scene asset deps are not loaded
commands.queue_spawn_scene(scene) Wait until dependencies load
level.spawn() on Startup Scene/SceneList function as a system

Do not mix "I expected queue semantics" with spawn_scene and then blame BSN.

B4 - Hierarchy and patches

Confirm:

  1. Children appear under the parent in the ECS relationship sense.
  2. A layered scene patch merges fields (official button width/height layering example).
  3. You did not reintroduce Bundle soup for the same tree.

B5 - Migration rename awareness (upgraders)

The 0.18 → 0.19 migration guide notes that the old scene crate space was reworked to make room for BSN. Round-trip World serialization and glTF scene loading still rely on the older path for now. If your project still needs glTF scene spawn the old way, do not delete that path because you learned bsn! tonight.

B6 - Receipt + latch

File the JSON. Set bevy_bsn_ok: true only when B1–B5 are honest.

Scene functions, patches, and why this beats Bundle soup

Reusable scene functions

fn player(name: &str) -> impl Scene {
    bsn! {
        Name(name)
        Player
    }
}

Call sites stop threading AssetServer through every helper just to build a tree. Templates can resolve asset paths like Sprite { image: "player.png" } when you are ready for assets - the World-aware Template system is why BSN can accept a path string instead of a preloaded handle in scene declarations (release notes).

Patches compose

fn button() -> impl Scene {
    bsn! {
        Button
        Node { width: px(100) }
    }
}

fn my_button() -> impl Scene {
    bsn! {
        button()
        Node { height: px(100) }
    }
}

my_button ends up with both width and height on Node - scenes are patches layered on defaults, not full replacements that wipe sibling fields.

SceneComponent (preview, not required tonight)

When a Player component should guarantee a full scene (hands, mesh, etc.) is present whenever the component exists, look up SceneComponent in the release notes. Spawning @Player { score: 10 } associates the component with Player::scene(). That is the idiomatic answer to "how do I know the whole prefab is there?" - save it for evening two if tonight is your first bsn!.

Common mistakes

  1. Expecting .bsn files to load out of the box in 0.19 - they do not with a first-party loader yet.
  2. Using spawn_scene with unloaded asset deps - use queue_spawn_scene when deps matter.
  3. Skipping Default + Clone on simple components - pass-through templates need them.
  4. Copying 0.17 Bundle tutorials into 0.19 - different scene era; prefer BSN for new UI trees.
  5. Confusing this with schedule hitch debugging - different URL, different problem (0.17 schedule debug).
  6. Promising partners an official Bevy Editor .bsn round-trip this quarter - editor editing of .bsn is roadmap language, not 0.19 shipped fact.

Trend discussion - what changed for Rust indies

Three motions matter:

  1. Scenes became a first-class language - BSN is not a niche macro; it is the centerpiece of 0.19's scene rewrite.
  2. UI and tooling are moving onto BSN - Feathers widgets migrated, which signals where Bevy wants widget authors to live.
  3. Asset-driven scenes are intentionally staged - code-first now, .bsn loader next. Studios that wait for the loader miss months of hierarchy ergonomics.

If you are still evaluating Bevy versus Godot for an editor-first workflow, be honest: 0.19 improves code-driven scenes dramatically; it does not yet replace a shipped visual .bsn editor pipeline.

Company / diligence paragraph

For a publisher or tech diligence zip, say:

  • Engine: Bevy 0.19.x
  • Scene authoring: code-driven BSN (bsn! / spawn_scene)
  • Asset scenes: first-party .bsn loader not shipped in 0.19 - tracked upstream
  • Evidence: bevy_019_bsn_scene_receipt_v1.json with gates B1–B6
  • Related iteration resources: 25 free Bevy Rust resources and 15 free Bevy 0.17 iteration resources (update versions in your own notes when you fully leave 0.17)

Receipt schema - bevy_019_bsn_scene_receipt_v1.json

{
  "schema": "bevy_019_bsn_scene_receipt_v1",
  "bevy_version": "0.19.x",
  "project_name": "bevy_bsn_evening",
  "workflow": "code_driven_bsn",
  "first_party_bsn_loader": false,
  "gates": {
    "B1_version": "green | red",
    "B2_loader_honesty": "green | red",
    "B3_spawn_api": "green | red",
    "B4_hierarchy_patches": "green | red",
    "B5_migration_awareness": "green | red | na_new_project",
    "B6_receipt_filed": "green | red"
  },
  "smoke": {
    "window_opened": true,
    "camera_spawned": true,
    "player_children_present": true,
    "hud_nodes_present": true
  },
  "sources": [
    "https://bevy.org/news/bevy-0-19/",
    "https://bevy.org/learn/migration-guides/0-18-to-0-19/",
    "https://github.com/bevyengine/bevy/blob/release-0.19.0/_release-content/release-notes/next-generation-scenes.md"
  ],
  "bevy_bsn_ok": false
}

One-evening schedule

Block Focus Exit
0:00-0:30 New crate, Bevy 0.19 dep, first build Compiles
0:30-1:00 Camera + player() with Children Hierarchy queryable
1:00-1:45 HUD Node tree via BSN Visible UI
1:45-2:15 Patch / scene function cleanup No Bundle soup left
2:15-2:45 Read loader caveat aloud; file receipt bevy_bsn_ok

Key takeaways

  • Bevy 0.19 introduces BSN and Next Generation Scenes as the modern way to declare entity trees in code.
  • Use the bsn! / bsn_list! macros and spawn with spawn_scene, queue_spawn_scene, or .spawn().
  • Children and scene functions replace a lot of manual Bundle nesting.
  • No first-party .bsn asset loader ships in 0.19 - code-driven workflow is the honest path.
  • Optional fields and patches reduce ..Default::default() noise.
  • Upgraders must read the 0.18→0.19 migration notes for old scene / glTF serialization realities.
  • File bevy_019_bsn_scene_receipt_v1.json and latch bevy_bsn_ok.
  • Keep this distinct from Bevy 0.17 platformer and schedule-debug posts.

FAQ

What is Bevy BSN?

BSN means Bevy Scene Notation - a Rust-like scene syntax used via the bsn! macro in Bevy 0.19, designed to also work in future .bsn asset files. See the Bevy 0.19 release notes.

Can I load .bsn files in Bevy 0.19?

Not with a first-party loader. 0.19 focuses on the code-driven workflow. An official .bsn loader is planned; adventurous teams can implement custom scene asset formats because the spawn system already understands scene asset dependencies.

How do I spawn a BSN scene?

Return impl Scene or impl SceneList from a function and use commands.spawn_scene(...), commands.queue_spawn_scene(...), or .spawn() on the function in a Startup schedule, as shown in the official notes.

When should I use queue_spawn_scene instead of spawn_scene?

When the scene depends on assets that may not be loaded yet. queue_spawn_scene waits; spawn_scene tries immediately and can fail if dependencies are missing.

Is BSN only for UI?

No. It can spawn anything in the ECS. UI is a highlighted win because nested Nodes and widgets get much more readable.

How is this different from Bundles?

Bundles are collections of components. BSN adds optional fields, relationships, patches, scene functions, templates, and asset-path ergonomics - see the Next Generation Scenes section of the release notes.

Should I upgrade from Bevy 0.17 just for BSN?

If you want modern scene authoring, yes - but budget migration work. Use the migration guide and do not assume glTF / old serialization paths are identical.

Where should I go after this evening?

Compose Feathers widgets with BSN using the official feathers examples, then read SceneComponent for prefab guarantees. Keep Bevy resource lists handy for crates and learning paths.

Related reads

Conclusion

Bevy 0.19's BSN is the rare engine feature that makes the beginner evening and the senior hierarchy design better at the same time. Spawn a camera, a player() scene with Children, and a small HUD Node tree. Say the .bsn loader caveat out loud so nobody plans a fake asset pipeline. File the receipt. Tomorrow you can chase SceneComponent and Feathers - tonight you just needed the macro to feel inevitable.