A website to invite guests and gather RSVP!
- HTML 94.2%
- JavaScript 5.2%
- Dockerfile 0.6%
| node_modules | ||
| public | ||
| .containerignore | ||
| Containerfile | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| server.js | ||
🎉 Birthday Party Invite
A festive birthday party invitation website with RSVP functionality, built with Node.js + Express.
Features
- Invite page — animated balloons, confetti, event details, RSVP form
- RSVP form — name + optional comment, yes/no toggle
- Confirmation —
.icscalendar download if attending, sorry message if not - Guest list page — live list of all RSVPs with stats
Tech Stack
- Backend: Node.js + Express (no database — RSVPs stored as JSON in a volume)
- Frontend: Vanilla HTML/CSS/JS (no build step needed)
- Container: Podman (OCI-compatible; Docker commands work identically)
🚀 Running with Podman
1. Build the image
podman build -t birthday-party .
2. Create a persistent volume
podman volume create birthday-data
3. Run the container
podman run -d \
--name birthday-party \
-p 2727:3000 \
-v birthday-data:/data \
birthday-party
The app is now available at http://localhost:3000
🛠 Useful commands
Stop the container
podman stop birthday-party
Start it again
podman start birthday-party
View logs
podman logs -f birthday-party
Inspect stored RSVPs (from host)
podman run --rm -v birthday-data:/data alpine cat /data/rsvps.json
Remove container (keeps data)
podman rm birthday-party
Remove volume (deletes all RSVPs!)
podman volume rm birthday-data
🔧 Configuration
| Environment variable | Default | Description |
|---|---|---|
PORT |
3000 |
Port the server listens on |
DATA_FILE |
/data/rsvps.json |
Path to the RSVP JSON file |
Override at runtime, e.g.:
podman run -d \
--name birthday-party \
-p 8080:8080 \
-e PORT=8080 \
-v birthday-data:/data \
birthday-party
API
| Method | Path | Body | Description |
|---|---|---|---|
| POST | /api/rsvp |
{ name, attending: bool, comment? } |
Submit or update RSVP |
| GET | /api/rsvps |
— | List all RSVPs |
Re-submitting with the same name (case-insensitive) updates the existing entry.