What Slides is
Slides is a complete present-a-deck system: @texuli/deck holds the framework-free model v2, JSON and Markdown codecs, navigation engine and templates; @texuli/slides is the Svelte 5 stage on top of it (layouts, presenter, print and PPTX). Both packages are published as 0.18.0 and are **in development** (pre-1.0). Pin the exact version or use ^0.17.0.
The live demo on this site is on the Slides landing, /solutions/slides/. The technical docs you are reading live at /guides/solutions/slides/.
What you get
- A validated deck as data (
formatVersion: 2), not HTML. - JSON or Markdown in, the same model out.
- A stage that scales a fixed canvas, follows
#/<slide>/<step>, and takes keyboard and touch. - 21 layouts, 13 background presets with a 4.5:1 text scrim, fragments, presenter view, print-to-PDF and local PPTX.
There is no hosted editor and no deck storage. The host app keeps the data.
Install
Svelte 5 (^5.57.2) is a peer of @texuli/slides. @texuli/deck has no runtime or peer dependencies.
npm install @texuli/slides @texuli/deck svelteImport the stylesheet once:
import '@texuli/slides/styles.css';A JSON deck on the stage
DeckStage validates before it paints and shows diagnostics instead of a broken slide. The default trust tier is untrusted.
<script lang="ts">
import '@texuli/slides/styles.css';
import { DeckStage } from '@texuli/slides/stage';
const deck = {
formatVersion: 2,
meta: { title: 'Quarterly update', locale: 'en' },
style: { theme: 'ocean', transition: 'slide' },
slides: [
{
id: 'opening',
layout: 'title-hero',
props: { title: 'Quarterly update', subtitle: 'Fictional numbers for Northwind' },
},
],
};
</script>
<DeckStage {deck} />Parse first
parseDeck never throws. It reports every issue at once, each with a code, a JSON path and a fix.
import { parseDeck } from '@texuli/deck/model';
import { formatDiagnostic } from '@texuli/deck/schema';
const result = parseDeck({
formatVersion: 2,
meta: { title: 'Quarterly review', locale: 'en' },
slides: [{ id: 'opening', layout: 'title-hero', props: { title: 'Quarterly review' } }],
});
if (result.ok) {
console.log(result.deck.slides.length);
} else {
for (const issue of result.issues) console.log(formatDiagnostic(issue));
}Model v2
The canonical document is data: formatVersion, meta, style, optional navigation and outline, and slides. Everything in @texuli/deck/model is a pure function. Untrusted input goes through loadUntrustedDeck, which bounds bytes, depth and nodes, migrates earlier shapes, then validates.
import { loadUntrustedDeck, migrateDeck, parseDeck } from '@texuli/deck/model';A slide names a layout and props for that layout, or blocks on the free layout. Fragments and steps live on the model; the stage only paints them.
Markdown dialect
parseDeckMarkdown from @texuli/deck/markdown reads the same model. --- separates slides. Note: starts speaker notes. Pass validateDeckBlock from the stage so block bodies use the stage's checks. Raw HTML, iframes, class, style and event handlers are refused. The dialect is inspired by reveal.js Markdown and is not compatible with it.
<script lang="ts">
import { parseDeckMarkdown } from '@texuli/deck/markdown';
import { DeckStage, validateDeckBlock } from '@texuli/slides/stage';
const result = parseDeckMarkdown(source, { validateBlock: validateDeckBlock });
</script>Engine
createDeckController in @texuli/deck/engine is the framework-free runtime: navigation, hash routes, the controls registry, canvas fit, auto-slide and the presenter protocol. It does not touch window or document.
import { createDeckController } from '@texuli/deck/engine';
const controller = createDeckController(deck);
controller.next();
controller.goTo('closing');
controller.getState();Stage
DeckStage from @texuli/slides/stage is the Svelte 5 presenter. Import @texuli/slides/styles.css once. Hosts that bring every renderer use DeckStageCore from @texuli/slides/stage-core so the build emits none of the default chunks.
The canvas is 1280 × 720 for 16:9 (also 4:3, 9:16 and 1:1) and scales into the host. Hash routes are #/<slide>/<step>. Only one stage on a page owns the hash.
Layouts
Twenty-one layouts ship in @texuli/slides/layouts: title hero, section divider, splits, cards, media, quote, code, big stat, table, process, timeline, team, closing call to action, chart, and free blocks. Backgrounds are 13 presets, hex, gradients, image or video, with a scrim that keeps slide text at 4.5:1.
Any slide-renderable catalog component can sit on a slide, loaded lazily, at the host's trust tier (@texuli/slides/components).
Print and PPTX
@texuli/slides/export prints one page per visible slide (the browser saves PDF) and writes a local, deterministic PPTX: text and tables as editable PowerPoint, images and charts as pictures the host supplies, plus a report of what it leaves out. There is no server-side PDF renderer.
Keyboard and input
Keys, a click on the slide, touch swipes and the toolbar run the same engine actions. Vertical stacks walk steps, then the stack, then the next slide. The overview is a thumbnail grid by keyboard or pointer. Focus after a keyboard move waits for the incoming slide.
Motion and contrast
Transitions (none, fade, fade-up, slide, zoom, morph) cut or fade under prefers-reduced-motion. Background scrims keep text at least 4.5:1. Stage styles include reduced-motion and forced-colors rules.
The keyboard map, reflow at 320px and screen-reader notes live with the package stage docs and the recorded slides accessibility transcripts.
Status
Slides is **in development**. @texuli/slides and @texuli/deck are on npm as 0.18.0. Under 0.x a new minor may break. Native rendering is planned, not built.
Not built
- A presenter screen on another device
- A server-side PDF or image renderer
- Deck video export
- Inline
$…$math inside text blocks - A hosted editor or deck storage (the host keeps the data)
Model v1 decks still parse; migrateDeck and the stage migrate them. @texuli/[email protected] is the previous stage. The upgrade path is in the package migration guide.
Untrusted decks
A deck from an agent, a paste or a share link is untrusted data. Use loadUntrustedDeck from @texuli/deck/model before any deep work. DeckStage validates at the untrusted tier by default, so an agent-written deck is safe to pass as data. There is no HTML sink: the stage paints the model.
Markdown and JSON
Agents can emit JSON (formatVersion: 2) or the closed Markdown dialect. parseDeck and parseDeckMarkdown return diagnostics instead of throwing. Hostile HTML in Markdown is refused.
The catalog can describe slide-renderable components; the stage loads only those renderers. Do not invent APIs or a hosted generation service. The live generation page on this site is a recorded replay, not a deployed agent.

