Spawning a new snake segment in tick is something we could copy/paste the code for from the original snake spawn in spawn_board.
Instead of that, we’re going to make our own custom Bevy command to make it a bit more clear what’s happening.
The Commands we use are how we mutate the World, and the trait each of these commands implements is called Command. Our goal is to implement Command to create our own spawn snake command.
In board.rs create a new public struct called SpawnSnakeSegment which will be the struct we use to drive our command. Think of this like the arguments to a function.
pub struct SpawnSnakeSegment {
    pub position: Position,
}
Bring command into scope:
use bevy::{ecs::system::Command, prelude::*};
and we can start implementing Command for SpawnSnakeSegment. The core of the Command trait is the write function, which gives us self, which is our SpawnSnakeSegment and a mutable world to modify.
impl Command for SpawnSnakeSegment {
    fn write(self, world: &mut World) {
        ...
    }
}
We are freely available to use this world reference to grab anything we want. We can use it to grab a reference to the board by querying the world in the same way our systems do. The biggest difference here is that world is a bit lower level than our systems, so the functions that are available to us change a bit.
For example, we can query for &Board but we don’t have .single() available to us anymore, so we use .iter, which also accepts an argument. We know there’s only one board, so we can call .next() on the iterator to get an Option<&Board> and .unwrap() to get the &Board.
Also note that we don’t have access to spawn_bundle anymore. We need to first .spawn an entity and then we can insert_bundle on that entity.
Finally also note that we’re using self to access the position.
impl Command for SpawnSnakeSegment {
    fn write(self, world: &mut World) {
        let board = world
            .query::<&Board>()
            .iter(&world)
            .next()
            .unwrap();
        world
            .spawn()
            .insert_bundle(SpriteBundle {
                sprite: Sprite {
                    color: COLORS.snake,
                    custom_size: Some(Vec2::new(
                        TILE_SIZE, TILE_SIZE,
                    )),
                    ..Sprite::default()
                },
                transform: Transform::from_xyz(
                    board.cell_position_to_physical(
                        self.position.x,
                    ),
                    board.cell_position_to_physical(
                        self.position.y,
                    ),
                    2.0,
                ),
                ..Default::default()
            })
            .insert(self.position);
    }
}
The core spawning logic here is a copy/paste from the spawn_board logic where we were spawning the snake segments originally.
The code here does have a flaw though and it’s an important one to point out.
error[E0502]: cannot borrow `*world` as mutable because it is also borrowed as immutable
   --> src/board.rs:119:9
    |
115 |               .iter(&world)
    |                     ------ immutable borrow occurs here
...
119 | /         world
120 | |             .spawn()
    | |____________________^ mutable borrow occurs here
...
130 | /                     board.cell_position_to_physical(
131 | |                         self.position.x,
132 | |                     ),
    | |_____________________- immutable borrow later used here
We get a board from the world, which means we’re holding a small piece of the world as a shared reference in the board variable.
When we go to use world.spawn() we are trying to mutate the world, which requires an exclusive (also known as mutable) reference. This is ok so far because the board hasn’t been used yet.
Unfortunately for us, we use the board after the world.spawn() to determine the cell positions. This means we’re trying to hold onto the shared reference to the board (which is a piece of world while also using a mutable reference to world.
We can not hold both a shared reference and an exclusive reference at the same time.
Luckily for us, we don’t actually need to use the board that late in the program, we can move our .cell_position_to_physical calls up above the world.spawn() call which means that we acquire and stop using the board before world.spawn happens, allowing us to drop the shared reference and take the exclusive reference.
impl Command for SpawnSnakeSegment {
    fn write(self, world: &mut World) {
        let board = world
            .query::<&Board>()
            .iter(&world)
            .next()
            .unwrap();
        let x = board
            .cell_position_to_physical(self.position.x);
        let y = board
            .cell_position_to_physical(self.position.y);
        world
            .spawn()
            .insert_bundle(SpriteBundle {
                sprite: Sprite {
                    color: COLORS.snake,
                    custom_size: Some(Vec2::new(
                        TILE_SIZE, TILE_SIZE,
                    )),
                    ..Sprite::default()
                },
                transform: Transform::from_xyz(x, y, 2.0),
                ..Default::default()
            })
            .insert(self.position);
    }
}
Back up in spawn_board we can now use our custom command by calling commands.add with out SpawnSnakeSegment that implements Command. The segment can be dereferenced, which will use the Copy implementation on Position, as I’m doing here or cloned with .clone if that is how you want to write it. It amounts to the same thing.
for segment in snake.segments.iter() {
    commands.add({
        SpawnSnakeSegment { position: *segment }
    });
}
Don’t forget to remove the extra Board we built in spawn_board.
let board = Board::new(20);
Back in lib.rs, right after push_front, add the same SpawnSnakeSegment command using next_position to insert the new snake head.
snake.segments.push_front(next_position);
commands.add({
    SpawnSnakeSegment {
        position: next_position,
    }
});
After running cargo run this will result in the snake running away off the right side of the screen.