---
title: Gemini Clone
description: Open-source Gemini clone in React with a centered greeting over an ambient glow, a single-row pill composer, avatar-free assistant replies, and disabled, ready, and stop send states.
---
import { Gemini } from "@/components/examples/gemini";
## Overview
The Gemini Clone shows how to restyle assistant-ui to match Google Gemini's current interface. The empty state centers a single-line greeting over a soft blue glow, and a single-row pill composer is shared by both the empty and chat states. Assistant replies render as full-width markdown with no avatar, and user turns sit in a rounded grey bubble.
## Features
- **Centered greeting**: one "How can I help you today?" headline, centered over a blurred radial glow.
- **Single-row composer**: a 32px pill that holds the `+` menu, the input, the model picker, the mic, and send on one line.
- **Combined `+` menu**: "Add photos & files" sits next to the Deep Research, Canvas, Create image, and Guided Learning tools.
- **Model picker**: Fast and Thinking, each with a short description and a check mark on the active model.
- **Send states**: a disabled grey arrow when empty, a blue arrow when ready, and a stop square while a response streams.
- **Avatar-free replies**: assistant messages are full-width markdown, with the action bar revealed on hover.
- **Grey user bubble**: a `rounded-3xl` warm-grey bubble, right-aligned, with copy and edit actions on hover.
## Quick Start
```bash
npx assistant-ui add thread
```
## Code
The empty and chat states render the same `Composer`. It is a flex column: an optional attachment row on top, then a single action row with the input as the `flex-1` middle and the controls bottom-aligned around it.
```tsx
import {
AuiIf,
ComposerPrimitive,
ThreadPrimitive,
} from "@assistant-ui/react";
export const Gemini = () => (
s.thread.isEmpty}>
!s.thread.isEmpty}>
);
const Composer = () => (
s.composer.attachments.length > 0}>
);
```
### Send states
The trailing slot swaps between Send and Cancel with `AuiIf`. `ComposerPrimitive.Send` disables itself while the composer is empty, so the disabled, ready, and running looks are all driven by state instead of manual class toggling:
```tsx
{/* Send: disabled grey when empty, blue when there is text */}
!s.thread.isRunning}>
{/* Cancel: stop square while a response streams */}
s.thread.isRunning}>
```
### Combined `+` menu
The `+` button opens one menu for both attachments and tools. `ComposerPrimitive.AddAttachment` is rendered as the first item through the `render` prop, so picking it opens the file dialog and closes the menu:
```tsx
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
}>
Add photos & files
Deep Research
Canvas
{/* Create image, Guided Learning ... */}
```
### Ambient glow
The empty state places a single blurred ellipse behind the greeting and composer. It is decorative, so it is `pointer-events-none` and `aria-hidden`:
```tsx
How can I help you today?
```
### Color palette
| Element | Light | Dark |
| ------------------ | --------------------- | --------- |
| Background | `#fdfcfc` | `#131314` |
| Composer surface | `#ffffff` | `#1e1f20` |
| Primary text | `#1f1f1f` | `#e3e3e3` |
| Muted text & icons | `#444746` | `#c4c7c5` |
| User bubble | `#f2f0f0` | `#333537` |
| Send (ready) | `#d3e3fd` | `#1f3760` |
| Ambient glow | `#a9d1fb` | `#1d4068` |
### Messages
Assistant replies have no avatar; the markdown spans the full content width and the action bar (feedback, copy, regenerate, more) fades in on hover. User turns sit in a rounded grey bubble, right-aligned, with copy and edit actions to its left:
```tsx
```
## Source