Skip to content

dtecx/clicky-store

Repository files navigation

Clicky-Store

A focused e-commerce sandbox for gaming and office mice — built with Go on the back, React on the front.

Go React TypeScript Tailwind CSS Vite PostgreSQL Docker CI


Clicky-Store is an educational online shop. It carries two product categories — gaming and office — and ships with the full e-commerce loop: browse, search, view a dedicated product page, add to cart, place an order, simulate payment, and manage everything from an admin dashboard.

Backend is plain net/http Go with a hexagonal layout (domains / ports / adapters). Frontend is a Vite-built React SPA in TypeScript, styled with Tailwind 4 and served by the same Go binary in production. PostgreSQL handles persistence; an in-memory store is the dev-only fallback.


Highlights

Customer Admin Platform
Browse, search, sort, filter Product CRUD with sectioned form PostgreSQL persistence
Dedicated product pages by slug JPEG/PNG image upload (drag-and-drop, max 10 / product) In-memory fallback for tests
Image gallery with thumbnails Image reorder, primary, alt text, delete HMAC-signed bearer tokens
Quantity controls + sticky mobile buy bar Order browsing, filtering, status badges Bcrypt password hashing
Cart, checkout, order placement User browsing + role updates Login rate limiting
Simulated payment (success/failure) Dashboard with revenue + low-stock alerts Local upload storage with safe filename gen
Auth + protected routes Server-side category whitelist (gaming / office) Multi-stage Docker build

Quick start (Docker Compose)

git clone <your-fork-url> clicky-store
cd clicky-store
cp .env.example .env          # optional — defaults work for local dev
docker compose up --build

The storefront and API both serve from one container at:

http://localhost:8080

Health probe:

curl http://localhost:8080/healthz

Seeded admin account (development only):

email:    admin@clicky.local
password: admin12345

Heads up. Outside APP_ENV=development the seeded admin is disabled and AUTH_SECRET must be set to a non-demo value. See docs/deployment.md.


Local dev (without Docker)

Three terminals — Postgres in Compose, the Go backend, and the Vite dev server with API proxy:

# 1. Database
docker compose up db

# 2. Backend
go run ./cmd/server

# 3. Frontend
cd frontend
npm install
npm run dev

The Vite dev server proxies /api/v1, /uploads, and /healthz to localhost:8080, so the SPA at http://localhost:5173 talks to the running Go backend without CORS gymnastics.


Tech stack

Backend     Go 1.25 · net/http · pgx · golang.org/x/crypto
Frontend    React 19 · Vite 8 · TypeScript · Tailwind CSS 4 · React Router 7 · lucide-react
Storage     PostgreSQL 16 (memory fallback)
Auth        HMAC-signed bearer tokens · bcrypt password hashing
DevOps      Docker · Docker Compose · multi-stage build · GitHub Actions CI

API surface

Public endpoints
GET  /healthz
GET  /api/v1/products
GET  /api/v1/products/{productId}
GET  /api/v1/products/slug/{slug}
POST /api/v1/auth/register
POST /api/v1/auth/login
Customer endpoints (Bearer token)
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/simulate
Admin endpoints (admin role required)
GET    /api/v1/admin/products
POST   /api/v1/admin/products
PATCH  /api/v1/admin/products/{productId}
DELETE /api/v1/admin/products/{productId}
POST   /api/v1/admin/products/{productId}/images
PATCH  /api/v1/admin/products/{productId}/images/order
PATCH  /api/v1/admin/products/{productId}/images/{imageId}
DELETE /api/v1/admin/products/{productId}/images/{imageId}
GET    /api/v1/admin/orders
GET    /api/v1/admin/users
GET    /api/v1/admin/users/{userId}
PATCH  /api/v1/admin/users/{userId}

The OpenAPI spec lives in docs/openapi.yaml. Runnable curl recipes live in docs/api-examples.md.


Example flow

# Register
curl -sS -X POST http://localhost:8080/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"name":"Test User","email":"test@example.com","password":"password123"}'

# Browse
curl -sS http://localhost:8080/api/v1/products | jq

# Direct product lookup by slug
curl -sS http://localhost:8080/api/v1/products/slug/viper-x1-gaming-mouse | jq

# Add to cart
curl -sS -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}'

# Place order
curl -sS -X POST http://localhost:8080/api/v1/orders \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"paymentMethod":"simulation"}'

# Simulate payment success or failure
curl -sS -X POST http://localhost:8080/api/v1/orders/<order-id>/payment/simulate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"result":"success"}'   # or "failure"

Project structure

clicky-store/
├── cmd/
│   ├── server/                  HTTP server composition root
│   └── initcatalog/             Manual validator for init/init.json
├── internal/
│   ├── adapters/
│   │   ├── db/                  In-memory store + contract tests
│   │   ├── db/postgres/         PostgreSQL adapter + embedded migrations
│   │   ├── http/v1/             REST API v1 handlers, requests, middleware
│   │   └── uploads/             Local product image upload storage
│   ├── core/
│   │   ├── domains/             Domain models, validation, shared errors
│   │   └── ports/               Storage interfaces
│   ├── service/                 Application use cases + auth
│   ├── frontend/                React build serving adapter
│   ├── initcatalog/             Validated demo catalog loader
│   ├── config/                  Environment loading + production secret guards
│   └── web/                     Shared HTTP / JSON / middleware helpers
├── frontend/
│   ├── src/                     React + TS source (pages, components, state, API)
│   └── public/assets/products/  Seed product SVGs shipped with the build
├── init/                        Demo catalog JSON + ignored local image source folder
├── docs/                        OpenAPI + dev/deploy/API docs
├── compose.yaml                 Local API + PostgreSQL services
├── Dockerfile                   Multi-stage React + Go production image
└── AGENTS.md                    Contributor + AI-agent guidance + roadmap

Catalog model

Two categories, server-side enforced:

gaming    High-DPI competitive picks
office    Quiet, ergonomic desk mice

Demo catalog seeding is opt-in. Drop matching JPG/PNG files into init/img/{slug}/ to match the entries in init/init.json, then start the server. The initializer validates every JSON field plus every referenced image (extension, MIME sniff, decoded headers, size). If anything fails validation, the original four fallback products remain.

# Validate the demo catalog locally
go run ./cmd/initcatalog -path init/init.json

Documentation

docs/
├── openapi.yaml         Machine-readable API spec
├── api-examples.md      Curl recipes
├── development.md       Local dev workflow + env vars
└── deployment.md        Production deploy + secrets + upload storage

AGENTS.md is the source of truth for contributor and AI-agent rules — design tokens, do/don't lists, phase plans, commit conventions.


Status

Educational project. No license file is attached; treat the repository as "look, learn, fork — no production warranty." Security limitations are documented honestly in AGENTS.md and docs/deployment.md.

CI runs gofmt, go test, go vet, the frontend lint + build, and a full Docker image build on every push to main and every pull request.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages