# AI home

> An AI assistant's start page — a soft AI glow, a greeting, the large composer with Ask/Agent modes, and starter cards.

A shadcn/ui block from the [@quill](https://www.quilldesignsystem.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/quill/ai-home).

- Page, with a live preview: https://shadcn.exchange/r/quill/ai-home
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/quill/ai-home-light-9ec37ce72c2e5d1b.png
- Registry item: https://www.quilldesignsystem.com/r/ai-home.json
- Categories: ai
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://www.quilldesignsystem.com/r/ai-home.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `https://www.quilldesignsystem.com/r/prompt-composer.json`, `https://www.quilldesignsystem.com/r/ai-mark.json`, `https://www.quilldesignsystem.com/r/suggested-prompts.json`

## Notes from the registry

An AI assistant's start page — a soft AI glow, a greeting, the large composer with Ask/Agent modes, and starter cards. Do: Keep the AI glow to this one start page. Don't: Add the glow behind other sections or pages — it marks the AI home, and repeated it becomes decoration. Use prompt-composer when you only need the box, inside a page that is about something else. Use chat when two people are messaging; there is no AI.

## Files

### `registry/blocks/ai-home.tsx`

```tsx
'use client'

import * as React from 'react'
import { PromptComposer } from '@/components/ui/prompt-composer'
import { Button } from '@/components/ui/button'
import { Icon } from '@/components/ui/icon'
import { SuggestedPrompts } from '@/components/ui/suggested-prompts'

const STARTERS = [
  { title: 'Brainstorm', detail: 'Ideas for a launch', prompt: 'Brainstorm ideas for our next launch' },
  { title: 'Draft a brief', detail: 'From my notes', prompt: 'Draft a brief from my notes' },
  { title: 'Plan my week', detail: 'Around my meetings', prompt: 'Plan my week around my meetings' },
  { title: 'Find', detail: 'Tasks due soon', prompt: 'Find tasks due soon' },
]

/** An AI assistant's start page — a soft AI glow, a greeting, the large composer with Ask/Agent modes, and starter cards. */
export function AiHome({
  greeting = 'What should we work on?',
  starters = STARTERS,
  onSubmit = () => {},
  onAdd,
  onMic,
}: {
  greeting?: string
  starters?: { title: string; detail: string; prompt: string }[]
  onSubmit?: (value: string) => void
  onAdd?: () => void // shows the + button (files, apps or context)
  onMic?: () => void // shows the mic while the box is empty
}) {
  const [value, setValue] = React.useState('')
  const composerRef = React.useRef<HTMLTextAreaElement>(null)
  return (
    // Not place-content-center: that sizes the one column to its widest child (the
    // starter row, 592px), so the composer's max-w-2xl never reached 672px.
    <section className="ai-glow grid min-h-[32rem] content-center justify-items-center gap-5 px-4 py-16">
      {/* The approved sketch's heading: Fraunces' text cut at 24px, normal tracking — calmer than h1's display preset. */}
      <h1 className="fraunces-text text-center font-heading text-xl font-medium tracking-normal">{greeting}</h1>
      <div className="w-full max-w-2xl">
        <PromptComposer
          ref={composerRef}
          size="lg"
          value={value}
          onValueChange={setValue}
          onSubmit={(v) => { onSubmit(v); setValue('') }}
          onMic={onMic}
          leading={onAdd ? (
            <Button type="button" size="icon" variant="ghost" className="rounded-full border border-border" aria-label="Add files or context" onClick={onAdd}>
              <Icon name="add" className="size-4" />
            </Button>
          ) : null}
          modes={[
            { value: 'ask', label: 'Ask', ai: true, placeholder: 'Ask anything. Type / for skills, @ to add context' },
            { value: 'agent', label: 'Agent', icon: <Icon name="person" />, placeholder: 'What should your agent take on?' },
          ]}
        />
      </div>
      <SuggestedPrompts
        layout="cards"
        label="Starters"
        className="w-full max-w-2xl"
        suggestions={starters.map((s) => ({ label: s.title, detail: s.detail, prompt: s.prompt }))}
        onPick={(prompt) => { setValue(prompt); composerRef.current?.focus() }}
      />
    </section>
  )
}
```
