A small drinks website built from Payload's official website template. Editors configure reusable Drinks Menu blocks; the website fetches cocktail or mocktail images, ingredients, and preparation instructions from TheCocktailDB.
- Next.js, React, TypeScript, Tailwind CSS
- Payload CMS 3.89 with PostgreSQL
- PostgreSQL 17 in Docker; the application runs locally with npm
- TheCocktailDB's public educational test key
Install Git, Docker Desktop (Linux containers), and Node.js 24 LTS. Start Docker Desktop.
git clone YOUR_GITHUB_REPOSITORY_URL
cd eagerly-payload
npm ci
Copy-Item .env.example .envIf you cloned into a different folder name, use that name with cd.
Edit .env. Choose a local alphanumeric database password and use it for both POSTGRES_PASSWORD and the password inside DATABASE_URL. Replace each secret placeholder with a separate random value. Generate each value with:
node -e "console.log(require('node:crypto').randomBytes(32).toString('hex'))"Start the database:
docker compose up -d postgres
docker compose ps
npm run devWait for the database to be healthy. Open http://localhost:3000/admin and create your local admin account. This CMS login is separate from the PostgreSQL login.
Stop the dev server with Ctrl+C, then create the demo homepage:
npm run seed:demo
npm run devOpen http://localhost:3000. The seed creates a published home page with two Drinks Menu blocks. It preserves any existing home page. It does not create accounts or copy credentials.
Optional: under Globals > Header, add custom links Cocktails → /#cocktails and Mocktails → /#mocktails.
The original desktop uses a manually created container named eagerly-postgres. Continue starting that container with docker start eagerly-postgres; do not start the Compose database on the same port alongside it. The Compose configuration is for a fresh laptop database and uses a separate volume. It does not automatically adopt the original container's data.
On the laptop, start Docker Desktop, then:
docker compose up -d postgres
npm run devStop the app with Ctrl+C and the database with docker compose stop. The named volume retains the database. docker compose down -v deletes that volume and its data. Changing the password variable does not reset a database that has already been initialized.
src/blocks/DrinksMenu/config.ts: CMS field definitions.src/collections/Pages/index.ts: makes the block available on pages.src/blocks/RenderBlocks.tsx: maps saved block types to React components.src/blocks/DrinksMenu/Component.tsx: fetches drink summaries and renders cards.src/blocks/DrinksMenu/getDrinkRecipe.ts: fetches each selected drink's recipe and normalizes ingredient fields.src/payload-types.ts: generated types; runnpm run generate:typesafter changing CMS field definitions.
The CMS stores heading, selection, and count. Drink data comes from the external API with a one-hour Next.js cache lifetime. Opening a recipe reveals already-fetched content. On a cold cache, each block makes one list request plus one detail request per displayed drink. One failed recipe keeps the other cards usable. Names beginning with numbers are excluded from the demo selection; displayed names remain unchanged.
The provided TypeScript response types describe expected API data; comprehensive runtime response validation is not yet implemented. This is a learning demo, not a production deployment configuration.
npx tsc --noEmit --incremental false
npm run lintManually verify both menus, recipe expansion, mobile layout, and CMS edits. npm run build performs a production build and requires the configured database; external API access is needed for live recipe content.
Create an empty repository on GitHub (do not initialize it with a README). From this project folder:
git status
git add .
git diff --cached --stat
git diff --cached
git commit -m "Build After Hours Payload drinks demo"
git branch -M main
git remote add origin YOUR_GITHUB_REPOSITORY_URL
git push -u origin mainCheck the staged diff before committing. .env, database backups, local uploads, dependencies, build output, and WebStorm settings should remain excluded. If an origin already exists, inspect git remote -v and use git remote set-url origin YOUR_GITHUB_REPOSITORY_URL instead of adding a duplicate.
Git transfers code, not PostgreSQL content, CMS accounts, or local uploads. The laptop seed recreates the basic demo page. Existing customized pages need a separate database backup/restore if you want an exact copy; keep backups out of the repository.
Based on the Payload website template. Recipes and images come from TheCocktailDB. Its public test key is intended for development and educational use; review its terms before public production use.
TypeScript checks pass. The seed command was verified to preserve an existing homepage; a fresh laptop installation has not yet been tested. The inherited ESLint configuration currently crashes with a circular-structure error against the installed Next.js ESLint package. This does not prevent the development server from running, but lint configuration needs updating before treating lint as a passing check.
Each menu has a Shuffle button that replaces the displayed drinks while keeping the CMS-configured count and alcohol selection. A client component manages loading and errors; a validated Server Action fetches the data and recipes. It avoids currently displayed drink IDs when enough alternatives exist. Failed requests preserve the existing cards. The list and recipes remain cached, while selection is randomized on each button click.