Clicky-Store is a small e-commerce project for gaming and office mice. The project brief in plan/plan.pdf asks for a client-server web store with a REST API, user accounts, product browsing, cart management, order placement, online payment handling or simulation, admin management, responsive UI, security basics, testing, and documentation.
This repository is starting with the backend and container foundation using:
- Go for the HTTP API
- Docker Compose for local services
- React, Vite, TypeScript, and Tailwind CSS for the storefront and admin UI
- PostgreSQL in Compose for durable persistence
Implemented backend features:
- Public product listing and product details
- Customer registration and login
- HMAC-signed bearer tokens
- Basic login rate limiting
- Authenticated profile endpoint
- Authenticated cart operations
- Authenticated order creation with pending simulated payment status
- Authenticated payment simulation for pending orders
- Admin product management
- Admin order listing
- Admin user listing, inspection, and role updates
- React storefront for browsing, product details, auth, cart, checkout, orders, and admin screens
- Health check endpoint
- Multi-stage Dockerfile and
compose.yaml - GitHub Actions CI for format checks, tests, vet, and Docker build
- PostgreSQL persistence for users, products, carts, and orders when
DATABASE_URLis set - Go production serving for the React build with SPA route fallback
The API uses PostgreSQL when DATABASE_URL is configured. If DATABASE_URL is empty, the server falls back to the in-memory store for lightweight local development and tests.
Optional local configuration can start from:
cp .env.example .envdocker compose up --buildThe API and React storefront listen on:
http://localhost:8080Open the storefront at:
http://localhost:8080/Health check:
curl http://localhost:8080/healthzSeeded admin account:
email: admin@clicky.local
password: admin12345Set a stronger local secret before serious testing:
AUTH_SECRET="replace-me" docker compose up --buildDATABASE_URL defaults to the PostgreSQL service in compose.yaml. Leave it empty only when you intentionally want the server to use the in-memory development store.
Development mode (APP_ENV=development) provides demo defaults for AUTH_SECRET and the seeded admin account. Outside development, set a non-demo AUTH_SECRET; admin seeding only runs when ADMIN_NAME, ADMIN_EMAIL, and ADMIN_PASSWORD are all configured.
More detailed API and setup documentation is available in:
docs/openapi.yaml
docs/api-examples.md
docs/development.md
docs/deployment.mdPublic endpoints:
GET /healthz
GET /api/v1/products
GET /api/v1/products/{productId}
POST /api/v1/auth/register
POST /api/v1/auth/loginCustomer endpoints:
GET /api/v1/me
GET /api/v1/cart
POST /api/v1/cart/items
PATCH /api/v1/cart/items/{productId}
DELETE /api/v1/cart/items/{productId}
GET /api/v1/orders
POST /api/v1/orders
POST /api/v1/orders/{orderId}/payment/simulateAdmin endpoints:
GET /api/v1/admin/products
POST /api/v1/admin/products
PATCH /api/v1/admin/products/{productId}
DELETE /api/v1/admin/products/{productId}
GET /api/v1/admin/orders
GET /api/v1/admin/users
GET /api/v1/admin/users/{userId}
PATCH /api/v1/admin/users/{userId}Use the token from login/register as:
Authorization: Bearer <token>Register:
curl -X POST http://localhost:8080/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","password":"password123"}'List products:
curl http://localhost:8080/api/v1/productsAdd to cart:
curl -X POST http://localhost:8080/api/v1/cart/items \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"productId":"prod-gaming-viper","quantity":1}'Create an order:
curl -X POST http://localhost:8080/api/v1/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"paymentMethod":"simulation"}'Simulate payment:
curl -X POST http://localhost:8080/api/v1/orders/<order-id>/payment/simulate \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"result":"success"}'Use "failure" to mark the pending simulated payment as failed.
- Add product image gallery persistence
- Add admin-only product image upload storage and API endpoints
- Add drag-and-drop product image management in React
- Display uploaded galleries across product cards, details, cart lines, and admin tables
- Remove the legacy static frontend after the React app covers every required flow and image path
cmd/server/ Go HTTP server composition root
internal/adapters/db/ Current in-memory database adapter
internal/adapters/db/postgres PostgreSQL adapter and embedded migrations
internal/adapters/http/v1 REST API v1 handlers and request DTOs
internal/core/domains/ Domain models and shared domain errors
internal/core/ports/ Storage interfaces
internal/frontend/ Static frontend serving adapter and temporary legacy assets
internal/service/ Application use cases and auth helpers
internal/web/ Shared HTTP JSON and middleware helpers
frontend/ React + Vite + TypeScript + Tailwind source app
compose.yaml Local API and database services
Dockerfile Multi-stage React and Go production image
plan/ Local project brief files, ignored by git