All work

Axl Pastries

A bakery storefront with a hand-written Go API, built to understand auth from the ground up.

Year
2024
Role
Design & Full Stack Development
Status
In development
  • Next.js 14
  • TypeScript
  • Go
  • Gin
  • PostgreSQL
  • Supabase
  • Zustand
  • Zod
  • Tailwind CSS
Axl Pastries online shop homepage

Overview

An online shop for a pastry business in Puerto Princesa selling cakes, cupcakes, desserts, and muffins, with category browsing, ordering, and custom-message support. A Next.js frontend with Zustand state and Zod-validated forms, backed by a Go API written from scratch: Gin routing, JWT auth, role middleware, and hand-rolled SQL migrations against Postgres.

The challenge

A bakery storefront does not need a custom backend. A BaaS would have shipped it faster. I wrote one in Go anyway, because the goal was to understand what authentication actually involves rather than to call a method that hides it.

The approach

The Go service handles registration, login, email confirmation, and password reset directly: bcrypt hashing via golang.org/x/crypto, JWTs issued and verified in middleware, and a separate role middleware gating admin routes from customer ones. Data access is raw lib/pq with SQL migrations checked into the repo, and no ORM, so the queries and the schema are both explicit. The frontend keeps cart state in Zustand and validates every form with Zod before it reaches the API.

Features & details

Full account lifecycle

Registration, login, email confirmation, forgotten password, and password reset, each written directly rather than delegated to an auth provider. Passwords are bcrypt-hashed and sessions are JWT-based.

Role-separated admin API

Two middleware layers compose on protected routes: one establishes who the caller is, the other decides what that identity may do. Admin endpoints for creating, updating, and deleting products and categories sit behind both; the public catalog endpoints sit behind neither.

Catalog browsing by category

Public endpoints serve the full cake list, individual product detail, and the category index, with the storefront presenting cakes, cupcakes, desserts, and muffins.

Ordering with custom messages

Customers can order for local delivery and attach personalised messages and design requests, the details that matter for a cake order and don't fit a standard product form.

Validated forms end to end

Every form is checked with Zod through React Hook Form before it reaches the API, so validation failures surface at the field rather than as a server error.

Versioned SQL migrations

Schema changes are numbered SQL files checked into the repo, run against Postgres through raw lib/pq with no ORM in between, so the queries and the schema are both explicit.

Outcome

The storefront is live and the Go API covers the full auth surface end to end. The build settled a question I had been avoiding: what a BaaS is actually doing when it hands you a session, which made the architectural choices on later projects, including choosing Supabase deliberately rather than by default, considerably better informed.