{"id":51043639,"url":"https://github.com/axeforging/tacomex-8bit-shop","last_synced_at":"2026-06-22T12:02:02.498Z","repository":{"id":337101836,"uuid":"1152354902","full_name":"AxeForging/tacomex-8bit-shop","owner":"AxeForging","description":"A full-stack retro-themed Mexican food delivery platform built with Fastify, React, PostgreSQL, and Redis.","archived":false,"fork":false,"pushed_at":"2026-04-02T16:18:38.000Z","size":22225,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-03T04:36:25.930Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AxeForging.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-07T18:48:46.000Z","updated_at":"2026-04-02T16:18:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/AxeForging/tacomex-8bit-shop","commit_stats":null,"previous_names":["axeforging/tacomex-8bit-shop"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AxeForging/tacomex-8bit-shop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AxeForging%2Ftacomex-8bit-shop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AxeForging%2Ftacomex-8bit-shop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AxeForging%2Ftacomex-8bit-shop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AxeForging%2Ftacomex-8bit-shop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AxeForging","download_url":"https://codeload.github.com/AxeForging/tacomex-8bit-shop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AxeForging%2Ftacomex-8bit-shop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34647750,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-22T12:01:57.708Z","updated_at":"2026-06-22T12:02:02.491Z","avatar_url":"https://github.com/AxeForging.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TacoMex 8-Bit Shop\n\nA full-stack retro-themed Mexican food delivery platform built with Fastify, React, PostgreSQL, and Redis.\n\n## Tech Stack\n\n| Layer      | Technology                              |\n|------------|-----------------------------------------|\n| Backend    | Fastify 4, Drizzle ORM, TypeScript      |\n| Frontend   | React 18, Vite 5, Zustand, React Query  |\n| Database   | PostgreSQL 15                            |\n| Cache      | Redis 7                                 |\n| Queue      | RabbitMQ 3.13 (notifications)           |\n| Infra      | Docker Compose                          |\n\n## Quick Start\n\n```bash\ngit clone https://github.com/AxeForging/tacomex-8bit-shop.git\ncd tacomex-8bit-shop\ndocker compose up --build\n```\n\n| Service     | URL                          |\n|-------------|------------------------------|\n| Frontend    | http://localhost:5173        |\n| API         | http://localhost:3001/api    |\n| Swagger     | http://localhost:3001/docs   |\n| Health      | http://localhost:3001/health |\n| RabbitMQ UI | http://localhost:15672       |\n\nThe seed service runs automatically on first start and populates the database with sample data.\n\n## Demo Credentials\n\n| Role     | Email                  | Password  |\n|----------|------------------------|-----------|\n| Admin    | admin@tacomex.com      | admin123  |\n| Customer | customer@tacomex.com   | pass123   |\n\n## Promo Codes\n\n`TACO20` `BURRITO10` `FIRSTORDER` `FREEDELIVERY` `8BITDEAL`\n\n## Connecting to Services\n\n### PostgreSQL\n\n```\nHost: localhost\nPort: 5432\nDatabase: tacomex_shop\nUser: tacomex\nPassword: tacomex_secret\n```\n\n```bash\npsql postgresql://tacomex:tacomex_secret@localhost:5432/tacomex_shop\n```\n\n### Redis\n\nNo password required.\n\n```bash\nredis-cli -h localhost -p 6379\n```\n\n### RabbitMQ\n\n```\nHost: localhost\nPort: 5672 (AMQP) / 15672 (Management UI)\nUser: tacomex\nPassword: tacomex_secret\n```\n\nOpen http://localhost:15672 to access the management dashboard.\n\n## API Endpoints\n\n### Auth (`/api/auth`)\n\n| Method | Endpoint    | Auth | Description                          |\n|--------|-------------|------|--------------------------------------|\n| POST   | `/register` | -    | Register new user                    |\n| POST   | `/login`    | -    | Login, returns JWT                   |\n| GET    | `/me`       | JWT  | Get current profile                  |\n| POST   | `/logout`   | JWT  | Invalidate token (Redis blacklist)   |\n\n### Products (`/api/products`)\n\n| Method | Endpoint           | Auth  | Description                     |\n|--------|--------------------|-------|---------------------------------|\n| GET    | `/`                | -     | List with filters \u0026 pagination  |\n| GET    | `/featured`        | -     | Featured products (max 10)      |\n| GET    | `/:id`             | -     | Get by ID or slug               |\n| POST   | `/`                | Admin | Create product                  |\n| PATCH  | `/:id`             | Admin | Update product                  |\n| DELETE | `/:id`             | Admin | Delete product                  |\n| GET    | `/categories/list` | -     | Categories with product counts  |\n\n**Query params:** `category`, `featured`, `available`, `minPrice`, `maxPrice`, `spiceLevel`, `search`, `sortBy`, `sortOrder`, `page`, `limit`\n\n### Categories (`/api/categories`)\n\n| Method | Endpoint | Auth | Description                 |\n|--------|----------|------|-----------------------------|\n| GET    | `/`      | -    | List all with product count |\n| GET    | `/:id`   | -    | Get by ID/slug with products|\n\n### Orders (`/api/orders`)\n\n| Method | Endpoint      | Auth  | Description                           |\n|--------|---------------|-------|---------------------------------------|\n| GET    | `/`           | JWT   | List orders (own or all for admin)    |\n| GET    | `/:id`        | JWT   | Order detail with items \u0026 history     |\n| POST   | `/`           | JWT   | Place order with items \u0026 promo code   |\n| PATCH  | `/:id/status` | Admin | Update status                         |\n\n**Order status flow:** `pending` -\u003e `confirmed` -\u003e `preparing` -\u003e `ready` -\u003e `delivered` (or `cancelled`)\n\n### Promotions (`/api/promotions`)\n\n| Method | Endpoint    | Auth  | Description              |\n|--------|-------------|-------|--------------------------|\n| GET    | `/`         | Admin | List all promotions      |\n| GET    | `/active`   | -     | Active promotions        |\n| POST   | `/validate` | -     | Validate promo code      |\n| POST   | `/`         | Admin | Create promotion         |\n| PATCH  | `/:id`      | Admin | Update promotion         |\n\n### Notifications (`/api/notifications`) — RabbitMQ queue → PostgreSQL\n\n| Method | Endpoint       | Auth | Description                       |\n|--------|----------------|------|-----------------------------------|\n| GET    | `/`            | JWT  | List notifications (email/sms)    |\n| PATCH  | `/:id/read`    | JWT  | Mark notification as read         |\n| POST   | `/read-all`    | JWT  | Mark all notifications as read    |\n\n**Triggers:**\n- **Email**: Order placed, order status change (confirmed, preparing, ready, delivered, cancelled)\n- **SMS**: User registration (welcome), order ready for pickup/delivery, order delivered\n\n### Cart (`/api/cart`) — Redis-backed, per user, 24 h TTL\n\n| Method | Endpoint            | Auth | Description                       |\n|--------|---------------------|------|-----------------------------------|\n| GET    | `/`                 | JWT  | Get cart                          |\n| POST   | `/items`            | JWT  | Add / update item                 |\n| PATCH  | `/items/:productId` | JWT  | Update quantity (0 removes item)  |\n| DELETE | `/items/:productId` | JWT  | Remove item                       |\n| DELETE | `/`                 | JWT  | Clear entire cart                 |\n\n### Users (`/api/users`)\n\n| Method | Endpoint | Auth  | Description              |\n|--------|----------|-------|--------------------------|\n| GET    | `/`      | Admin | List users with stats    |\n| GET    | `/:id`   | JWT   | Profile (admin or self)  |\n| PATCH  | `/:id`   | JWT   | Update (admin or self)   |\n\n### Health\n\n| Method | Endpoint  | Description                        |\n|--------|-----------|------------------------------------|\n| GET    | `/`       | API info and endpoint listing      |\n| GET    | `/health` | DB \u0026 Redis connectivity status     |\n\n## Project Structure\n\n```\ntacomex-8bit-shop/\n├── backend/\n│   ├── src/\n│   │   ├── config/        # Redis \u0026 RabbitMQ configuration\n│   │   ├── db/            # Drizzle schema \u0026 connection\n│   │   ├── middleware/    # Auth (JWT) \u0026 error handling\n│   │   ├── plugins/       # Swagger/OpenAPI docs\n│   │   ├── routes/        # API route handlers\n│   │   ├── services/      # Notification publisher \u0026 consumer\n│   │   ├── seeds/         # Database seeding\n│   │   └── index.ts       # Server entry point\n│   └── Dockerfile\n├── frontend/\n│   ├── src/\n│   │   ├── components/    # Reusable UI (pixel art theme)\n│   │   ├── pages/         # Route pages\n│   │   ├── hooks/         # React Query hooks\n│   │   ├── services/      # Axios API client\n│   │   ├── stores/        # Zustand (auth, cart)\n│   │   └── App.tsx        # Router setup\n│   └── Dockerfile\n├── scripts/\n│   └── init-db.sql        # PostgreSQL schema init\n├── .github/\n│   ├── actions/\n│   │   └── start-app/     # Composite action: spin up \u0026 wait\n│   └── workflows/\n│       └── ci.yml         # CI pipeline with Playwright\n├── docker-compose.yaml\n└── README.md\n```\n\n## Rate Limiting\n\nRate limits are Redis-backed and configurable via environment variables — the defaults are **very permissive in dev** so you can test freely.\n\n| Variable | Dev default | Prod default | Window |\n|---|---|---|---|\n| `RATE_LIMIT_GLOBAL` | 10 000 | 100 | 15 min |\n| `RATE_LIMIT_AUTH` | 1 000 | 5 | 15 min |\n| `RATE_LIMIT_ORDERS` | 1 000 | 10 | 1 hour |\n\nTo simulate throttling locally, set low values in your `.env` or inline:\n\n```bash\n# Simulate tight auth throttling (3 login attempts / 15 min)\nRATE_LIMIT_AUTH=3 docker compose up backend\n\n# Or add to your .env:\n# RATE_LIMIT_GLOBAL=10\n# RATE_LIMIT_AUTH=3\n# RATE_LIMIT_ORDERS=2\n```\n\n## Development\n\n```bash\n# Start all services\ndocker compose up --build\n\n# Rebuild a single service\ndocker compose up --build backend\n\n# View logs\ndocker compose logs -f backend\n\n# Run database seeds manually\ndocker compose exec backend npm run seed\n\n# Open Drizzle Studio\ndocker compose exec backend npm run db:studio\n\n# Stop everything\ndocker compose down\n\n# Stop and remove volumes\ndocker compose down -v\n\n# Reset database and reseed (drops volumes, rebuilds, and reseeds automatically)\ndocker compose down -v \u0026\u0026 docker compose up --build\n```\n\n## GitHub Actions\n\nThis repo includes a **composite action** at `.github/actions/start-app/` that starts the full stack and waits for it to be healthy — as a step inside your job, so subsequent steps (like Playwright) share the same running containers.\n\nThe action works from **any repo** — it automatically clones the TacoMex source, builds, and starts everything. Your workspace stays untouched for your own code and tests.\n\n### From another repo (e.g. a separate Playwright test suite)\n\n```yaml\n# .github/workflows/e2e.yml in your test repo\nname: E2E Tests\n\non: [push, pull_request]\n\njobs:\n  e2e:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4  # checks out YOUR test repo\n\n      - name: Start TacoMex app\n        uses: AxeForging/tacomex-8bit-shop/.github/actions/start-app@main\n\n      # At this point:\n      #   - TacoMex API is running on localhost:3001\n      #   - Frontend is running on localhost:5173\n      #   - Your workspace still has YOUR repo's files\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - run: npm ci\n      - run: npx playwright install --with-deps\n      - run: npx playwright test\n```\n\nThe action clones the TacoMex source into a `.tacomex-app/` subdirectory, builds and starts everything via Docker Compose, then waits for the health check to pass. Your workspace stays clean with your own code.\n\n### Inside the TacoMex repo\n\n```yaml\njobs:\n  e2e:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Start app\n        uses: AxeForging/tacomex-8bit-shop/.github/actions/start-app@main\n        with:\n          checkout: \"false\"\n          install-frontend-deps: \"true\"\n\n      - run: npx playwright install --with-deps \u0026\u0026 npx playwright test\n        working-directory: frontend\n```\n\n**Inputs:**\n\n| Input | Default | Description |\n|-------|---------|-------------|\n| `health-timeout` | `180` | Max seconds to wait for the health check |\n| `health-url` | `http://localhost:3001/health` | Health endpoint URL to poll |\n| `docker-compose-file` | `docker-compose.yaml` | Path to docker-compose file |\n| `checkout` | `true` | Clone the TacoMex repo automatically (set to `false` when running inside the TacoMex repo) |\n| `app-ref` | `main` | Git ref (branch/tag/sha) of the TacoMex repo to checkout |\n| `install-frontend-deps` | `false` | Install frontend deps on the host and restart the container (needed for Playwright) |\n| `frontend-dir` | `frontend` | Relative path to frontend directory |\n| `rate-limit-global` | _(permissive)_ | Set a low number (e.g. `10`) to simulate global throttling in tests |\n| `rate-limit-auth` | _(permissive)_ | Set a low number (e.g. `3`) to simulate auth lockout in tests |\n| `rate-limit-orders` | _(permissive)_ | Set a low number (e.g. `2`) to simulate order throttling in tests |\n\n**Example — testing throttle behaviour:**\n\n```yaml\n- name: Start TacoMex app (tight rate limits)\n  uses: AxeForging/tacomex-8bit-shop/.github/actions/start-app@main\n  with:\n    rate-limit-auth: \"3\"    # lock out after 3 login attempts\n    rate-limit-orders: \"2\"  # throttle after 2 orders/hour\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxeforging%2Ftacomex-8bit-shop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxeforging%2Ftacomex-8bit-shop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxeforging%2Ftacomex-8bit-shop/lists"}