# Architecture

> How the packages fit together and why the seams are where they are

## The packages

```
@getnarro/core          the runtime: Presentation, Slide, navigation, motion
@getnarro/shared-ui     ~50 slide components, no runtime dependency on core
@getnarro/markdown      the markdown/MDX dialect + its Vite plugin
@getnarro/marketplace   themes, colour schemes, template metadata
@getnarro/cli           new / dev / build / export / import
@getnarro/mcp-server    MCP tools and resources for AI assistants
@getnarro/docs          these pages as data + the generated API reference
create-narro            npm create narro
```

## Why the seams are there

**`core` and `shared-ui` are separate** because they change at different rates
and for different reasons. `core` owns behaviour — how navigation works, when a
slide is active, how transitions run. `shared-ui` owns appearance. A deck can
use `core` alone and hand-write its markup, which is exactly what the `minimal`
template did until the docs made `shared-ui` the assumed baseline.

**`shared-ui` has no i18n and no state.** Components take text as props. That
keeps them usable from markdown, from React, and from generated code without
each caller having to set up a provider.

**`markdown` does not live in `cli`.** The dialect is a library — the Vite
plugin, the compiler, and the layouts are all importable — so a scaffolded
project can use it without depending on the CLI's much heavier install
(Playwright, sharp, the Google APIs client).

**`create-narro` does not live in `cli`** either, and cannot: `npm create narro`
resolves the `create-narro` package specifically, and scaffolding has to run
before anything is installed. `@getnarro/cli` depends on it so `narro create`
and `create-narro` share one implementation and one copy of the templates.

## How a deck renders

Both modes converge on the same runtime.

**React mode.** Your `App.tsx` composes `Presentation` and `Slide` directly.
Vite builds it like any other React app.

**Markdown mode.** The `@getnarro/markdown` Vite plugin compiles `deck.md` into
virtual modules:

```
virtual:narro/deck            the deck component
virtual:narro/deck.css        Tailwind, scanning the deck for utility classes
virtual:narro/slot/<i>/<n>    one compiled MDX module per slot
virtual:narro/layout/<name>   a resolved layout component
```

The result is a tree of `Presentation` and `Slide` — the same components React
mode uses. This is why the two modes share navigation, transitions, presenter
view, and export: there is only one runtime, and markdown is a front end to it.

Editing the deck recompiles only the slots whose content changed.

## Core concepts

**A slide is a component.** No slide registry, no ordering metadata — order is
source order, and a slide is addressable by `id`.

**Activity is context, not a prop.** `useSlideActive()` tells a component
whether its slide is on screen. This is what lets animations start when the
audience sees them, and lets off-screen backgrounds stop doing work.

**Fragments are navigation steps.** They participate in the same next/previous
sequence as slides, which is why a fragment reveal and a slide advance feel
identical to the presenter.

**Layouts resolve by name, most specific first.** A deck's own `layouts/`
directory shadows the theme, which shadows the built-ins. Overriding one layout
never means forking the rest.