Guide: Presentation slides

- Make each slide a frame of 1920 by 1080. Put the slides in reading order from left to right, 100 px apart: `x` is 0, 2020, 4040 and so on. - Make a small set

  • Make each slide a frame of 1920 by 1080. Put the slides in reading order from left to right, 100 px apart: x is 0, 2020, 4040 and so on.
  • Make a small set of slide components, such as a title slide and a slide with points. Place each one many times, with different props on each frame.
  • Keep text short. Make titles 64 to 96 px and body text 32 to 40 px, with six lines or less on a slide.
  • Keep a margin of 120 px on each side. Put the slide number in the same place on each slide.
  • Use a title slide, an agenda, one idea on each slide and a closing slide.
  • Make charts as in guide/dashboard.md, at a larger size.
type TitleSlideProps = { title?: string; subtitle?: string; className?: string }

export function TitleSlide({
  title = 'Ledger',
  subtitle = 'Board update, October 2026',
  className = ''
}: TitleSlideProps) {
  return (
    <section
      className={`flex size-full flex-col justify-end gap-6 bg-foreground p-30 text-background ${className}`}
    >
      <h1 className="font-display text-[120px] leading-none font-semibold tracking-tight">
        {title}
      </h1>
      <p className="text-[40px] opacity-70">{subtitle}</p>
    </section>
  )
}

type PointsSlideProps = {
  number?: string
  title?: string
  point1?: string
  point2?: string
  point3?: string
  className?: string
}

export function PointsSlide({
  number = '02',
  title = 'What changed',
  point1 = 'Revenue grew 18% on the last quarter.',
  point2 = '',
  point3 = '',
  className = ''
}: PointsSlideProps) {
  return (
    <section
      className={`flex size-full flex-col gap-16 bg-background p-30 text-foreground ${className}`}
    >
      <div className="flex items-baseline justify-between">
        <h2 className="text-[80px] leading-none font-semibold tracking-tight">{title}</h2>
        <span className="font-mono text-[32px] text-muted-foreground">{number}</span>
      </div>
      <ul className="flex flex-col gap-8 text-[40px] leading-snug">
        {point1 && <li>{point1}</li>}
        {point2 && <li>{point2}</li>}
        {point3 && <li>{point3}</li>}
      </ul>
    </section>
  )
}

export const canvas = {
  pages: [
    {
      name: 'Deck',
      items: [
        { render: TitleSlide, x: 0, y: 0, width: 1920, height: 1080 },
        {
          render: PointsSlide,
          props: {
            number: '02',
            title: 'What changed',
            point1: 'Revenue grew 18% on the last quarter.',
            point2: 'Overdue invoices fell to 6%.',
            point3: 'Payouts now reach 40 countries.'
          },
          x: 2020,
          y: 0,
          width: 1920,
          height: 1080
        },
        {
          render: PointsSlide,
          props: {
            number: '03',
            title: 'Next quarter',
            point1: 'Launch in Japan.',
            point2: 'Hire two engineers.'
          },
          x: 4040,
          y: 0,
          width: 1920,
          height: 1080
        }
      ]
    },
    { name: 'Components', kind: 'components', items: [] }
  ]
}

The subset has no lists from arrays, so a slide with points has one prop for each point. An empty point does not show.