# Template Gallery Page

> A gallery of ready-made workspace templates: search hero with fanned previews, categories, sort, drawn template cards and a detail dialog.

- Type: React template (Templates)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.0
- Install: `npx wingo-ui@latest add template-gallery-page`
- Docs: https://wingo-ui.com/templates/template-gallery-page

## Interaction

The hero rises in once on mount over three template cards fanned out below the search (bold: cascaded beside the title); each one opens its template. Typing in the search filters the gallery live (/ focuses it, Escape clears, Enter scrolls to the results) and the popular chips fill it in. On desktop a sticky sidebar picks a category with live counts and a Made by filter (Everyone, Acme, Community); below 1024px the categories become a chip row that scrolls sideways and the Made by filter a segmented control. Popular / Newest / A to Z re-sorts the cards, which glide to their new places; twelve show at first and Show more opens the rest. No match shows an empty state with Clear filters. Every card draws a mini app of what the template is (kanban, roadmap, doc, OKRs, calendar, pipeline, bug table, checklist, automation flow, dashboard, sticky notes, form, habit grid) and is one button: it opens a detail dialog (a bottom sheet below 768px) with a large preview, what's included, the views, the creator and related templates, which swap in place. Use template spins, then confirms Added to your workspace with an Open template link, and the card gets an Added badge. The featured collection rail snaps sideways on phones and Add all adds its four templates. The community band links to submitting a template; the closing band and footer newsletter follow. Reduced motion keeps everything still.

## Installation

```bash
npx wingo-ui@latest add template-gallery-page
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/template-gallery-page` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `components/templates/template-gallery-page.tsx`
- `components/templates/template-gallery-page-data.ts`

npm dependencies: `npm i lucide-react motion`

Wingo UI dependencies (installed automatically):

- [Marketing Section](https://wingo-ui.com/components/marketing-section) ([Markdown](https://wingo-ui.com/components/marketing-section.md))
- [Marketing Header](https://wingo-ui.com/components/marketing-header) ([Markdown](https://wingo-ui.com/components/marketing-header.md))
- [Marketing Footer](https://wingo-ui.com/components/marketing-footer) ([Markdown](https://wingo-ui.com/components/marketing-footer.md))
- [CTA Section](https://wingo-ui.com/components/cta-section) ([Markdown](https://wingo-ui.com/components/cta-section.md))
- [Avatar](https://wingo-ui.com/components/avatar) ([Markdown](https://wingo-ui.com/components/avatar.md))
- [Badge](https://wingo-ui.com/components/badge) ([Markdown](https://wingo-ui.com/components/badge.md))
- [Button](https://wingo-ui.com/components/button) ([Markdown](https://wingo-ui.com/components/button.md))
- [Dialog](https://wingo-ui.com/components/dialog) ([Markdown](https://wingo-ui.com/components/dialog.md))
- [Empty State](https://wingo-ui.com/components/empty-state) ([Markdown](https://wingo-ui.com/components/empty-state.md))
- [Search Input](https://wingo-ui.com/components/search-input) ([Markdown](https://wingo-ui.com/components/search-input.md))
- [Segmented Control](https://wingo-ui.com/components/segmented-control) ([Markdown](https://wingo-ui.com/components/segmented-control.md))
- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Navigation](https://wingo-ui.com/components/navigation) ([Markdown](https://wingo-ui.com/components/navigation.md))
- [Text match](https://wingo-ui.com/components/text-match) ([Markdown](https://wingo-ui.com/components/text-match.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [UIProvider](https://wingo-ui.com/components/ui-config) ([Markdown](https://wingo-ui.com/components/ui-config.md))

## Usage

```tsx
// app/(marketing)/templates/page.tsx
"use client"

import Link from "next/link"
import { useRouter } from "next/navigation"
import { TemplateGalleryPage } from "@/components/templates/template-gallery-page"

export default function TemplatesRoute() {
  const router = useRouter()
  return (
    <TemplateGalleryPage
      linkComponent={Link}
      ctaTone="brand"
      templateHref={(template) => `/app/templates/${template.id}`}
      onUseTemplate={async (template) => {
        const response = await fetch("/api/templates/copy", { method: "POST", body: JSON.stringify({ id: template.id }) })
        if (response.status === 401) router.push(`/sign-up?template=${template.id}`)
        if (!response.ok) throw new Error("Could not copy the template")
      }}
    />
  )
}
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `design?` | `"classic" \| "bold" \| "minimal"` | `"classic"` | The whole page's look. classic: a centered hero over a fanned stack of three template cards, raised cards and a gray collection band; bold: a pill header, a split hero with heavy type on a gradient mesh and a cascade of cards, bigger tiles, an inverted collection panel, an image band and a wordmark footer; minimal: a transparent header, a quiet hero without previews, flat cards with outlined previews, no gray bands, plain closing and a simple footer. |
| `templates?` | `GalleryTemplate[]` | `"GALLERY_TEMPLATES"` | The gallery: { id, name, description, summary?, category, preview, previewItems?, creator: { name, role?, team? }, uses, plan: free \| business, createdAt, includes, views?, keywords? }. preview picks the drawn mini app; previewItems feeds it words. |
| `categories?` | `TemplateCategory[]` | `"TEMPLATE_CATEGORIES"` | { value, label, description? } for the sidebar and the chip row: Product, Engineering, Design, Marketing, HR, Operations, Personal. |
| `collection?` | `TemplateCollection` | `"TEMPLATE_COLLECTION"` | The featured collection: { eyebrow, title, description, steps: { template (id), label, note }[] }. |
| `heroTemplates?` | `string[]` | `"TEMPLATE_GALLERY_HERO"` | Three template ids drawn in the hero: back left, front, back right. |
| `popularSearches?` | `string[]` | `"TEMPLATE_POPULAR_SEARCHES"` | The chips under the search; a tap fills the search and scrolls to the results. |
| `labels?` | `Partial<TemplateGalleryPageLabels>` | `"DEFAULT_TEMPLATE_GALLERY_PAGE_LABELS"` | Every visible string; counts and names go through small functions (results, uses, previewTemplate...). |
| `hrefs?` | `Partial<TemplateGalleryPageHrefs>` | `"DEFAULT_TEMPLATE_GALLERY_PAGE_HREFS"` | { submit, guidelines, signUp, sales }: the community submit form, its guidelines and the closing band's buttons. |
| `category?` | `string` |  | The selected category (controlled): "all" or a category value. |
| `defaultCategory?` | `string` | `"all"` | The category selected at first (uncontrolled). |
| `onCategoryChange?` | `(category: string) => void` |  | Runs when a category is picked. |
| `query?` | `string` |  | The search text (controlled). |
| `defaultQuery?` | `string` | `""` | The search text at first (uncontrolled). |
| `onQueryChange?` | `(query: string) => void` |  | Runs on every keystroke in the search. |
| `defaultSort?` | `"popular" \| "newest" \| "az"` | `"popular"` | The first order of the cards: most used, most recently published, or by name. |
| `defaultSource?` | `"all" \| "acme" \| "community"` | `"all"` | The Made by filter at first: everyone, the Acme team only, or community members only. |
| `columns?` | `2 \| 3` | `3` | Cards per row from 1280px (two from 640px either way, one on phones). |
| `pageSize?` | `number` | `12` | Cards shown before a Show more button that opens the rest of the matches; a new search, category, filter or sort pages again. 0 shows every match. |
| `ctaVariant?` | `"inverted" \| "soft" \| "split"` | `"inverted"` | The closing band: a solid band, a gray band, or copy beside the buttons on a raised panel. Applies to the classic design. |
| `showPopular?` | `boolean` | `true` | The popular search chips under the search. |
| `showHeroPreviews?` | `boolean` | `true` | The three template cards in the hero (classic and bold). |
| `showSidebar?` | `boolean` | `true` | The sticky category sidebar from 1024px; off, the chip row shows at every width. |
| `showSourceFilter?` | `boolean` | `true` | The Made by filter: Everyone, Acme, Community. |
| `showSort?` | `boolean` | `true` | The Popular / Newest / A to Z control. |
| `showCollection?` | `boolean` | `true` | The featured collection rail. |
| `showSubmit?` | `boolean` | `true` | The community band with the top creators, and the sidebar's submit card. |
| `showCta?` | `boolean` | `true` | The closing call to action. |
| `tone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Accents: the selected category chip, the segmented controls, Business badges, the hero pill, the preview glow and the included checks. |
| `ctaTone?` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger" \| "info"` | `"neutral"` | Use template, Add all, Submit a template, the header's Get started and the closing band; brand is the marketing orange. |
| `onUseTemplate?` | `(template: GalleryTemplate) => (void \| Promise<unknown>)` |  | Use template and Add all. A returned promise keeps the button loading; a rejection leaves the template as it was. Without it the button waits 900 ms and confirms. |
| `templateHref?` | `(template: GalleryTemplate) => string` | `"/app/templates/<id>"` | Where Open template goes once the template was added. |
| `onSubscribe?` | `(email: string) => (void \| Promise<unknown>)` |  | The footer newsletter; a rejected promise shows an error. |
| `header?` | `boolean` | `true` | The marketing header; off inside a site layout. |
| `footer?` | `boolean` | `true` | The marketing footer with its newsletter form. |
| `headerProps?` | `Partial<MarketingHeaderProps>` |  | Passed to MarketingHeader. |
| `footerProps?` | `Partial<MarketingFooterProps>` |  | Passed to MarketingFooter. |
| `ctaProps?` | `Partial<CtaSectionProps>` |  | Overrides for the closing CtaSection. |
| `animateIn?` | `boolean` | `true` | The hero and its cards rise in once on mount; false keeps the page still (thumbnails). Reduced motion always does. |
| `locale?` | `string` | `"en-US"` | Intl locale for the use counts (de-DE: 63,9K), publish dates and the A to Z order. |
| `linkComponent?` | `(props: LinkComponentProps) => ReactNode` | `"<a>"` | The router link for every link on the page (next/link in an app). |
| `className?` | `string` |  | Classes for the root. |
| `classNames?` | `Partial<Record<TemplateGalleryPageSlot, string>>` |  | Classes for header, hero, title, search, fan, gallery, sidebar, chips, toolbar, grid, card, preview, collection, submit, detail, cta and footer. |

## Parts

### TemplatePreview (component)

The drawn mini app of a template (an app window peeking out of a tinted panel), sized by its container. Takes div props.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `template?` | `GalleryTemplate` |  | The template to draw; its preview kind picks the scene and previewItems the words. |
| `label?` | `string` |  | The spoken label; without it the scene is decorative. |

### TEMPLATE_GALLERY_SAMPLE (constant)

All the sample content in one object: categories, templates, collection, heroTemplates and popularSearches.

### GALLERY_TEMPLATES (constant)

Twenty-four Acme templates across seven categories, from Sprint board to Personal goals.

### TEMPLATE_CATEGORIES (constant)

Product, Engineering, Design, Marketing, HR, Operations and Personal.

### TEMPLATE_COLLECTION (constant)

Ship a launch in 30 days: PRD, roadmap, sprint board and launch checklist.

### TEMPLATE_GALLERY_HERO (constant)

The three hero template ids.

### TEMPLATE_POPULAR_SEARCHES (constant)

Sprint, Roadmap, OKRs, Meeting notes and Hiring.

### DEFAULT_TEMPLATE_GALLERY_PAGE_LABELS (constant)

The English strings.

### DEFAULT_TEMPLATE_GALLERY_PAGE_HREFS (constant)

The default link targets.

### TEMPLATE_GALLERY_PAGE_DESIGNS (constant)

The design names, classic first: ["classic", "bold", "minimal"].

### TemplateGalleryPageProps (type)

Props of TemplateGalleryPage.

### TemplateGalleryPageDesign (type)

"classic" | "bold" | "minimal".

### TemplateGallerySort (type)

"popular" | "newest" | "az".

### TemplateGallerySource (type)

"all" | "acme" | "community".

### TemplatePreviewProps (type)

Props of TemplatePreview.

### GalleryTemplate (type)

One template of the gallery.

### TemplatePreviewKind (type)

The drawn scenes: kanban, roadmap, doc, meeting, okr, calendar, pipeline, bugs, table, checklist, automation, report, retro, form, habits.

### TemplateCategory (type)

One category.

### TemplateCollection (type)

The featured collection.

### TemplateGalleryPageLabels (type)

The strings labels can override.

### TemplateGalleryPageHrefs (type)

The link targets hrefs can override.

## Examples

- **Bold design**: design="bold": a split hero with heavy type and a cascade of cards, big tiles, an inverted collection panel and a wordmark footer.
- **Minimal design**: design="minimal": a quiet hero without previews, flat cards with outlined previews, no gray bands and a simple footer.
- **Brand orange, newest first**: tone and ctaTone brand with the gallery sorted by Newest: orange chips, Business badges and Use template.
- **Community engineering templates**: defaultCategory engineering and defaultSource community, two columns, without the hero previews.
- **No results**: A search with no match: the empty state with Clear filters.

## See also

- [Integrations Page](https://wingo-ui.com/templates/integrations-page) ([Markdown](https://wingo-ui.com/templates/integrations-page.md))
- [Landing Page](https://wingo-ui.com/templates/landing-page) ([Markdown](https://wingo-ui.com/templates/landing-page.md))
- [Search Input](https://wingo-ui.com/components/search-input) ([Markdown](https://wingo-ui.com/components/search-input.md))
- [Dialog](https://wingo-ui.com/components/dialog) ([Markdown](https://wingo-ui.com/components/dialog.md))
- [Empty State](https://wingo-ui.com/components/empty-state) ([Markdown](https://wingo-ui.com/components/empty-state.md))

---

Canonical: https://wingo-ui.com/templates/template-gallery-page
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
