# Getting started

> Add the kit to a video made by cargo fframes new and show a title and a lower third.

Page: https://fframes-kit.pages.dev/docs/start/getting-started/

Add the kit to a video made by `cargo fframes new` and show a title and a lower third.

## 1. Create the project

The kit builds against the crates.io release of fframes, the one `cargo fframes new` pins:

```bash
cargo install cargo-fframes
cargo fframes new my-video --backend cpu --yes
```

- `--backend cpu` renders with the CPU backend. Leave it out on a machine with a GPU to get
  the Skia Vulkan (or Metal) backend.

## 2. Add the kit

One dependency line in `[dependencies]`:

```toml
fframes-kit = "0.3"
```

- The kit is 0.x: its API may still change between minor versions. `"0.3"` takes fixes but
  no breaking release.
- `{ git = "https://github.com/khanhthanhdev/fframes-kit" }` instead takes the unreleased
  `main`; pin a `rev` to keep a project on one commit.
- Explainer kits are features, for example `fframes-kit = { ..., features = ["math"] }`; see
  [components.md](https://fframes-kit.pages.dev/docs/basics.md).
- A project that takes fframes from a checkout or a git repository instead of crates.io
  patches it, so the kit uses the same fframes. Two copies of fframes do not mix; their types
  differ and the project does not compile:

```toml
[patch.crates-io]
fframes = { path = "../fframes/fframes" } # or { git = "<url>", rev = "<rev>" }
```

  The patch applies while that fframes has a version the kit accepts (1.3 or a later 1.x).

## 3. A first video

Replace `src/lib.rs` with the following (the names are those of a project called
`kit-sample`; `main.rs` stays as generated). One import brings the kit, `svgr!` and the fframes
types a video needs:

```rust title="Not compiled"
use fframes::include_media_dir;
use fframes_kit::prelude::*;

// Every file of `media/` is embedded into the binary. Fonts are used by family name; the
// kit's default theme uses DM Sans, which `cargo fframes new` already put there.
include_media_dir!(pub struct KitSampleMedia, "media");

#[derive(Debug)]
pub struct KitSampleVideo<'a> {
    pub media: &'a KitSampleMedia,
    title: String,
    theme: Theme,
}

impl<'a> KitSampleVideo<'a> {
    pub fn new(media: &'a KitSampleMedia, title: &str) -> Self {
        // The kit's defaults with an orange accent and a light background.
        let theme = Theme {
            colors: Colors {
                accent: Color::hex("#ff5500"),
                background: Color::hex("#f8fafc"),
                title: Color::hex("#0f172a"),
                text: Color::hex("#0f172a"),
                muted: Color::hex("#475569"),
                ..Colors::default()
            },
            ..Theme::default()
        };
        Self { media, title: title.to_owned(), theme }
    }
}

impl Video for KitSampleVideo<'_> {
    const FPS: usize = 30;
    const WIDTH: usize = 1920;
    const HEIGHT: usize = 1080;

    fn duration(&self) -> Duration<'_> {
        Duration::Seconds(6.0)
    }

    fn audio(&self) -> AudioMap<'_> {
        AudioMap::none()
    }

    fn render_frame<'a>(&'a self, frame: Frame, ctx: &FFramesContext<'a, '_>) -> Svgr<'a> {
        let mut ui = Ui::new(frame, ctx, &self.theme);
        let c = self.theme.colors;
        let style = self.theme.typography.title;
        let title = self.title.as_str();

        // The title fades in and out over the whole video ...
        let heading = ui.show(SceneFade::new(
            &ui,
            children(move |_| {
                svgr!(
                    <text x="96" y="420" font-family={style.family} font-size={style.size}
                          font-weight={style.weight} fill={c.title}>{title}</text>
                )
            }),
        ));
        // ... and a lower third shows from 1 s to 5 s.
        let lower_third = ui.show(Sequence {
            from: 1.0,
            duration: Some(4.0),
            children: children(|ui| {
                ui.show(LowerThird {
                    name: "Ada Lovelace".into(),
                    role: "Mathematician".into(),
                    ..ui.defaults()
                })
            }),
        });

        svgr!(
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1920 1080"
                 width={ctx.current_video_size.width} height={ctx.current_video_size.height}>
                <rect width="1920" height="1080" fill={c.background} />
                {heading}
                {lower_third}
            </svg>
        )
    }
}
```

- `Ui` carries the frame, the context and the theme. `ui.show(component)` renders a component,
  and `..ui.defaults()` fills the props you do not set from the theme.
- `Sequence` shifts time: inside it, the lower third starts at its own 0 s, one second into
  the video, and is gone after `duration`.
- The `Theme` is a plain value. Build it once in the constructor, override the fields you need
  (`colors`, `typography`, `spacing`, ...) and keep the rest with `..Theme::default()`.

## 4. Check it

```bash
cargo run --release -- inspect        # "no problems found"
cargo run --release -- strip -n 8     # one image of the whole video
cargo run --release -- render         # the video file
```

[components.md](https://fframes-kit.pages.dev/docs/basics.md) goes on from here: the time containers, fades, `Anim`,
transitions, effects and writing your own components.
