Step 1: Set Things Up

Let’s start by getting Presenton up and running locally.

Clone the Repository

Open your terminal and run:
git clone https://github.com/presenton/presenton.git
cd presenton

Start the Server

Now, fire up Presenton using Docker:
docker compose up development --build
Once it’s running, open your browser and visit: http://localhost:5000 If you see the Presenton interface, you’re good to go!

Step 2: Understand How Layouts Work

Presenton organizes slide designs into layout groups. Each group contains one or more slide layouts and some metadata that describes the group.

Where Layouts Live

All layouts are located in:
servers/nextjs/presentation-layouts
Navigate there by running:
cd servers/nextjs/presentation-layouts
Inside this folder, you’ll see multiple subdirectories — each one is a layout group.

Explore a Layout Group

Pick any layout group folder and open it. Here’s what you’ll typically find inside:
  • settings.json: This file contains basic information about the layout group, such as its description and behavior.
  • One or more .tsx files: Each .tsx file defines the layout of a single slide, including its schema (used by the AI to generate content) and the React component that renders the slide visually.
You can think of each .tsx file as a “slide template” that Presenton can use when building a presentation.

Preview Layout Groups in the UI

To see all available layout groups and their layouts in your browser, go to: http://localhost:5000/layout-preview This preview page gives you a visual overview of each group and lets you inspect how each layout will look when used. When generating a presentation, you’ll be able to pick from these layout groups in the Outlines and Layouts step of the process.

Step 3: Build Your Own Layout Group

Now it’s time to roll up your sleeves and create a custom layout group of your own.

Create a New Directory

In the presentation-layouts folder, make a new directory. This will be your layout group.
mkdir my-presentation-layout
cd my-presentation-layout
💡 The name you give this folder will appear in the UI as the layout group name.

Add a settings.json File

Create a file named settings.json and paste the following:
{
  "description": "This is my presentation layout",
  "ordered": false,
  "default": false
}
You can edit the description to something more personal if you’d like. Here’s what these fields do:
  • description: Basic description of this layout.
  • ordered: We will talk about this later. Keep it false for now.
  • default: If true, this layout will be used by default when generating a presentation.

Step 4: Add Your First Slide Layout

Let’s create an actual slide layout now.

Create a .tsx File

touch SlideLayout1.tsx
Then open the file, and copy content from the template at:
presentation-layouts/ExampleSlideLayoutTemplate.tsx
Paste it into your file. Before going further, fix the import line:

Old Import

import { ImageSchema, IconSchema } from "./defaultSchemes";

New Import

import { ImageSchema, IconSchema } from "../defaultSchemes";

Step 5: Define Schema & Component

Each slide layout needs two parts:
  1. A schema (Zod) — tells the AI what kind of data this slide expects.
  2. A component (React) — renders the slide visually.
Let’s keep it simple with just a title and a description.

Schema

const Schema = z.object({
  title: z.string().min(3).max(50).default("Slide Layout Title").meta({
    description: "Main title of the slide"
  }),
  description: z.string().min(10).max(180).default("Slide Layout Description").meta({
    description: "Content description of the slide"
  })
});
✨ Tip: The default values help render the preview, and meta.description helps the AI generate better content.

SlideComponent

const SlideComponent = ({ data }: { data: Partial<SchemaType> }) => {
  return (
    <div className="h-full w-full flex flex-col justify-center items-center p-10">
      <h1 className="text-4xl font-bold">{data.title}</h1>
      <p className="mt-6">{data.description}</p>
    </div>
  );
};
You can customize this however you like.

Step 6: Preview Your Layout

Time to see your creation in action! Visit: http://localhost:5000/layout-preview You should now see your layout group listed. Click on it, and your new slide layout should appear. Boom — that’s it! Your layout is now ready to use
You can now select this new layout in Outlines and Layouts page while generating your presentation.

Adding More Slides to Your Layout Group

Now that you’ve got your first slide working, let’s take it a step further and add another layout, this time with a title, description, image, and icon.

Create a New Slide Layout File

Inside your layout group directory, create a new file:
touch SlideLayout2.tsx
(We’ll rename this later for better clarity.) Just like before, open the file and copy the contents from the template file:
presentation-layouts/ExampleSlideLayoutTemplate.tsx
Make sure to fix the import path if needed:
import { ImageSchema, IconSchema } from "../defaultSchemes";

Define the Schema

Here’s a full schema that includes a title, description, image, and icon:
export const Schema = z.object({
  title: z.string().min(3).max(50).default("Slide Layout Title").meta({
    description: "Main title of the slide"
  }),
  description: z.string().min(10).max(180).default("Slide Layout Description").meta({
    description: "Content description of the slide"
  }),
  image: ImageSchema.default({
    __image_url__: "https://cdn.pixabay.com/photo/2015/12/01/20/28/road-1072823_1280.jpg",
    __image_prompt__: "A beautiful road in the mountains"
  }).meta({
    description: "Image to display in the slide"
  }),
  icon: IconSchema.default({
    __icon_url__: "/static/icons/placeholder.png",
    __icon_query__: "A beautiful road in the mountains"
  }).meta({
    description: "Icon to display in the slide"
  }),
});
🖼️ To include AI-generated images and icons in your slides, make sure to use ImageSchema and IconSchema.

Create the Slide Component

Now let’s define how the slide will be rendered:
const SlideComponent = ({ data }: { data: Partial<SchemaType> }) => {
  return (
    <div className="h-full w-full flex justify-center items-center gap-4 p-10">
      <div className="basis-1/2 rounded-lg overflow-hidden">
        <img className="w-full" src={data.image?.__image_url__} alt={data.image?.__image_prompt__} />
      </div>
      <div className="basis-1/2 flex flex-col justify-center items-center">
        <img className="w-16 h-16" src={data.icon?.__icon_url__} alt={data.icon?.__icon_query__} />
        <h1 className="mt-4 text-4xl font-bold">{data.title}</h1>
        <p className="mt-6">{data.description}</p>
      </div>
    </div>
  );
};

Preview the New Slide

Just like before, head to: 📍 http://localhost:5000/layout-preview You should now see both layouts listed under your layout group. 🎉 That’s it! Now your layout group includes two slide layouts.

Rename Your Slide Files for Better AI Matching

While your layout files can technically be named anything, giving them meaningful names helps the AI choose layouts that best match the content of each slide. For example, instead of generic names like:
SlideLayout1.tsx
SlideLayout2.tsx
Rename them like this:
TitleDescriptionSlide.tsx
TitleDescriptionImageIconSlide.tsx
This makes it easier for Presenton’s layout selector to understand which layout is suited for what kind of content.
💡 Pro tip: The more descriptive the filename, the better the layout selection works — even when ordered is set to false.

How Slides Are Selected in a Layout Group

When generating a presentation using your layout group, Presenton will automatically choose a layout for each slide from the ones available in the group. But what if you want to control exactly which layout is used for each slide? Let’s say you want:
  • Slide 1 to always use the layout with just title and description
  • Slide 2 to always use the layout with title, image, icon, and description
You can do that by using the ordered field in your settings.json.

Use ordered: true for Specific Slide Order

Open your settings.json and set ordered to true:
{
  "description": "My custom layout with specific slide order",
  "ordered": "true",
  "default": "false"
}
Now, rename your layout files with a numeric prefix to indicate the order:
mv TitleDescriptionSlide.tsx 1-TitleDescriptionSlide.tsx
mv TitleDescriptionImageIconSlide.tsx 2-TitleDescriptionImageIconSlide.tsx
📛 The filenames determine the slide order when ordered is set to true.
Now, when this layout group is selected during presentation generation:
  • Slide 1 will always use 1-TitleDescriptionSlide.tsx
  • Slide 2 will always use 2-TitleDescriptionImageIconSlide.tsx
You can keep adding more layouts — just name them like 3-, 4-, etc. You can keep expanding your layout group by adding more .tsx files — each one with its own design and schema. Now go build something awesome! 💡✨ Got more ideas? Add more .tsx files inside your layout group and let your creativity run wild. 🎨💡