diff --git a/packages/client/src/components/dish-host.tsx b/packages/client/src/components/dish-host.tsx
new file mode 100644
index 0000000..205b601
--- /dev/null
+++ b/packages/client/src/components/dish-host.tsx
@@ -0,0 +1,76 @@
+import { useState } from "react"
+import type { Country, Dish } from "@celebrate-esc/shared"
+import { Button } from "@/components/ui/button"
+import { Input } from "@/components/ui/input"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+
+interface DishHostProps {
+ dishes: Dish[]
+ countries: Country[]
+ onAddDish: (name: string, correctCountry: string) => void
+ onReveal: () => void
+}
+
+export function DishHost({ dishes, countries, onAddDish, onReveal }: DishHostProps) {
+ const [name, setName] = useState("")
+ const [country, setCountry] = useState("")
+ const allRevealed = dishes.length > 0 && dishes.every((d) => d.revealed)
+
+ return (
+
+
+ Dish of the Nation
+
+
+ {!allRevealed && (
+
+ setName(e.target.value)} maxLength={100} />
+
+
+
+ )}
+
+ {dishes.length > 0 && (
+
+
{dishes.length} dish(es) added:
+
+ {dishes.map((d) => (
+ -
+ {d.name} → {countries.find((c) => c.code === d.correctCountry)?.name ?? d.correctCountry}
+ {d.revealed && " (revealed)"}
+
+ ))}
+
+
+ )}
+
+ {dishes.length > 0 && !allRevealed && (
+
+ )}
+
+
+ )
+}
diff --git a/packages/client/src/components/dish-list.tsx b/packages/client/src/components/dish-list.tsx
new file mode 100644
index 0000000..f3ae85e
--- /dev/null
+++ b/packages/client/src/components/dish-list.tsx
@@ -0,0 +1,100 @@
+import { useState } from "react"
+import type { Country, Dish, DishGuess } from "@celebrate-esc/shared"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+
+interface DishListProps {
+ dishes: Dish[]
+ myGuesses: DishGuess[]
+ countries: Country[]
+ onGuess: (dishId: string, guessedCountry: string) => void
+}
+
+export function DishList({ dishes, myGuesses, countries, onGuess }: DishListProps) {
+ if (dishes.length === 0) {
+ return (
+
+
+ No dishes yet — the host will add them.
+
+
+ )
+ }
+
+ return (
+
+
+ Dish of the Nation
+
+
+ {dishes.map((dish) => (
+ g.dishId === dish.id)}
+ countries={countries}
+ onGuess={onGuess}
+ />
+ ))}
+
+
+ )
+}
+
+function DishItem({
+ dish,
+ myGuess,
+ countries,
+ onGuess,
+}: {
+ dish: Dish
+ myGuess: DishGuess | undefined
+ countries: Country[]
+ onGuess: (dishId: string, guessedCountry: string) => void
+}) {
+ const [selected, setSelected] = useState(myGuess?.guessedCountry ?? "")
+
+ if (dish.revealed) {
+ return (
+
+
{dish.name}
+
+ Answer: {countries.find((c) => c.code === dish.correctCountry)?.name}
+
+ {myGuess && (
+
+ Your guess: {countries.find((c) => c.code === myGuess.guessedCountry)?.name}
+ {myGuess.guessedCountry === dish.correctCountry ? " ✓" : " ✗"}
+
+ )}
+
+ )
+ }
+
+ return (
+
+
{dish.name}
+
+
+
+ {myGuess && (
+
+ Guessed: {countries.find((c) => c.code === myGuess.guessedCountry)?.name}
+
+ )}
+
+ )
+}
diff --git a/packages/client/src/components/dish-results.tsx b/packages/client/src/components/dish-results.tsx
new file mode 100644
index 0000000..78429ba
--- /dev/null
+++ b/packages/client/src/components/dish-results.tsx
@@ -0,0 +1,39 @@
+import type { GameState, Country } from "@celebrate-esc/shared"
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
+
+interface DishResultsProps {
+ results: NonNullable
+ countries: Country[]
+}
+
+export function DishResults({ results, countries }: DishResultsProps) {
+ return (
+
+
+ Dish Results
+
+
+ {results.map((r) => (
+
+
{r.dish.name}
+
+ Answer: {countries.find((c) => c.code === r.dish.correctCountry)?.name}
+
+ {r.guesses.length === 0 ? (
+
No guesses
+ ) : (
+
+ {r.guesses.map((g) => (
+ -
+ {g.displayName}: {countries.find((c) => c.code === g.guessedCountry)?.name}
+ {g.correct ? " ✓" : " ✗"}
+
+ ))}
+
+ )}
+
+ ))}
+
+
+ )
+}