README.md

Amerik Vitamin — vit-store

Mongolia-based ecommerce store (amerikvitamin.mn) selling US-imported vitamins and supplements (NatureBell, MicroIngredients, Nutricost, and more). Shopping is in Mongolian; prices in MNT (₮). 99% of traffic is mobile.

The monorepo contains four apps — a storefront, an admin dashboard, an API server, and a Facebook Messenger AI shopping agent — plus shared packages, all deployed to Cloudflare via Alchemy (TypeScript IaC).

What's in here

Apps (apps/)

AppStackWhat it does
storev2Astro 5 + SolidJS islands, Tailwind v4, tRPCCustomer-facing storefront. Catalog with brand/category filtering, search, product detail pages, SolidJS cart, checkout (phone → address → delivery zone → confirmation), order tracking, QPay payment, OTP phone login. Neo-brutalist, mobile-first design (see DESIGN.md).
adminReact 19 + Vite + TanStack Router/Query, tRPC, shadcn/uiInternal dashboard. Product CRUD with AI-assisted extraction from Amazon URLs, order management, customer records (phone-based), brand/category management, purchase/inventory tracking (Amazon/iHerb imports), payment confirmation (QPay + bank transfer), analytics (sales, top products, PostHog web analytics).
serverHono + tRPC + Drizzle, Cloudflare WorkersCentral API gateway. Three tRPC routers: /trpc/admin (dashboard), /trpc/store (storefront), /trpc/bot (Messenger admin agent). REST routes for Google OAuth, QPay webhook, Messenger webhook, image uploads. PostgreSQL via Hyperdrive, R2 for images, Upstash Redis Search for product discovery, KV for sessions, rate limiting, and structured logging.
messengerAgents SDK Durable Objects + Chat SDK (Zernio) + AI SDKCustomer Messenger bot through Zernio: product search, cart, checkout, QPay/transfer payments, handoff with Telegram alerts. The Telegram admin bot lives here too: POST /telegram/webhook feeds a per-chat Admin Durable Object with the Codemode query tool, image extractors, seven skills, and inline-button callbacks. Inbound admin photos stage in R2 under messenger-inbound/ (auto-expired), and only the key enters history.

Packages (packages/)

PackagePurpose
@vit/apitRPC routers (admin/store/bot), Drizzle DB queries, integrations (Messenger, QPay, PostHog, Resend, SMS gateway), AI product-extraction pipeline, payment logic.
@vit/sharedDomain types, Valibot schemas, constants (delivery fee 6,000₮, bank transfer details, status enums).

Tech stack

  • Runtime/dep manager: Bun, Turborepo
  • Storefront: Astro 5 (SSR via @astrojs/cloudflare), SolidJS islands, Tailwind v4
  • Admin: React 19, Vite, TanStack Router/Query, shadcn/ui
  • Server: Hono, tRPC v11, Drizzle ORM
  • Bots: apps/messenger — Agents SDK + Chat SDK + AI SDK (customer Messenger via Zernio, admin Telegram bot)
  • Database: PostgreSQL 16 (Drizzle ORM, Hyperdrive connection pooling in prod)
  • Storage: Cloudflare R2 (product + inbound images), KV (sessions/cache)
  • State: Upstash Redis Search (product discovery); Durable Objects (agent sessions, inbox/outbox, cart/checkout, payments)
  • IaC/deploy: Alchemy → Cloudflare Workers (server) and Pages (storev2, admin)
  • Lint/format: Vite+ (vp check: oxfmt + oxlint); type checks via tsc

Getting started

Install dependencies:

bash
1bun install

Database

PostgreSQL via Docker (port 5433):

bash
1bun db:docker:up # docker-compose up -d
2bun db:push # push Drizzle schema

Local dev with Caddy

A Caddyfile provides local TLS domains so OAuth/cookies behave like prod:

Local domainProxiesApp
https://vitstore.devlocalhost:4321storev2
https://api.vitstore.devlocalhost:3006server
https://admin.vitstore.devlocalhost:3005admin

Run everything in dev (Turborepo):

bash
1bun dev

Or run a single app:

bash
1bunx turbo dev --filter=storev2
2bun dev:server
3bunx turbo dev --filter=admin

The messenger worker runs via Wrangler locally:

bash
1cd apps/messenger && bun dev # wrangler dev

Deploy

Each app deploys via Alchemy to Cloudflare (prod stage reads ../../.env.prod):

bash
1bun deploy # turbo deploy (server first, then frontends)

Available scripts

ScriptDescription
bun devStart all apps in dev mode
bun buildBuild all apps
bun check-typesTypeScript checks across all apps
bun deployDeploy all apps
bun db:pushPush Drizzle schema to the database
bun db:migrate / bun db:migrate:localRun migrations (prod/local)
bun db:studio / bun db:studio:localOpen Drizzle Studio
bun db:seedSeed the database
bun db:docker:up / bun db:docker:downStart/stop the Postgres container
bun lint / bun lint:fixoxlint / autofix
bun fmt / bun fmt:fixoxfmt check / write
bun checkfmt + lint (what CI runs)
bun checkoxlint
bun knipDead-code/dependency analysis
bun qualitycheck-types + fallow dead-code + fallow health

Maintenance scripts, product JSON dumps, and QA reports live in the sibling vit-playground checkout (see its README).

Cache maintenance

Cache maintenance moved to vit-playground/scripts/clear-kv-cache.ts. Every invocation must select local, staging, or production, the analytics scope, and a namespace. An invocation without --confirm is a non-mutating preview; staging and production previews do not contact Cloudflare.

Use a unique namespace name and persistence directory for disposable local work:

bash
1cd ../vit-playground
2bun scripts/clear-kv-cache.ts -- --environment local --scope analytics --namespace-id <unique-local-name> --persist-to <absolute-path>
3bun scripts/clear-kv-cache.ts -- --environment local --scope analytics --namespace-id <unique-local-name> --persist-to <absolute-path> --confirm local:<unique-local-name>

Remote operations additionally require both the account and namespace IDs. Replace placeholders from the intended Alchemy stage output; do not copy identifiers between environments:

bash
1bun scripts/clear-kv-cache.ts -- --environment staging --scope analytics --account-id <staging-account-id> --namespace-id <staging-namespace-id>
2bun scripts/clear-kv-cache.ts -- --environment staging --scope analytics --account-id <staging-account-id> --namespace-id <staging-namespace-id> --confirm staging:<staging-account-id>:<staging-namespace-id>
3
4bun scripts/clear-kv-cache.ts -- --environment production --scope analytics --account-id <production-account-id> --namespace-id <production-namespace-id>
5bun scripts/clear-kv-cache.ts -- --environment production --scope analytics --account-id <production-account-id> --namespace-id <production-namespace-id> --confirm production:<production-account-id>:<production-namespace-id> --confirm-production DELETE-PRODUCTION-CACHE

The package script disables Bun env-file loading. Wrangler runs from an isolated directory with only its user-level authentication configuration and the explicitly supplied account ID; it does not load the repository .env files.

Playground checkout

One-off scripts, JSON dumps, dogfood/QA reports, and scratch notes live in ../vit-playground as a sibling directory. The app repo keeps source, ADRs, docs/problems/, and plans/.

Project structure

1vit-store/
2├── apps/
3│ ├── storev2/ # Storefront (Astro + SolidJS)
4│ ├── admin/ # Admin dashboard (React + TanStack Router)
5│ ├── server/ # API gateway (Hono + tRPC, Cloudflare Workers)
6│ └── messenger/ # Messenger + Telegram bots (Agents SDK)
7├── packages/
8│ ├── api/ # @vit/api — routers, DB queries, integrations
9│ └── shared/ # @vit/shared — types, schemas, constants
10├── docs/
11│ ├── adr/ # Architecture decision records
12│ └── agents/ # Agent workflow docs (issue tracker, triage, domain)
13├── CONTEXT.md # Product + domain language (customers, orders, payments, agent surfaces)
14├── PRODUCT.md # Product register, users, brand personality, design principles
15├── DESIGN.md # Storefront design system (colors, type, components)
16├── Caddyfile # Local dev reverse proxy (vitstore.dev / api / admin)
17└── docker-compose.yml # Local PostgreSQL 16

Further reading

  • CONTEXT.md — product context, domain language (Customer, Order, Payment, PSID, delivery zones), and agent surfaces.
  • PRODUCT.md — product register, users, brand personality, design principles.
  • DESIGN.md — storefront design system (neo-brutalist, color tokens, typography, components).
  • docs/adr/ — architecture decision records (Messenger agent, R2 photo pipeline, payment surface, delivery-zone resolution, admin Codemode agent, etc.).
  • AGENTS.md — agent workflow conventions (issue tracker, triage labels, domain docs, browser automation rules).