SlopScore
00 crowd

shopz

Shopping app I built with Claude to learn
Open repo on GitHubgithub.com/Ayishanourish/shopz
TypeScript · ★ 1 · 0 forks · MIT · paperwork by the Cap'mmostly ai (inferred)light human (inferred)works-on-my-machine (inferred)other
listed 2 hours ago by Ayishanourish · last checked 2 hours ago
The owner didn't write this. This repo never submitted itself. The Cap'm found it on a truffle trawl and wrote its paperwork from what GitHub already shows. Picked by hand by the Cap'm on 2026-09-14: Shopping app I built with Claude to learn; its own README says "Shopping app I built with Claude to learn". 1 stars; MIT license. The owner did not submit this. Votes count; awards don't until the owner claims it.

I'm not calling your project slop! Geeze, it's a joke... Do you own this repo?

Log in with GitHub as Ayishanourish. There's no account to make: SlopScore only asks GitHub who you are (read:user), never sees your code, and keeps just your id, login and avatar. Then you can:

  • Keep it, on your terms. Commit your own slopscore.md (spec) and press Refresh. Your paperwork replaces the Cap'm's, and you can submit it for Slop of the Day.
  • Take it down. One click on Remove. It stays gone; the trawl never brings it back.

Log in with GitHub

Can't log in as the owner? Request a takedown. No login needed, and a trawled listing comes down right away.

GitHub says
Shopping app I built with Claude to learn
created
2026-06-10 · pushed 1 month ago · 2 commits · 1 contributor
languages
TypeScript 73%HCL 23%JavaScript 2%Dockerfile 1%HTML 0%CSS 0%
paperwork
contributinglicensereadme 71% health
dependencies
no dependency graph (no manifest, or disabled) · OSV.dev, checked 2 hours ago

Disclosures, inferred by the Cap'm

slopbucket
vibe-coded
category
other
ai_generated
mostly
human_touch
light
status
works-on-my-machine
language (detected)
cssdockerfilehclhtmljavascriptshelltypescript
license (detected)
mit

The Cap'm's log

The Cap'm wrote this paperwork, not the owner. This repo never submitted itself to SlopScore. The Cap'm picked it by hand: Shopping app I built with Claude to learn; its own README says "Shopping app I built with Claude to learn". It carries the MIT license. The disclosures above are his best guess from what GitHub shows.

Is this yours? Commit a real slopscore.md and press Refresh to replace this, or remove the listing in one click. There's no account to make: you log in with GitHub.

README — the repo's own words, folded up so the grading fits on one screen

Shopz

This is a production-ready online store I built with Claude to learn Typescript, React and explore a couple of tools and concepts related to Redis, Docker, Stripe, MailHog, AWS and Github Actions. Claude has filled some gaps that were needed to make this production-ready, but I've focused primarily on those tools.

It's a full e-commerce platform: customers can browse a catalog, add items to a cart, register / log in, check out via Stripe, and view their order history. Admins can manage products, categories, inventory and images from a role-gated admin panel.


Table of contents

  1. What this app does
  2. Live demo flow
  3. Tech stack
  4. Architecture at a glance
  5. Repo layout
  6. Quick start (local dev)
  7. Stripe setup
  8. How to use the app
  9. Available scripts
  10. Testing
  11. Deploying to AWS
  12. Documentation index
  13. License

What this app does

I've tried to solve both the customer facing and merchant facing sides:

Customer side

  • Browse the catalog — search by keyword, filter by category, sort by price/newest, paginate. Lazy-loaded images, mobile-friendly grid.
  • Product detail pages — image gallery, full description, stock level, "Add to cart" with optimistic UI updates.
  • Shopping cart — works for both anonymous guests (cookie-backed) and logged-in users (DB-backed). On login, the guest cart is automatically merged into the user account.
  • Account management — signup with email verification, login, password reset, profile, shipping addresses, order history.
  • Checkout — Stripe-hosted checkout collects payment securely; we never see card numbers. Orders are created server-side via a signed webhook, with stock decremented inside a database transaction so the same item can't be oversold.
  • Order history — list view + detail page showing snapshot of items, prices, status, and shipping address at time of purchase.

Admin side (role-gated, signed in as ADMIN)

  • Product CRUD — create, edit, deactivate (soft-delete). Unique slugs, price in cents, stock, category assignment.
  • Image upload — direct browser-to-S3 upload using presigned URLs. Multiple images per product, ordered.
  • Category CRUD — name + slug + optional description. Blocks deletion if products still reference the category.
  • Audit log — every admin write goes to an AuditLog table: who-did-what-when, with before/after snapshots.

Infrastructure & operations

  • Production-grade auth — JWT access tokens (15 min) + rotating refresh tokens (httpOnly, Secure cookies, 30 days), bcrypt password hashing.
  • CSRF protection — Origin/Referer allowlist on cookie-mutating endpoints.
  • Rate limiting — Redis-backed, shared across multiple API instances.
  • Idempotent webhooks — Stripe events deduped via (provider, eventId) unique constraint; safe to retry.
  • Observability — Pino structured logs with request IDs, Sentry error tracking, Prometheus /metrics endpoint exposing RED metrics + Node defaults.
  • Threat model — documented OWASP Top 10 checklist + mitigations.
  • AWS deployment — Terraform modules for VPC, RDS, ElastiCache, ECS Fargate, ALB, CloudFront, S3, WAF, Secrets Manager. Separate staging and prod environments with different sizing.
  • CI/CD — GitHub Actions: lint, typecheck, test, build, Trivy security scan on every PR; auto-deploy to staging on merge; gated deploy to prod on git tag.

Live demo flow

After setup, here's what works end-to-end:

  1. Open http://localhost:5173 → home page with "Browse products" CTA
  2. Click Products → browse catalog (30 sample products in 6 categories)
  3. Use the search box, category filter, and sort dropdown — URL updates so you can share / bookmark
  4. Click a product → detail page with image gallery + Add to cart
  5. Add to cart (works as guest — cookie holds your cart)
  6. Click Sign in → log in with customer@example.com / CustomerDemo1!
  7. Your guest cart is automatically merged into your account
  8. Click Cart → adjust quantities, remove items, see live subtotal
  9. Proceed to checkout → shipping form → Stripe redirect (needs Stripe keys; see below)
  10. After payment → order appears at Orders within seconds (via webhook)
  11. Log out, log back in as admin@example.com / AdminChangeMe1!
  12. Header now shows an Admin link → product list, create/edit forms, image upload, category management

Tech stack

Layer Choice Why
Frontend React 18 + TypeScript + Vite Modern, fast HMR, mature ecosystem
Routing React Router v6 Standard for SPAs
Server state TanStack Query Best-in-class caching + retries
Forms React Hook Form + Zod Fewer re-renders + type-safe validation
Styling Tailwind CSS Tiny output, no naming bikeshed
Backend Node 20 + Fastify Faster than Express, schema-first
Logging Pino Fastest structured logger
Database PostgreSQL 16 + Prisma ORM Battle-tested + type-safe queries
Cache Redis 7 Rate limit + session store + idempotency
Storage S3-compatible (MinIO local / S3 prod) Direct browser uploads via presigned URLs
Email nodemailer (Mailhog local / SES prod) Standard SMTP everywhere
Payments Stripe Checkout + Webhooks PCI scope minimized to SAQ-A
Auth JWT + rotating refresh cookie + bcrypt Short access tokens, revokable refresh
Infra Terraform → AWS (ECS Fargate, RDS, ElastiCache, ALB, CloudFront, S3, WAF) Standard, reproducible
CI/CD GitHub Actions + AWS OIDC No long-lived AWS keys in GitHub
Observability Sentry + Prometheus + CloudWatch Errors + metrics + logs
Tests Vitest (unit/integration), Playwright (e2e), k6 (load) Right tool per layer
Container Docker (multi-stage, distroless runtime) Same artifact local + prod

A pnpm monorepo holds it all together, so the frontend and backend can share TypeScript types and Zod validators — there's a single source of truth for "what does a Product look like."


Architecture at a glance

Local dev

[browser :5173] ─► Vite dev server ─► proxies /api/* ─► [Fastify API :3001]
                                                        │
                                                        ├─► Postgres :5432   (Docker)
                                                        ├─► Redis :6379      (Docker)
                                                        ├─► MinIO :9000      (Docker, pretend S3)
                                                        └─► Mailhog :1025    (Docker, pretend SES)

Production (AWS)

[browser]
   │  HTTPS
   ▼
CloudFront + WAF
   ├─ /                → S3 (React SPA static files)
   ├─ /images/*        → S3 (product images)
   └─ /api/*           → ALB → ECS Fargate (Fastify API)
                              │
                              ├─► RDS Postgres 16 (Multi-AZ, encrypted)
                              ├─► ElastiCache Redis (primary + replica)
                              ├─► S3 (presigned image uploads)
                              ├─► SES (transactional email)
                              └─► Stripe (checkout sessions + webhooks)

Full Mermaid diagram + cost estimate in docs/aws-architecture.md.


Repo layout

shopping-app/
├── apps/
│   ├── api/                      # Fastify API server (Node)
│   │   ├── src/                  # routes, auth, cart, orders, observability
│   │   ├── prisma/               # schema + migrations + seed
│   │   ├── test/                 # vitest integration tests
│   │   ├── Dockerfile            # multi-stage, distroless runtime image
│   │   └── .env.example
│   │
│   └── web/                      # React SPA (Vite)
│       ├── src/
│       │   ├── pages/            # route components
│       │   ├── pages/admin/      # admin-only pages
│       │   ├── components/       # reusable UI bits
│       │   ├── auth/             # AuthContext + ProtectedRoute
│       │   └── lib/              # typed API clients
│       ├── Dockerfile            # builds bundle, serves with nginx
│       ├── nginx.conf
│       └── .env.example
│
├── packages/
│   └── shared/                   # Zod schemas + Money type + shared utils
│       └── src/schemas/          # auth, cart, order, product, admin
│
├── e2e/                          # Playwright browser tests
│   └── tests/smoke.spec.ts       # golden path: browse → cart → login → checkout
│
├── load-tests/
│   └── smoke.js                  # k6 smoke profile with SLO thresholds
│
├── infra/
│   └── terraform/
│       ├── bootstrap/            # one-time: state bucket + lock table + OIDC role
│       ├── modules/              # reusable: network, rds, redis, ecs-*, s3-cdn, waf, secrets
│       └── envs/{staging,prod}/  # per-environment wiring
│
├── docs/
│   ├── architecture.md           # system overview + request lifecycle
│   ├── aws-architecture.md       # production AWS topology + cost
│   ├── security.md               # threat model + OWASP checklist
│   ├── launch-checklist.md       # go-live checklist (60+ items)
│   ├── runbooks/                 # deploy, incident response
│   └── adr/                      # Architecture Decision Records
│
├── .github/
│   ├── workflows/
│   │   ├── ci.yml                # lint, typecheck, test, audit, build, Docker scan
│   │   └── deploy.yml            # PR plan + main→staging + tag→prod
│   └── dependabot.yml
│
├── docker-compose.yml            # local: postgres + redis + minio + mailhog
├── pnpm-workspace.yaml           # monorepo configuration
└── tsconfig.base.json            # shared strict TS settings

Quick start (local dev)

Prerequisites

Tool Min version macOS install
Node.js 20.11 brew install node@20 && brew link --overwrite node@20 (or use nvm)
pnpm 9 brew install pnpm
Docker Desktop recent brew install --cask docker-desktop, then launch the app once

Node 22/25 work for local dev. CI pins Node 20.

Setup

# 1. Get dependencies
pnpm install

# 2. Start backing services (Postgres, Redis, MinIO, Mailhog)
docker compose up -d
docker compose ps                       # all four should say "healthy"

# 3. Copy env files (gitignored copies of the *.example files)
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env

# 4. Create the database schema + seed sample data
pnpm db:migrate:dev                     # creates tables
pnpm db:seed                            # 6 categories + 30 products + 2 users

# 5. Run everything (api + web with hot reload)
pnpm dev

Open http://localhost:5173.

Demo accounts (created by seed)

Role Email Password
Admin admin@example.com AdminChangeMe1!
Customer customer@example.com CustomerDemo1!

Useful local URLs

What URL
Web app http://localhost:5173
API health probe http://localhost:3001/healthz
API readiness (pings DB + Redis) http://localhost:3001/readyz
Prometheus metrics (if METRICS_ENABLED=true) http://localhost:3001/metrics
Prisma Studio (browse DB visually) pnpm --filter @shopping-app/api db:studiohttp://localhost:5555
MinIO console (pretend S3) http://localhost:9001 · login minioadmin / minioadmin
Mailhog UI (catches outgoing email) http://localhost:8025

Tearing down

docker compose down        # stop services, keep data
docker compose down -v     # stop AND delete all data (fresh start next time)

Stripe setup (for real checkout)

The cart and order routes work without Stripe, but /checkout/session needs real test-mode keys. Free, takes ~5 minutes.

  1. Sign up at https://dashboard.stripe.com/register. After signup, ensure the toggle in the top-right says "Test mode" (yellow banner).
  2. Grab your Secret key from https://dashboard.stripe.com/test/apikeys (starts with sk_test_...) and put it in apps/api/.env:
    STRIPE_SECRET_KEY=sk_test_51...
    
  3. Install the Stripe CLI and have it forward webhooks to your local API:
    brew install stripe/stripe-cli/stripe
    stripe login
    stripe listen --forward-to localhost:3001/webhooks/stripe
    It prints a whsec_... — paste it into apps/api/.env:
    STRIPE_WEBHOOK_SECRET=whsec_...
    
    Leave stripe listen running while you test — it forwards real Stripe events to your local API so order creation actually happens.
  4. Restart pnpm dev so the API picks up the new env vars.
  5. In the browser: add a product to cart → Proceed to checkout → fill in the address → you'll redirect to Stripe's hosted page.
  6. Use card 4242 4242 4242 4242, any future expiry (12/34), any CVC.
  7. You'll land on /checkout/success and the order appears at /orders within 1–2 seconds.

How to use the app

As a customer

Goal Path
Browse products /products (search, filter, sort, paginate)
See a product /products/<slug>
Sign up /signup → check Mailhog at http://localhost:8025 for the verify link
Log in /login
Reset password /forgot-password → check Mailhog
View cart /cart
Checkout /checkout (requires login)
Order history /orders
Single order /orders/<id>
Account profile + logout /account

As an admin

Log in as admin@example.com → an Admin link appears in the header.

Goal Path
List all products (incl. inactive) /admin/products
Create a product /admin/products/new
Edit a product + manage its images /admin/products/<id>
Manage categories /admin/categories

A non-admin visiting /admin gets Access denied.


Available scripts

Run from the repo root.

Command What it does
pnpm dev Run api + web concurrently with hot reload
pnpm build Production build of every workspace
pnpm typecheck tsc --noEmit across all workspaces
pnpm lint ESLint with type-aware rules
pnpm format Prettier write
pnpm format:check Prettier check (no writes)
pnpm test Run all workspace tests (vitest)
pnpm db:migrate Apply migrations against the configured DB
pnpm db:seed Seed the demo catalog (idempotent)

Per-workspace shortcuts:

Command What it does
pnpm --filter @shopping-app/api db:studio Open Prisma Studio (browse DB)
pnpm --filter @shopping-app/api db:reset Drop, re-apply migrations, re-seed
pnpm --filter @shopping-app/e2e install:browsers Download Playwright browsers (one-off)
pnpm --filter @shopping-app/e2e test Run end-to-end browser tests

Testing

What How
Unit + integration (API) pnpm test
Typecheck pnpm typecheck
Lint + format pnpm lint && pnpm format:check
E2E in a real browser pnpm --filter @shopping-app/e2e test (see e2e/README.md)
Load smoke k6 run --env BASE_URL=http://localhost:3001 load-tests/smoke.js (see load-tests/README.md)
Dependency CVE audit pnpm audit --audit-level high
Container vuln scan runs on every PR in CI via Trivy

Deploying to AWS

End-to-end deploy needs an AWS account + a Route 53 hosted zone. Detailed topology, costs and trade-offs are in docs/aws-architecture.md.

One-time bootstrap (once per AWS account):

cd infra/terraform/bootstrap
terraform init
terraform apply -var "github_org=YOUR_ORG" -var "github_repo=shopping-app"

Copy the printed github_role_arn into .github/workflows/deploy.yml as AWS_ROLE_ARN.

Provision staging:

cd infra/terraform/envs/staging
cp terraform.tfvars.example terraform.tfvars   # fill in zone id + hostnames
terraform init
terraform apply

Seed the app secrets (Terraform creates them empty so plaintext is never in state):

aws secretsmanager put-secret-value --secret-id shop-staging/jwt-secret \
  --secret-string "$(openssl rand -base64 48)"
aws secretsmanager put-secret-value --secret-id shop-staging/stripe-secret-key \
  --secret-string "sk_test_..."
# …repeat for the others (see launch-checklist.md)

First deploy kicks off automatically when CI pushes to main. It builds the Docker image, pushes to ECR, syncs the SPA to S3, invalidates CloudFront, and updates the ECS service.

Promote to prod by tagging:

Scan report · 2026-09-14
  • Prohibited terms or links
  • Repository eligibility
  • slopscore.md paperwork
  • Content policy
  • Risk review — +10 owner has 0 followers

0 comments

log in to comment.

report this listinglog in to report