A modern slide presentation system built with Next.js 15, React, and Tailwind CSS using pure TypeScript components with a powerful presentation registry system.
- ⚡ Pure TypeScript: No build complexity, full type safety, better IDE support
- 🎨 Multiple Templates: Pre-built slide templates for different content types
- ⌨️ Keyboard Navigation: Navigate with arrow keys, spacebar, Home, and End
- 🔗 URL Navigation: Direct links to specific slides and presentations
- 📱 Responsive Design: Works on all screen sizes
- 🎯 TypeScript: Full type safety throughout
- 🚀 Fast: Built with Next.js 15 with Turbopack for blazing-fast development
- 📋 Presentation Registry: Centralized management of multiple presentations
- 🎭 Theme Support: Built-in dark/light theme switching
- 📄 Multiple Presentations: Support for organizing multiple presentations in one app
- 🔍 Advanced Search & Filtering: Search presentations by title, subtitle, author, or description, and filter by author or date
- ✅ Better IDE Support: Full IntelliSense, auto-completion, and error checking
- ✅ Type Safety: Catch errors at compile time, not runtime
- ✅ Cleaner Imports: No complex build configuration or loader setup
- ✅ Easier Refactoring: Rename components, move files with confidence
- ✅ Better Debugging: Source maps work perfectly, stack traces are clear
- ✅ No Build Complexity: Standard Next.js setup, no additional loaders
-
Install dependencies:
npm install
-
Run the development server:
npm run dev
-
Open your browser and navigate to
http://localhost:3000 -
Explore presentations: Use the presentation list or navigate directly to
/presentations/[id]
The app includes a powerful search and filtering system to help you find presentations quickly:
- Full-text search: Search across presentation titles, subtitles, authors, and descriptions
- Real-time filtering: Results update instantly as you type
- Case-insensitive: Search works regardless of letter case
- Filter by Author: Select from available authors to show only their presentations
- Filter by Date: Filter presentations by their creation or presentation date
- Combined filtering: Use search and filters together for precise results
The search interface is located at the top of the presentation library page and includes:
- Search input field: Enter keywords to search across all presentation metadata
- Author dropdown: Filter by specific authors
- Date dropdown: Filter by specific dates
- Results counter: Shows how many presentations match your current search/filters
- Search for "JavaScript" to find all presentations containing JavaScript content
- Filter by author "John Doe" to see only presentations by that author
- Combine search and filters: Search for "React" and filter by date "2025" to find React presentations from 2025
Perfect for title slides with optional subtitle, author, and date.
<TitleSlide
title="Your Presentation Title"
subtitle="Optional subtitle"
author="Your Name"
date="Today's Date"
/>General purpose slide with optional title and custom content.
<ContentSlide title="Your Title">
<div className="text-3xl">
Your custom content here
</div>
</ContentSlide>Display a list of bullet points.
<BulletSlide
title="Key Points"
items={[
"First point",
"Second point",
"Third point"
]}
/>Split content into two columns.
<TwoColumnSlide
title="Comparison"
left={<div>Left content</div>}
right={<div>Right content</div>}
/>Display syntax-highlighted code.
<CodeSlide
title="Code Example"
language="javascript"
code={`function hello() {
console.log("Hello, World!");
}`}
/>Display images with optional caption.
<ImageSlide
title="Image Title"
src="/path/to/image.jpg"
alt="Image description"
caption="Optional caption"
/>- Create a new TypeScript file in the
src/presentations/directory:
import { SlidePresenter } from '../components/SlidePresenter'
import { TitleSlide, ContentSlide, BulletSlide } from '../components/slides/SlideTemplates'
// Clean, typed metadata
const metadata = {
title: "My Awesome Presentation",
subtitle: "Built with TypeScript and React",
author: "Your Name",
date: "August 30, 2025"
} as const
export default function MyPresentation() {
return (
<SlidePresenter>
<TitleSlide
title={metadata.title}
subtitle={metadata.subtitle}
author={metadata.author}
date={metadata.date}
/>
<ContentSlide title="Welcome">
<div className="text-3xl">
<p>Welcome to my presentation!</p>
</div>
</ContentSlide>
<BulletSlide
title="Agenda"
items={[
"Introduction",
"Main Content",
"Conclusion"
]}
/>
</SlidePresenter>
)
}- Register your presentation in
src/lib/presentation-registry.ts:
import dynamic from 'next/dynamic'
export const presentations: Record<string, PresentationEntry> = {
// ... existing presentations
'my-presentation': {
metadata: {
id: 'my-presentation',
title: 'My Awesome Presentation',
subtitle: 'Built with TypeScript and React',
author: 'Your Name',
date: 'August 30, 2025',
description: 'A custom presentation demonstrating the power of TypeScript components.'
},
component: dynamic(() => import('@/presentations/my-presentation'), {
loading: () => <LoadingSlide />
})
}
}- Access your presentation at
http://localhost:3000/presentations/my-presentation
- → or Space: Next slide
- ←: Previous slide
- Home: First slide
- End: Last slide
- Direct slide access: Navigate to specific slides with
?slide=N - Presentation routing: Access presentations at
/presentations/[id] - Main page: Lists all available presentations at
/
- Presentation Library: Use the search and filter interface on the main page to find presentations
- Quick Access: Search by keywords, author, or date to quickly locate presentations
- Real-time Results: See filtered results instantly as you type or change filters
You can create your own slide templates by adding them to src/components/slides/SlideTemplates.tsx:
type CustomSlideProps = {
readonly title: string
readonly content: string
}
export function CustomSlide({ title, content }: CustomSlideProps) {
return (
<Slide className="p-16 bg-gradient-to-br from-purple-900 to-blue-900">
<div className="max-w-6xl mx-auto w-full h-full flex flex-col justify-center items-center">
<h1 className="text-6xl font-bold mb-8 text-center">{title}</h1>
<p className="text-2xl text-center">{content}</p>
</div>
</Slide>
)
}The app uses Tailwind CSS for styling. You can customize the appearance by:
- Modifying the existing slide templates
- Creating new templates with custom styles
- Updating the global styles in
src/app/globals.css
src/
├── app/
│ ├── page.tsx # Main presentation list page
│ ├── layout.tsx # App layout with theme provider
│ ├── globals.css # Global styles
│ └── presentations/
│ └── [id]/
│ └── page.tsx # Dynamic presentation routes
├── components/
│ ├── SlideContainer.tsx # Navigation and slide management
│ ├── SlidePresenter.tsx # Presentation wrapper
│ ├── LoadingSlide.tsx # Loading state component
│ ├── Navigation.tsx # Navigation controls
│ ├── ThemeProvider.tsx # Theme context provider
│ ├── ThemeToggle.tsx # Theme switching component
│ └── slides/
│ └── SlideTemplates.tsx # Slide template components
├── lib/
│ └── presentation-registry.ts # Centralized presentation registry
└── presentations/
├── sample.tsx # Example presentation
└── code-sample.tsx # Code examples presentation
The app features a centralized presentation registry that manages all presentations with type-safe metadata:
- Type-safe metadata: Structured information about each presentation
- Dynamic loading: Presentations are loaded on-demand for better performance
- Centralized management: All presentations registered in one place
- SEO-friendly: Each presentation gets its own route and metadata
type PresentationMetadata = {
id: string;
title: string;
subtitle?: string;
author?: string;
date?: string;
description?: string;
}
type PresentationEntry = {
metadata: PresentationMetadata;
component: React.ComponentType;
}- Create your presentation component in
src/presentations/ - Add an entry to the registry in
src/lib/presentation-registry.ts - Your presentation will automatically appear in the main list and be accessible via
/presentations/[id]
- Full TypeScript IntelliSense in your IDE
- Compile-time error checking
- Easy refactoring and renaming
- Better debugging with source maps
- Hot reloading with Turbopack
- Clear component boundaries
- Easy to test individual slides
- No complex build configuration
- Standard Next.js project structure
- Centralized presentation registry
- No additional build steps or loaders
- Faster development server startup with Turbopack
- Smaller bundle size (no MDX runtime)
- Better tree shaking
- Dynamic loading of presentations
We welcome contributions! Here are some ways you can help:
- Add new slide templates to
src/components/slides/SlideTemplates.tsx - Improve the navigation system in
src/components/Navigation.tsx - Enhance styling and themes in the CSS files
- Add presentation examples in
src/presentations/ - Improve the registry system in
src/lib/presentation-registry.ts
The codebase is designed to be easily extensible with full TypeScript support.
MIT License © 2025 Theoklitos Bampouris