> ## Documentation Index
> Fetch the complete documentation index at: https://docs.presenton.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Your Own Presentation Templates in Presenton

> Want to design your own presentation templates in Presenton? This guide walks you through the full process from setup to seeing your template live in the app.

## Step 1: Set Things Up

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

### Clone the Repository

Open your terminal and run:

```bash theme={null}
git clone https://github.com/presenton/presenton.git
cd presenton
```

### Start Presenton

You can run Presenton in two ways:

**Option A: Docker (recommended for quick setup)**

```bash theme={null}
docker compose up development --build
```

**Option B: Electron (for development or desktop use)**

```bash theme={null}
cd electron
npm run setup:env   # First time only
npm run dev
```

Once it's running, open your browser and visit:

**[http://localhost:5000](http://localhost:5000)**

If you see the Presenton interface, you're good to go!

## Step 2: Understand How Templates Work

Presenton organizes slide designs into **template groups**. Each template group contains one or more **slide layouts** and a `settings.json` file that describes the group's behavior.

### Where Templates Live

All templates are located in:

```
app/presentation-templates
```

The exact path depends on how you run Presenton:

* **Docker:** `servers/nextjs/app/presentation-templates`
* **Electron:** `electron/servers/nextjs/app/presentation-templates`

Navigate there by running:

```bash theme={null}
# For Docker setup
cd servers/nextjs/app/presentation-templates

# For Electron setup
cd electron/servers/nextjs/app/presentation-templates
```

Inside this folder, you'll see multiple subdirectories — each one is a **template group** (e.g., `general`, `neo-general`, `modern`, `standard`, `swift`).

### Explore a Template Group

Pick any template folder (e.g., `general`) and open it. Here's what you'll find:

* **`settings.json`**: Contains metadata about the template group: description, whether slides are ordered, and whether it's the default template.
* **One or more `.tsx` files**: Each file defines a single slide layout, including its Zod schema (used by the AI to generate content) and the React component that renders the slide.

Each `.tsx` file must export:

* `Schema` — Zod schema defining the slide data
* `layoutId` — Unique identifier for the layout
* `layoutName` — Display name in the UI
* `layoutDescription` — Description for the AI to match content
* Default export — The React component that renders the slide

### Preview Templates in the UI

To see all available presentation templates and their slide layouts in your browser, go to:

**[http://localhost:5000/template-preview](http://localhost:5000/template-preview)**

This preview page gives you a visual overview of each template group and lets you inspect how each slide layout looks when used.

When generating a presentation, you'll be able to pick from these templates in the **Outlines and Templates** step of the process.

## Step 3: Build Your Own Template

Now it's time to create a custom template of your own.

### Create a New Template Directory

In the `presentation-templates` folder, create a new directory. This will be your template group.

```bash theme={null}
mkdir my-presentation-template
cd my-presentation-template
```

> 💡 The folder name (e.g., `my-presentation-template`) becomes the template ID used in the app.

### Add a `settings.json` File

Create a file named `settings.json` with:

```json theme={null}
{
  "description": "This is my presentation template",
  "ordered": false,
  "default": false
}
```

* **`description`**: Short description of this template group.
* **`ordered`**: If `true`, slides are used in a fixed order (see [How Slides Are Selected](#how-slides-are-selected-in-a-template) below). Keep `false` for AI-driven layout selection.
* **`default`**: If `true`, this template is used by default when generating a presentation.

> ⚠️ Use boolean values (`true`/`false`), not strings (`"true"`/`"false"`).

## Step 4: Add Your First Slide Layout

### Create a Layout File

Create a new `.tsx` file for your first slide:

```bash theme={null}
touch TitleDescriptionSlide.tsx
```

You can use `ExampleSlideLayoutTemplate.tsx` in the `presentation-templates` folder as a minimal starting point, or copy from an existing layout like `general/BasicInfoSlideLayout.tsx`.

### Define Schema and Component

Each slide layout needs:

1. A **Zod schema** — tells the AI what data this slide expects.
2. A **React component** — renders the slide visually.

Here's a minimal example with title and description:

```tsx theme={null}
import * as z from "zod";

export const layoutId = "title-description-slide";
export const layoutName = "Title & Description";
export const layoutDescription =
  "A simple slide with a title and description text.";

export const Schema = z.object({
  title: z.string().min(3).max(50).default("Slide Title").meta({
    description: "Main title of the slide",
  }),
  description: z
    .string()
    .min(10)
    .max(180)
    .default("Slide description content.")
    .meta({
      description: "Content description of the slide",
    }),
});

type SchemaType = z.infer<typeof Schema>;

const SlideComponent = ({ data }: { data: Partial<SchemaType> }) => {
  return (
    <div className="w-full max-w-[1280px] max-h-[720px] aspect-video bg-white flex flex-col justify-center items-center p-10 mx-auto">
      <h1 className="text-4xl font-bold">{data.title}</h1>
      <p className="mt-6">{data.description}</p>
    </div>
  );
};

export default SlideComponent;
```

> ✨ **Tips:**
>
> * Use `.default()` on each schema field so the preview renders correctly.
> * Use `.meta({ description: "..." })` to help the AI generate better content.
> * Keep a consistent **16:9 aspect ratio** and **max-width of 1280px** — layouts are exported as PDF and PPTX.

## Step 5: Register Your Template in the App

Templates are not auto-discovered. You must register them in `presentation-templates/index.tsx`. The file is organized into five steps — follow them in order:

### Step 5.1: Import Your Layouts

Find the `// TODO: Step 1: Import All templates Layouts Here` section and add your layout import:

```ts theme={null}
// Import your layout (add with other imports)
import TitleDescriptionSlideLayout, {
  Schema as TitleDescriptionSlideSchema,
  layoutId as TitleDescriptionSlideId,
  layoutName as TitleDescriptionSlideName,
  layoutDescription as TitleDescriptionSlideDesc,
} from "./my-presentation-template/TitleDescriptionSlide";
```

### Step 5.2: Import Your Settings

Find the `// TODO: Step 2: Import template settings Here` section and add:

```ts theme={null}
import myTemplateSettings from "./my-presentation-template/settings.json";
```

### Step 5.3: Create Template Entries

Find the `// TODO: Step 3: Create template entries for each template` section and add your template array:

```ts theme={null}
export const myTemplateLayouts: TemplateWithData[] = [
  createTemplateEntry(
    TitleDescriptionSlideLayout,
    TitleDescriptionSlideSchema,
    TitleDescriptionSlideId,
    TitleDescriptionSlideName,
    TitleDescriptionSlideDesc,
    "my-presentation-template", // template group ID (folder name)
    "TitleDescriptionSlide", // file name without .tsx
  ),
];
```

### Step 5.4: Add to allLayouts

Find the `// TODO: Step 4: Combine all templates into a single array For UseCases` section and add your layouts to `allLayouts`:

```ts theme={null}
export const allLayouts: TemplateWithData[] = [
  ...neoGeneralTemplates,
  // ... other templates
  ...myTemplateLayouts,
];
```

### Step 5.5: Add to templates

Find the `// TODO: Step 5: Combine all templates into a single array For UseCases` section and add your template group to the `templates` array:

```ts theme={null}
export const templates: TemplateLayoutsWithSettings[] = [
  // ... existing template groups
  {
    id: "my-presentation-template",
    name: "My Presentation Template",
    description: myTemplateSettings.description,
    settings: myTemplateSettings as TemplateGroupSettings,
    layouts: myTemplateLayouts,
  },
];
```

## Step 6: Preview Your Template

Visit:

**[http://localhost:5000/template-preview](http://localhost:5000/template-preview)**

You should see your template group listed. Click on it to preview your slide layout.

Your template is now ready to use. Select it in the **Outlines and Templates** step when generating a presentation.

***

## Adding More Slides to Your Template

Add another slide layout with title, description, image, and icon.

### Create a New Layout File

```bash theme={null}
touch TitleDescriptionImageIconSlide.tsx
```

### Define the Schema with Image and Icon

Use `ImageSchema` and `IconSchema` from the default schemes for AI-generated images and icons:

```tsx theme={null}
import * as z from "zod";
import {
  ImageSchema,
  IconSchema,
} from "@/app/presentation-templates/defaultSchemes";

export const layoutId = "title-description-image-icon-slide";
export const layoutName = "Title, Description, Image & Icon";
export const layoutDescription =
  "A slide with title, description, image, and icon.";

export const Schema = z.object({
  title: z.string().min(3).max(50).default("Slide Title").meta({
    description: "Main title of the slide",
  }),
  description: z.string().min(10).max(180).default("Slide 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__: "mountain icon",
  }).meta({
    description: "Icon to display in the slide",
  }),
});

type SchemaType = z.infer<typeof Schema>;

const SlideComponent = ({ data }: { data: Partial<SchemaType> }) => {
  return (
    <div className="w-full max-w-[1280px] max-h-[720px] aspect-video bg-white flex justify-center items-center gap-4 p-10 mx-auto">
      <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>
  );
};

export default SlideComponent;
```

> 🖼️ **ImageSchema** and **IconSchema** are required for AI-generated images and icons. They ensure compatibility with PDF and PPTX export.

### Register the New Layout

In `index.tsx`, add the import in **Step 1** and the `createTemplateEntry` call in **Step 3** (`myTemplateLayouts` array):

```ts theme={null}
// Step 1: Add import
import TitleDescriptionImageIconSlideLayout, {
  Schema as TitleDescriptionImageIconSlideSchema,
  layoutId as TitleDescriptionImageIconSlideId,
  layoutName as TitleDescriptionImageIconSlideName,
  layoutDescription as TitleDescriptionImageIconSlideDesc,
} from "./my-presentation-template/TitleDescriptionImageIconSlide";

// Step 3: Add to myTemplateLayouts array
createTemplateEntry(
  TitleDescriptionImageIconSlideLayout,
  TitleDescriptionImageIconSlideSchema,
  TitleDescriptionImageIconSlideId,
  TitleDescriptionImageIconSlideName,
  TitleDescriptionImageIconSlideDesc,
  "my-presentation-template",
  "TitleDescriptionImageIconSlide"
),
```

### Preview

Visit **[http://localhost:5000/template-preview](http://localhost:5000/template-preview)** — both slides should appear under your template.

### Naming Layouts for Better AI Matching

Use **descriptive filenames** so the AI can choose the right layout for each slide. For example:

* `TitleDescriptionSlide.tsx`
* `TitleDescriptionImageIconSlide.tsx`

Instead of generic names like `SlideLayout1.tsx` or `SlideLayout2.tsx`.

***

## How Slides Are Selected in a Template

When generating a presentation, Presenton selects a slide layout for each slide from the layouts in your template group.

### AI-Driven Selection (`ordered: false`)

With `ordered: false` (default), the AI picks the best layout for each slide based on content. Descriptive `layoutName` and `layoutDescription` help improve matching.

### Fixed Order (`ordered: true`)

To force a specific layout order, set `ordered: true` in `settings.json`:

```json theme={null}
{
  "description": "My template with fixed slide order",
  "ordered": true,
  "default": false
}
```

Then order your layouts in the `myTemplateLayouts` array in `index.tsx` — the first layout is slide 1, the second is slide 2, and so on. You can also use numeric prefixes in filenames (e.g., `1-TitleSlide.tsx`, `2-ContentSlide.tsx`) to keep the order clear.

***

## Layout Best Practices

* **Aspect ratio**: Use `aspect-video` (16:9) and `max-w-[1280px] max-h-[720px]` for consistent export.
* **Defaults**: Every schema field should have a `.default()` for preview and fallbacks.
* **Meta descriptions**: Add `.meta({ description: "..." })` to help the AI.
* **Validation**: Use `.min()` and `.max()` on strings and arrays.
* **Theme variables**: Use CSS variables like `var(--background-color)`, `var(--primary-color)`, `var(--heading-font-family)` for theme support.
* **Optional branding**: Support `__companyName__` and `_logo_url__` in `data` for company branding when provided.

For more examples, see `ExampleSlideLayout.tsx` and existing layouts in `general/`, `neo-general/`, and other template folders.
