Files
lukasandClaude Sonnet 5 79bd64ce8c Add guest/account auth flows, order tracking, and order history UI
- Wire up Better Auth (email/password + Google/Apple SSO) with a
  sign-in/sign-up UI, header account menu, and a basket that follows
  the signed-in-or-guest state.
- Give the order status page a vertical timeline per preparation step
  (with a distinct customer-facing name separate from the machine tag,
  a done/in-progress/queued/pending look, and a sonar-ping highlight on
  the active step), a formatted ETA (relative under 3h, absolute clock
  time beyond that), and Buy again / Get help / Cancel actions.
- Expand Pizza's recipe into 6 steps across a shared prep station and
  the existing oven/assembly stations, with matching schema, seed, and
  domain changes plus updated/added test coverage.
- Add an Orders list (account orders via session, guest orders via a
  locally remembered access-token list) with a shared getOrdersForCustomer
  domain summary, and remember a guest's name/contact after their first
  order so checkout doesn't ask again.
- Improve page transitions with the View Transitions API: a shared
  element morph between an order card and its detail page, a stable
  (non-jumping) header across navigations, and reduced-motion handling.
- Add a Ghost Kitchen wordmark (Space Grotesk, faded "Ghost", ghost
  icon standing in for the "o") and shrink the basket icon to match
  the rest of the header controls.
- Add a run-ghost-kitchen agent skill documenting local setup, the
  dev-server driver, and the gotchas hit along the way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 11:58:24 +02:00

265 lines
7.6 KiB
Markdown

Welcome to your new TanStack Start app!
# Getting Started
To run this application:
```bash
npm install
npm run dev
```
This requires a running Postgres database — see
[Local development database](#local-development-database) below before your
first run.
# Building For Production
To build this application for production:
```bash
npm run build
```
## Styling
This project uses SCSS Modules. Every component that needs styles gets a
co-located `Component.module.scss` next to `Component.tsx`; shared tokens
(colors, spacing, breakpoints) live in `src/styles/_variables.scss`. See
`CLAUDE.md` for the full styling conventions.
## Linting & Formatting
This project uses [eslint](https://eslint.org/) and [prettier](https://prettier.io/) for linting and formatting. Eslint is configured using [tanstack/eslint-config](https://tanstack.com/config/latest/docs/eslint). The following scripts are available:
```bash
npm run lint
npm run format
npm run check
```
## Local development database
This project requires a Postgres database — both for its own data (Drizzle,
see `src/db/schema.ts`) and for Better Auth's own tables (users, sessions,
etc). A `docker-compose.yml` at the repo root starts one:
```bash
docker compose up -d # starts Postgres on localhost:5433
cp .env.example .env.local # sets DATABASE_URL to match
npm run db:migrate # applies this project's Drizzle migrations
npm run auth:migrate # applies Better Auth's own tables
npm run db:seed # seeds a sample Brand, menu, and Machines
npm run dev
```
`DATABASE_URL` in `.env.local` is picked up automatically by both the dev
server and the `drizzle-kit` commands above — no other wiring needed.
After changing `src/db/schema.ts`, generate and apply a new migration rather
than editing the database by hand:
```bash
npm run db:generate
npm run db:migrate
```
## Setting up Better Auth
Generate and set the `BETTER_AUTH_SECRET` environment variable in your
`.env.local`, and make sure `BETTER_AUTH_URL` matches the URL the app is
actually served from (`http://localhost:3000` in local dev):
```bash
npx @better-auth/cli secret
```
Account creation and sign-in live at `/signup` and `/login`, supporting both
email/password and "Continue with Google" / "Continue with Apple" SSO. The
SSO buttons only appear once the corresponding provider's credentials are
set in `.env.local`:
```bash
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
APPLE_CLIENT_ID=...
APPLE_CLIENT_SECRET=...
```
Create OAuth credentials in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
and the [Apple Developer portal](https://developer.apple.com/account/resources/identifiers/list/serviceId)
respectively, with the redirect URI `{BETTER_AUTH_URL}/api/auth/callback/google`
(swap `google` for `apple`). See the
[Better Auth documentation](https://www.better-auth.com) for more on
configuring authentication, and its
[Google](https://www.better-auth.com/docs/authentication/google) and
[Apple](https://www.better-auth.com/docs/authentication/apple) provider
guides for provider-specific setup details.
For Google, `scripts/setup-google-sso.sh` walks you through the Google Cloud
Console steps interactively and writes the resulting `GOOGLE_CLIENT_ID` /
`GOOGLE_CLIENT_SECRET` into `.env` for you:
```bash
./scripts/setup-google-sso.sh
```
Apple's Sign in with Apple doesn't support `localhost` redirect URIs — you
need a real HTTPS domain (a deployment or a tunnel like ngrok) registered on
the Services ID before it's testable, so there's no equivalent script for it
yet.
## Routing
This project uses [TanStack Router](https://tanstack.com/router) with file-based routing. Routes are managed as files in `src/routes`.
### Adding A Route
To add a new route to your application just add a new file in the `./src/routes` directory.
TanStack will automatically generate the content of the route file for you.
Now that you have two routes you can use a `Link` component to navigate between them.
### Adding Links
To use SPA (Single Page Application) navigation you will need to import the `Link` component from `@tanstack/react-router`.
```tsx
import { Link } from "@tanstack/react-router";
```
Then anywhere in your JSX you can use it like so:
```tsx
<Link to="/about">About</Link>
```
This will create a link that will navigate to the `/about` route.
More information on the `Link` component can be found in the [Link documentation](https://tanstack.com/router/v1/docs/framework/react/api/router/linkComponent).
### Using A Layout
In the File Based Routing setup the layout is located in `src/routes/__root.tsx`. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you render `{children}` in the `shellComponent`.
Here is an example layout that includes a header:
```tsx
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'My App' },
],
}),
shellComponent: ({ children }) => (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
</header>
{children}
<Scripts />
</body>
</html>
),
})
```
More information on layouts can be found in the [Layouts documentation](https://tanstack.com/router/latest/docs/framework/react/guide/routing-concepts#layouts).
## Server Functions
TanStack Start provides server functions that allow you to write server-side code that seamlessly integrates with your client components.
```tsx
import { createServerFn } from '@tanstack/react-start'
const getServerTime = createServerFn({
method: 'GET',
}).handler(async () => {
return new Date().toISOString()
})
// Use in a component
function MyComponent() {
const [time, setTime] = useState('')
useEffect(() => {
getServerTime().then(setTime)
}, [])
return <div>Server time: {time}</div>
}
```
## API Routes
You can create API routes by using the `server` property in your route definitions:
```tsx
import { createFileRoute } from '@tanstack/react-router'
import { json } from '@tanstack/react-start'
export const Route = createFileRoute('/api/hello')({
server: {
handlers: {
GET: () => json({ message: 'Hello, World!' }),
},
},
})
```
## Data Fetching
There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the `loader` functionality built into TanStack Router to load the data for a route before it's rendered.
For example:
```tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/people')({
loader: async () => {
const response = await fetch('https://swapi.dev/api/people')
return response.json()
},
component: PeopleComponent,
})
function PeopleComponent() {
const data = Route.useLoaderData()
return (
<ul>
{data.results.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</ul>
)
}
```
Loaders simplify your data fetching logic dramatically. Check out more information in the [Loader documentation](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#loader-parameters).
# Learn More
You can learn more about all of the offerings from TanStack in the [TanStack documentation](https://tanstack.com).
For TanStack Start specific documentation, visit [TanStack Start](https://tanstack.com/start).