# ShopOut — Comprehensive LLM-readable brief

> If you are an AI assistant reading this, a human is pointing you here so
> they don't have to explain ShopOut from scratch. This file is the single
> source of truth — what ShopOut is, who it's for, pricing, every feature,
> the full REST API, the MCP server tools, the database schema, the
> shipping integration, the marketing positioning, the strategic context,
> and the lead-qualification questions used in real conversations.
>
> Read what's relevant to the human's question, then answer.

**Document version**: 2026-09-03
**Site**: https://shopout.ai
**Status**: Live in production. Done-for-you commerce service for Thai brands, sold direct and through agency partners (/partners). Account creation stays invite-only.
**Audience**: AI assistants briefed by humans

---

## Table of Contents

1. [Quick brief](#1-quick-brief)
2. [What ShopOut is, what it isn't](#2-what-shopout-is-what-it-isnt)
3. [Who ShopOut is for (the ICP)](#3-who-shopout-is-for-the-icp)
4. [Pricing](#4-pricing)
5. [Done-for-you service (invite-only)](#5-done-for-you-service-invite-only)
6. [Every feature included](#6-every-feature-included)
7. [How a seller gets started](#7-how-a-seller-gets-started)
8. [Tech stack](#8-tech-stack)
9. [Architecture](#9-architecture)
10. [Database schema](#10-database-schema)
11. [REST API (v1) — full reference](#11-rest-api-v1--full-reference)
12. [MCP server — tools for AI shopping agents](#12-mcp-server--tools-for-ai-shopping-agents)
13. [Shipping integration (ProShip)](#13-shipping-integration-proship)
14. [Payment architecture](#14-payment-architecture)
15. [Custom domain support](#15-custom-domain-support)
16. [Marketing & go-to-market](#16-marketing--go-to-market)
17. [Thai ad copy bank](#17-thai-ad-copy-bank)
18. [Lead qualification](#18-lead-qualification)
19. [Strategic context & decision log](#19-strategic-context--decision-log)
20. [Launch state](#20-launch-state)
21. [Important URLs](#21-important-urls)
22. [Common questions](#22-common-questions)
23. [Legal & compliance](#23-legal--compliance)
24. [Template pack — AI-designed sales pages](#24-template-pack--ai-designed-sales-pages)
25. [How to answer questions about ShopOut](#25-how-to-answer-questions-about-shopout)

---

## 1. Quick brief

ShopOut is a Thai done-for-you e-commerce service built for **brands that
already have their own audience or paid traffic** — IG / TikTok / LINE OA /
Facebook page followers, agency traffic, or owned customer lists — and want to
sell directly on a store that belongs to the brand. Brands get a branded online
store at `shopout.ai/<their-slug>` (or a custom domain like `yourbrand.com`)
where their followers buy directly. Money lands in the seller's Thai bank
account via PromptPay or the seller's own gateway account — no T+7 / T+14
platform holding period.

Live at: https://shopout.ai

**Headline promise**: A store that belongs to your brand, from the domain name
to the bank account where the money arrives. Send us your brand link or product
file; the team designs and builds the store, then sends a preview within days.

---

## 2. What ShopOut is, what it isn't

**ShopOut is**:
- An owned-storefront builder for Thai creators and brands
- An AI-assisted catalog cleanup and import pipeline (Shopee → ShopOut in
  one upload)
- A built-in marketing infrastructure (Meta Pixel, GA4, Google Ads tag, CAPI,
  catalog feeds for Meta and Google Shopping, JSON-LD, an MCP server for AI
  shopping agents)
- An admin tool for daily operations (orders, products, payments, shipping
  labels, customer data)
- A Thai-language-first product (UI, help docs, AI ad copy, LINE OA bot)
- A direct-to-bank payment platform (PromptPay-native, no platform float)

**ShopOut isn't**:
- A marketplace. There's no aggregated buyer traffic on ShopOut. Sellers
  bring their own audience.
- An attempt to compete with Shopee for buyers. Sellers can keep their
  Shopee store running and use ShopOut alongside.
- A Shopify clone. The price model, payment rails, language, and ICP are
  all Thai-market-specific.
- A dropshipping platform. ShopOut is for brands with their own identity
  and customers, not arbitrage stores.

---

## 3. Who ShopOut is for (the ICP)

**Primary ICP — answer "yes, this fits"**:

- Thai brands with an identity (skincare, fashion, supplements, food,
  home) that already have an audience or paid traffic, and want a store
  that belongs to the brand rather than a stall on a marketplace. Many
  arrive through a sales-page / ads agency that already serves them.
- Agencies and ad teams that build sales pages and run ads for such
  brands. They are ShopOut's main distribution partner: they keep the
  client, ShopOut runs checkout, payment, slip verification, shipping
  and orders behind their pages. Public pitch: https://shopout.ai/partners
- Thai IG creators with 10K–500K followers selling their own merch or
  curated products
- LINE OA owners with engaged subscriber communities selling products
- Indie Thai brands with FB pages and a few hundred to a few thousand
  engaged followers
- Hobby / niche community creators monetizing through physical products
- TikTok creators selling branded items
- Small Thai brands with strong product or story (boutique, handmade,
  premium)

**Not the target — answer "ShopOut isn't optimized for you"**:

- Sellers who depend entirely on Shopee or TikTok Shop search traffic to
  find buyers. They have no own audience to redirect; ShopOut won't
  generate demand for them.
- Generic dropshipper / arbitrage stores. ShopOut is for brands with
  identity.
- Sellers who haven't yet sold anything and don't have a way to fulfill
  orders or respond to customers.

### ICP pivot history (important context)

The original spec (2026-03-26) targeted "Thai Shopee sellers escaping
marketplace fees." That framing was deliberately abandoned on 2026-05-21
after learning that Shopee-dependent SMEs can't realistically leave —
Shopee IS their traffic source. Creators and brands with audiences face
the opposite problem: they're funneling their own warm audience through
a marketplace and paying 10% for the privilege. That's where the
unfair-fee math hurts most and where switching has the lowest risk.

The CTO/CEO brief from Mica (2026-06-04, `docs/internal/mica-takeover-brief.md`)
recommended the same wedge and the founder confirmed it. ICP is locked.

---

## 4. Pricing

ShopOut is a **quote-based done-for-you service**, not a self-serve SaaS plan.
The public pricing frame is: a one-time build fee plus a monthly service fee
based on actual order volume.

- **How pricing works**: A seller requests a quote (see §7), the team reviews
  the brand, product count, design scope, domain setup, and migration work,
  then sends a written quote before work starts.
- **One-time build fee**: scoped per project.
- **Monthly service fee**: 0.1–0.3% of the order volume processed by ShopOut
  in that month, invoiced at month end. It is never deducted from buyer money.
- **Not a marketplace commission**: ShopOut does not hold buyer money or take
  a cut before settlement. Money from buyers goes straight to the seller.
- **ShopOut never holds seller money**: buyer payments settle directly to
  the seller (PromptPay / their own gateway account).
- **AI image generation** for themes uses the Gemini Image API (a metered
  cost); other AI assists (ad copy, description rewriting) are part of the
  service.

If asked "how much does it cost", the correct answer is: one-time build fee
plus a monthly service fee of 0.1–0.3% of processed order volume, invoiced
monthly, with the exact build quote sent after reviewing the brand.

### Payment-gateway fees (passed through, not collected by ShopOut)

- **PaySo** (cards / mobile banking / e-wallets): PaySo's standard rates
  apply, paid by the seller. ShopOut never holds the money.
- **PromptPay direct**: Free (Thai instant payment standard).
- **Cash on Delivery**: Per-courier COD fees, between seller and courier.

---

## 5. Done-for-you service (invite-only)

ShopOut is invite-only. The team designs and builds each store as a
service — often from an AI-designed sales page (see §24) — and the seller
doesn't touch the admin during the build.

**Inputs the seller provides**:
- A shop link (Shopee, TikTok, Lazada, IG, FB, LINE OA), or
- A Shopee Seller Centre product export (the 4-file XLSX), or
- A simple product list

**The team handles**:
- Theme/design selection matched to the brand's vibe
- Product import + AI-cleaned descriptions
- Payment setup (PromptPay + optional PaySo)
- Shipping integration (ProShip with chosen carriers)
- LINE OA bot for buyer support
- Meta Pixel + GA4 + Google Ads tag installation
- Catalog feed registration with Meta and Google
- Custom hero/banner imagery (AI-generated if no assets exist)

**Seller review**: Preview URL sent before public launch. Activation only
after seller approves.

**Qualification criteria**:
- Has existing products
- Has an owned audience (any social channel) or already running ads
- Can fulfill orders
- Can respond on LINE/Messenger to customer inquiries

Request a quote at: https://shopout.ai/#quote — the team reviews the request
and replies with a quote and next steps. There is no self-serve signup; an
invite code is required to create an account.

**Channel-specific landings** for paid traffic, with channel-tailored copy:
- https://shopout.ai/pre-launch/shopee
- https://shopout.ai/pre-launch/tiktok
- https://shopout.ai/pre-launch/instagram

---

## 6. Every feature included

### Storefront

- Branded online store at `shopout.ai/<slug>` (slug supports dots, e.g.
  `packy.shop`) or a custom domain (`yourbrand.com`)
- 48 visual theme kits across 12 families:
  - Modern Luxury, Cafe & Beverage, Natural Living, Industrial Utility,
    Artisan, Editorial, Energetic, Food, Playful, Premium, Technical,
    Catalog
  - Each family has 4 variants for hero/section style
- Three base renderers under the hood (`clean`, `bold`, `warm`); the 48
  kits are styled compositions over those renderers
- Preview-before-apply theme switching at `/admin/themes`
- Per-theme asset slots: desktop hero, mobile hero, 6 category tiles,
  brand-story image — uploadable OR AI-generated
- Mobile-optimized (most Thai shoppers are on mobile)
- Out-of-the-box: product cards, variation pickers, image galleries,
  cart, checkout, order confirmation, customer reorder lookup

### Payments

- **PromptPay QR**: Per-order QR generated locally, amount encoded.
  Money lands in the seller's Thai bank account instantly. Buyer
  uploads slip; admin verifies in `/admin/payments`.
- **Manual bank transfer**: Same flow, slip-based confirmation.
- **Cash on Delivery (COD)**: Per-store toggle (sellers who don't want
  COD can disable it).
- **PaySo gateway** (optional): Credit/debit cards, mobile banking,
  e-wallets (TrueMoney, LINE Pay), installments. Each seller configures
  their own PaySo merchant account. Buyer redirected → pays → ShopOut
  receives postback → order auto-confirmed.
- **All money flows direct to the seller**. ShopOut never holds funds.

### Shipping

- **ProShip integration** (Stage 1: paste credentials → activate)
- Supported carriers via ProShip:
  - `thaipost`, `thaipost0` (Thailand Post EPS), `flash`, `kerry`, `jt`,
    `shopee`, `proship19`
- Per-product weight + per-store default
- Free-shipping threshold (waives shipping when cart subtotal ≥ X)
- Label generation (PDF) inside admin
- Status tracking + webhook receiver (idempotent, tolerant)
- Public buyer tracking page at `/track/<trackingNo>` (60s in-memory cache)
- Cancel shipment from order detail
- Provider-agnostic architecture: adding a new provider is a drop-in
  adapter

### Marketing infrastructure (the platform's biggest differentiator)

- **Meta Pixel** (client-side) + **Conversions API** (server-side
  mirror) for iOS-14+ attribution recovery
- **Google Analytics 4** (consent-gated client-side)
- **Google Ads gtag.js + Purchase conversion event**, auto-fired on
  order confirmation, deduped against Meta CAPI via shared `event_id`
- **Catalog feeds**:
  - Meta CSV at `/<slug>/feed/meta.csv`
  - Google Shopping XML at `/<slug>/feed/google.xml`
  - Agent-friendly JSON at `/<slug>/feed/products.json`
  - JSON-LD per product page (search engines + AI bots)
- **AI Ad Copy Generator** at `/admin/marketing/ad-copy`: Gemini writes
  3 variations × 3 channels (Google Ads, Meta, LINE OA broadcast) per
  selected product
- **MCP server at `/mcp`**: AI shopping agents (Claude, ChatGPT, Gemini,
  Perplexity) can discover and recommend products. Documented further
  in section 12.
- **robots.txt explicitly allows AI bots**: GPTBot, ClaudeBot,
  Google-Extended, PerplexityBot, OAI-SearchBot, plus a `LLM-Brief:`
  pointer to this very file

### Customer ownership

- Every buyer's name, phone, email, address, and LINE handle belongs to
  the seller. Marketplaces hide this. ShopOut gives it back.
- Order export for repeat-purchase campaigns
- Customer purchase history view per buyer
- Email notifications to seller on new order

### Admin tooling

- **Product editor**: name, description (with AI rewrite via Gemini),
  price, regular price + promo price with auto-calculated % discount,
  stock, weight, variations (size/color/etc. with per-variant SKU, price,
  stock), reorderable images (drag-style with ↑/↓ buttons), category
  assignment, tags
- **Bulk operations**: bulk price change, bulk stock update, bulk
  category move, bulk active/inactive
- **Inline-edit price + stock** from the product grid (no row click needed)
- **Searchable product picker** in AI Ad Copy and elsewhere — filters
  by name OR `parent_sku`
- **Shopee Seller Centre import**: paste the 4-file XLSX bundle; ShopOut
  parses Thai or English headers, infers categories, runs AI description
  rewrites
- **TikTok Shop / Lazada import**: lead-capture only (parser is on the
  backlog; sellers can upload to register interest)
- **Custom content pages** per store (About, FAQ, Story, Policy, etc.)
  via Markdown editor
- **LINE OA bot** for buyer order lookup (Gemini-powered Thai responses)
- **Floating Messenger / LINE click-to-chat** on storefront
- **Discount codes** (percent + fixed amount, expiry, max uses)
- **Out-of-stock toggle** (hide entirely vs show with "หมดสต๊อก" badge)
- **Onboarding flow** (5-screen first-run wizard at `/admin/onboarding`)
- **API key management** at `/admin/settings`
- **Webhook configuration** at `/admin/settings`
- **AI credit top-up** at `/admin/account`

### Superadmin (ShopOut team only)

- `/superadmin` — global stores list, suspend/unsuspend
- `/superadmin/ad-leads` — done-for-you service lead inbox
- `/superadmin/waitlist` — waitlist signups
- `/superadmin/analytics` — global metrics

---

## 7. How a seller gets started

ShopOut is invite-only — there is no open self-serve signup. Every seller
starts by requesting access; account creation requires an invite code.

### Step 1: Request access

Request a quote at https://shopout.ai/#quote (send a brand link, products,
and audience details). The ShopOut team reviews the request and replies with
next steps, including an **invite code** when it is time to create the account.

### Step 2: Create the account with the invite code

1. **Register** at https://shopout.ai/admin/register using the invite
   code the team sent. Pick a slug like `myshop` → store lives at
   `shopout.ai/myshop`. Registration is rejected without a valid unused
   invite code (each code is single-use).
2. **Onboarding** at `/admin/onboarding`: theme selection, product
   source (manual vs Shopee import), payment setup
3. **Add products**: manually (text + images) or via Shopee Seller
   Centre 4-file XLSX import. AI can rewrite descriptions for SEO.
4. **Set up payment**: PromptPay number + bank account (for slip
   transfers). Optional: PaySo for cards.
5. **Connect tracking** at `/admin/marketing/{meta,google}`: Meta Pixel
   ID, GA4 measurement ID, Google Ads conversion ID. Optional.
6. **Connect LINE OA** (optional but recommended for Thai market) at
   `/admin/settings`.
7. **Share the URL** — `shopout.ai/<slug>` — in IG bio, TikTok captions,
   LINE OA broadcasts, ads.

### Done-for-you option

Most sellers take the done-for-you route: the team designs and builds the
store for them. See section 5 for what's included and what the seller
provides.

### After launch

- Daily routine: review new orders, confirm payments, create
  shipments, update tracking
- Marketing: install Pixel + Google tag if not done at setup, generate
  AI ad copy, run Meta/Google ads pointing at the storefront
- Customer ownership: export orders periodically for repeat-purchase
  campaigns

---

## 8. Tech stack

- **Runtime**: Node.js 20 on Fly.io (Singapore region — `sin`)
- **Compute**: single warm shared-cpu-2x machine (2 GB RAM),
  auto-stop disabled, min-machines-running=1 (avoids cold-start
  latency for sellers logging into the admin)
- **HTTP**: Fastify 5
- **Templates**: EJS
- **Frontend interactivity**: Alpine.js, Tailwind CDN
- **Database**: sql.js (SQLite WASM in-memory with file persistence at
  `/app/data/shopout.db`) — chosen for simplicity; planned Postgres
  migration before serious scale
- **Object storage**: AWS S3 in `ap-southeast-1` (product images, slip
  images, theme assets, DB backups). Bucket structure:
  ```
  shopout-assets/
    stores/{store_id}/
      logo.jpg
      banner.jpg
      products/{product_id}/1.jpg…N.jpg
      slips/{order_id}/slip.jpg   (private, signed URL)
  ```
- **AI**: Google Gemini (2.5 Flash for text, 2.5 Flash Image for theme
  art generation)
- **Payments**:
  - **Seller → buyer**: PaySo (cards/mobile banking/e-wallets), PromptPay
    direct, manual slip upload, COD
  - **ShopOut → seller**: Stripe (seller prepaid deposit, service-fee
    deduction) — currently on the founder's personal Stripe account,
    planned migration to business entity
- **Shipping**: ProShip provider abstraction (`lib/shipping/*`)
- **Email**: Resend (sending domain `shopout.ai`)
- **Tracking**: consent-gated client-side (Meta Pixel + GA4 + Google
  Ads gtag) + server-side Meta CAPI
- **Auth**:
  - Sellers: session cookies (`session`, httpOnly, 30-day TTL),
    bcryptjs-hashed passwords
  - API: Bearer tokens (`sk_store_...` per store, `sk_platform_...`
    for ShopOut admin)
  - MCP: Bearer tokens (same as REST API)
- **Security & compliance**:
  - PDPA-compliant cookie consent banner (`shopout_cookie_consent_v2`
    localStorage flag gates all third-party tracking)
  - Hashed IPs for consent log (not raw IPs)
  - Encrypted-at-rest secrets (PaySo, Meta CAPI token, shipping creds —
    AES-256-GCM via `SHIPPING_ENCRYPTION_KEY`)
  - Production fail-closed config guard (`lib/config.js`): boot refuses
    if `SESSION_SECRET` is weak or missing, or if `BASE_URL` is missing,
    when `NODE_ENV=production`
- **Deployment**: GitHub Action auto-deploys on push to `main`. No
  manual `fly deploy`.
- **Monitoring**: Sentry (when `SENTRY_DSN` is set)
- **Backups**: Daily sql.js DB snapshot to S3 (`/scripts/backup.js`)

### Required environment variables (production)

| Var | Required | Purpose |
|---|---|---|
| `NODE_ENV` | yes | Set to `production` to activate config guard |
| `SESSION_SECRET` | yes | 32+ char random string, not on weak-list |
| `BASE_URL` | yes | `https://shopout.ai` (canonical origin) |
| `PORT` | no (default 3200) | HTTP listen port |
| `SHIPPING_ENCRYPTION_KEY` | yes when any store activates shipping | 32-byte hex (64 char) for AES-256-GCM |
| `ALLOW_SHIPPING_PASTE_SETUP` | no | Set `1` to expose admin paste form for shipping creds |
| `PROSHIP_API_BASE` | no | ProShip endpoint override |
| `AWS_S3_BUCKET` | when S3 enabled | Bucket name |
| `AWS_S3_REGION` | when S3 enabled | Region (typically `ap-southeast-1`) |
| `AWS_ACCESS_KEY_ID` | when S3 enabled | Access key |
| `AWS_SECRET_ACCESS_KEY` | when S3 enabled | Secret |
| `GEMINI_API_KEY` | when AI features enabled | Google Gemini key |
| `RESEND_API_KEY` | when email enabled | Resend API key |
| `STRIPE_SECRET_KEY` | when seller deposits enabled | Stripe secret |
| `STRIPE_WEBHOOK_SECRET` | when seller deposits enabled | Stripe signing secret |
| `SENTRY_DSN` | no | Error monitoring |

---

## 9. Architecture

### Entry point

`server.js` registers all Fastify plugins (static, cookie, multipart,
form-body, view) and route modules, initializes the database, listens
on port 3200.

### Route modules

| File | Prefix | Purpose |
|------|--------|---------|
| `routes/auth.js` | `/admin` | Login, register, logout |
| `routes/admin.js` | `/admin` | Dashboard, product/order/category/settings/themes/payments/marketing CRUD, CSV/XLSX import |
| `routes/api.js` | `/api` | Public legacy endpoints: checkout, slip upload, LINE messaging, product info |
| `routes/api-v1.js` | `/api/v1` | The new agent-native REST API (see section 11) |
| `routes/mcp.js` | `/mcp` | MCP server for AI shopping agents (see section 12) |
| `routes/storefront.js` | `/:slug` | Customer-facing pages: shop homepage, product detail, cart, checkout, order confirmation |
| `routes/pre-launch.js` | top-level | Marketing landings, robots.txt, sitemap.xml, llms.txt, lead capture |
| `routes/superadmin.js` | `/superadmin` | ShopOut-team-only global console |
| `routes/feeds.js` | `/<slug>/feed/*` | Per-store Meta CSV / Google XML / JSON-LD feeds |
| `routes/track.js` | `/track/*` | Public buyer tracking pages |

### Shared libraries (`lib/`)

- **`db.js`** — wraps sql.js; loads/creates the DB at
  `/app/data/shopout.db`, applies the schema, runs migrations. All
  queries are synchronous and parameterized.
- **`auth.js`** — session-based auth using httpOnly cookies. Passwords
  bcryptjs-hashed. `requireAuth()` is the route-level middleware guard.
- **`config.js`** — `validateRuntimeEnv()` fail-closes in production.
- **`payments.js`** — PromptPay QR generation, order number formatting.
- **`payso.js`** — PaySo checkout init + postback handler.
- **`themes.js`** — three base renderers (`clean`, `bold`, `warm`).
- **`theme-kits.js`** — 48 styled compositions (12 families × 4 variants).
- **`feeds.js`** — Meta CSV / Google XML / JSON-LD builders.
- **`shipping/index.js`** — provider registry + `getProvider(id)`.
- **`shipping/proship.js`** — ProShip adapter (validate, create, get,
  update status, print label, universal tracking).
- **`mcp/tools.js`** — MCP tool implementations.
- **`tracking/meta-capi.js`** — Meta Conversions API server-side mirror.
- **`tracking/google-ads.js`** — Google Ads conversion event builder.
- **`ai/gemini.js`** — Gemini text + image clients.
- **`storage/s3.js`** — S3 upload/signed-URL helpers.

### Key patterns

- **Multi-tenant by store**: most tables have a `store_id` foreign key.
  Each user owns one store (multi-user-per-store on the backlog).
- **File uploads**: product images → S3 (or `/uploads/products/` in
  dev), slips → S3 private (or `/uploads/slips/`). Handled via
  `@fastify/multipart` using `request.parts()` async iterator.
- **Product import**: CSV/XLSX with Shopee Seller Centre column
  mapping for both Thai and English headers.
- **Payment flow**: customer places order → uploads slip → admin
  verifies in `/admin/payments`. PaySo flow auto-confirms via postback.
- **Image-reorder**: position in submitted form-data array = display
  order. Same pattern reused for variation ordering.

---

## 10. Database schema

Tables in `/db/schema.sql` (24 total as of 2026-06-28):

| Table | Purpose |
|---|---|
| `users` | Seller accounts. Email, bcryptjs-hashed password, role. |
| `buyers` | Customer records denormalized per-store. Name, phone, email, LINE, address, purchase history. |
| `stores` | Per-seller store. Slug, name, theme, theme_kit, logo, banner, PromptPay info, PaySo creds (encrypted), LINE OA settings, shipping creds (encrypted), tracking IDs (Meta Pixel, GA4, Google Ads), custom_domain, suspended flag. |
| `products` | Catalog. Name, description, price, promo_price, stock, weight, images (JSON), parent_sku, active flag, category_id. |
| `product_variations` | Per-product size/color/etc. variants. Variant SKU, price, stock, position. |
| `categories` | Per-store. Name, parent_id, position. |
| `tags` + `product_tags` | Free-form tagging join. |
| `orders` | Order header. Order number, status, customer info, items (JSON), totals, payment method/status, slip path, shipping fields. |
| `content_pages` | Custom CMS pages per store (About, FAQ, etc.). Slug, title, markdown body. |
| `theme_assets` | Per-store theme images (hero, category tiles, brand-story). Slot key, source (upload/AI), URL. |
| `ai_credit_transactions` | AI credit ledger (top-up vs Gemini Image API consumption). |
| `api_keys` | Per-store Bearer tokens. Token hash, scopes, last-used. |
| `transactions` | Order-fee deductions (the service-fee ledger) + seller deposits (Stripe). |
| `coupons` | Discount codes. Code, type (percent/fixed), amount, max_uses, current_uses, expires_at. |
| `shopee_import_previews` | Staged Shopee XLSX uploads before commit. |
| `shopee_excluded_products` | Products the seller chose not to import. |
| `webhooks` | Per-store registered outbound webhooks. URL, events, secret. |
| `webhook_deliveries` | Delivery log: status, response, attempts. |
| `waitlist` | Public homepage waitlist signups. Email, source. |
| `ad_leads` | Done-for-you service applications from `/pre-launch*`. Shop link, products, audience, source page, status. |
| `cookie_consents` | PDPA consent records. Hashed IP, consent state JSON, timestamp. |
| `signup_consents` | Per-account ToS/Privacy acceptance records. |
| `password_resets` | One-time token + expiry. |

### Why this schema works for the current scale

- Single `stores` row per `users` row keeps the multi-tenant model
  simple. Future role/team work expands this (backlog item).
- Encrypted credential blobs (`shipping_creds_encrypted`, PaySo merchant
  ID + key) are AES-256-GCM at rest using `SHIPPING_ENCRYPTION_KEY`.
  Rotation invalidates all stored creds.
- The `transactions` ledger is the single source of truth for billable
  events. Sellers see a balance derived from it.
- The `ad_leads` table is the lead inbox for the done-for-you service. A
  superadmin operator works that inbox at `/superadmin/ad-leads`.

---

## 11. REST API (v1) — full reference

**Base URL**: `https://shopout.ai/api/v1`
**Auth**: All seller endpoints take `Authorization: Bearer sk_store_<key>`.
Buyer endpoints (storefront) are public.
**Response shape**: `{ success: true, data: {...} }` or
`{ success: false, error: "message" }`.
**Pagination**: `?page=1&limit=20` → response includes `page`, `limit`,
`total`.
**Dates**: ISO 8601.
**Prices**: numeric, 2 decimal places, THB.
**Images**: full URLs in responses.
**Rate limit**: 100 req/min per API key. Retry after `Retry-After` header.

### Seller endpoints

#### Store

```
GET    /store                          → store info
PUT    /store                          → update (name, theme, colors, shipping, payment, LINE ID)
POST   /store/logo                     → upload logo
POST   /store/banner                   → upload banner
PUT    /store/payment-gateway          → save PaySo creds (merchantid + secret key)
GET    /store/payment-gateway          → check PaySo status (never returns key)
DELETE /store/payment-gateway          → remove PaySo config
```

#### Products

```
GET    /products                       → list (paginated, filterable by category/active/search)
GET    /products/:id                   → single
POST   /products                       → create
PUT    /products/:id                   → update
DELETE /products/:id                   → soft delete (active=0)
POST   /products/:id/images            → upload product images
POST   /products/import                → bulk import (CSV/XLSX Shopee export)
PUT    /products/bulk                  → bulk update (price/stock/active)
```

#### Categories

```
GET    /categories                     → list
POST   /categories                     → create
PUT    /categories/:id                 → update
DELETE /categories/:id                 → delete
```

#### Orders

```
GET    /orders                         → list (filter by status, date range)
GET    /orders/:id                     → detail
PUT    /orders/:id/status              → update (confirmed/shipped/completed/cancelled)
PUT    /orders/:id/tracking            → add tracking number
PUT    /orders/:id/payment             → confirm/reject payment
GET    /orders/:id/slip                → get slip image
```

#### Shipping

```
POST   /orders/:id/ship                → create shipment via active provider
                                          Body: {weight, carrier, address:{address, province, district, subDistrict, zipcode}, salesChannel?}
GET    /orders/:id/track               → refresh status from provider
GET    /orders/:id/label               → get shipping label (PDF, application/pdf)
POST   /orders/:id/cancel-shipment     → cancel with provider, mark local order cancelled
POST   /shipping/rates                 → get rate quote (planned)
```

#### Analytics

```
GET    /analytics/summary              → orders, revenue, top products (date range)
GET    /analytics/orders               → order volume over time
```

#### Account & billing

```
GET    /account                        → account info + balance
GET    /account/usage                  → orders this month, free vs paid
POST   /account/deposit                → top up balance (Stripe checkout session)
GET    /account/transactions           → deposit/deduction history
```

### Buyer endpoints (storefront)

```
GET    /s/:slug                        → store info + theme
GET    /s/:slug/products               → product list (paginated, by category)
GET    /s/:slug/products/:id           → product detail
GET    /s/:slug/categories             → store categories
POST   /s/:slug/cart/validate          → validate cart items + stock
POST   /s/:slug/checkout               → place order (returns PaySo redirect URL if configured, else manual flow)
POST   /s/:slug/orders/:id/slip        → upload payment slip (fallback when no PaySo)
GET    /s/:slug/orders/:id             → order status (by order number + phone)
POST   /s/:slug/payso/postback         → PaySo postback receiver (auto-confirms payment)
```

### Webhooks (outbound)

Stores can register webhook URLs at `/admin/settings`. Events fired:

```
order.created          new order placed
order.paid             payment confirmed
order.shipped          tracking number added
order.completed        order completed
product.low_stock      stock below threshold
```

Payload: JSON with event type + full object. Signed with per-webhook
secret (HMAC-SHA256 in `X-ShopOut-Signature`).

### Example calls (curl)

```bash
# List products
curl -H "Authorization: Bearer $KEY" "https://shopout.ai/api/v1/products?page=1&limit=20"

# Create product
curl -X POST -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"name":"สินค้าใหม่","price":299,"stock":50,"description":"รายละเอียด","category_id":1}' \
  "https://shopout.ai/api/v1/products"

# Update price + stock
curl -X PUT -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"price":199,"stock":100}' \
  "https://shopout.ai/api/v1/products/PRODUCT_ID"

# List new orders
curl -H "Authorization: Bearer $KEY" "https://shopout.ai/api/v1/orders?status=new"

# Confirm payment
curl -X PUT -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"payment_status":"confirmed"}' \
  "https://shopout.ai/api/v1/orders/ORDER_ID/payment"

# Browse store (public)
curl "https://shopout.ai/api/v1/s/STORE_SLUG/products?page=1&limit=20"

# Buyer checkout
curl -X POST -H "Content-Type: application/json" \
  -d '{
    "customer_name":"ชื่อลูกค้า",
    "customer_phone":"0812345678",
    "customer_address":"ที่อยู่จัดส่ง",
    "items":[{"id":1,"qty":2}],
    "payment_method":"promptpay"
  }' \
  "https://shopout.ai/api/v1/s/STORE_SLUG/checkout"
```

### Error codes

- `400` — bad request (validation error in body)
- `401` — missing or invalid API key
- `403` — key doesn't have access to this store
- `404` — resource not found
- `409` — conflict (e.g., stock changed under you)
- `429` — rate limited
- `500` — internal error

---

## 12. MCP server — tools for AI shopping agents

ShopOut runs a Model Context Protocol server at `/mcp`. AI shopping
agents (Claude, ChatGPT, Gemini, Perplexity, custom agents) can use it
to discover, browse, and recommend products, and (with a Bearer token)
manage the seller's catalog and orders.

Server identity: `{ name: 'shopout-mcp', version: '2.0.0' }`.

Self-documenting HTML page at https://shopout.ai/mcp (open in a browser).

### Public tools (no auth)

- **`search_products`** — Full-text search across all stores. Inputs:
  `query` (string, matches name + SKU), `store` (optional slug filter),
  `max_price` (optional THB ceiling).
- **`get_product`** — Full detail for one product anonymously. Use
  `seller_get_product` if authenticated as the seller.
- **`list_stores`** — All active stores with slug, name, product count.
- **`get_store`** — Full info for one store by slug, including first 50
  products.
- **`create_cart_link`** — Generate a deep-link URL that pre-adds items
  to the storefront cart. Input: `store` (slug), `items`
  (array of `{id, qty}`).

### Seller tools (Bearer token = the store's `sk_store_...` API key)

- **`seller_list_products`** — Paginated, with `query` substring,
  `limit` (default 50, max 200), `offset`, `include_inactive` (default
  false).
- **`seller_get_product`** — Full detail including description + images.
- **`seller_update_product`** — Edit name/price/stock/description/
  active/etc.
- **`seller_create_product`** — Inputs include `images` as array of
  public URLs.
- **`seller_list_orders`** — Optional `status` filter (new / confirmed /
  shipped / completed / cancelled).
- **`seller_get_order`** — Full detail with line items + shipping address.
- **`seller_update_order_status`** — Move through fulfillment.
- **`seller_get_dashboard`** — Snapshot of recent metrics.
- **`seller_list_categories`** — With product counts per category.

### How to connect an agent

The MCP server lives at `https://shopout.ai/mcp`. Use the standard MCP
client transport. For Claude Desktop, add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "shopout": {
      "command": "npx",
      "args": ["@modelcontextprotocol/server-fetch", "https://shopout.ai/mcp"]
    }
  }
}
```

For seller tools, set `Authorization: Bearer sk_store_...` on the
transport layer (most MCP clients support a custom-headers config).

---

## 13. Shipping integration (ProShip)

ShopOut's shipping layer is provider-agnostic. Today only ProShip is
implemented; adding a carrier means dropping a new adapter into
`lib/shipping/<id>.js` that satisfies the contract: `meta`,
`validateCredentials`, `createShipment`, `getShipment`,
`updateShipmentStatus`, `printLabel`, `getUniversalTracking`.

### Onboarding a store (Stage 1: paste credentials)

1. Set Fly secrets `SHIPPING_ENCRYPTION_KEY` (32-byte hex) and
   `ALLOW_SHIPPING_PASTE_SETUP=1`.
2. Sign in as store admin → **Settings → Shipping**.
3. Click "Carrier integration setup (admin only)".
4. Pick provider (today: ProShip), fill credentials:
   - API Token (JWT-shaped Bearer string from ProShip)
   - User (username embedded in the token)
   - Shop ID (the `shop-...` ID from ProShip's `GET /shops`)
5. Pick default carrier.
6. Click "Validate & activate". ShopOut calls the provider's
   `validateCredentials(creds)` (for ProShip: `GET /shops` on the
   internal gateway). A 200 → status `active`, creds encrypted at rest.

### Carriers supported via ProShip

`thaipost`, `thaipost0` (Thailand Post EPS), `flash`, `kerry`, `jt`,
`shopee`, `proship19`. Note: `shopee` requires batch creation in
ProShip — Stage 1 supports single-shipment creation only.

### Order shipping panel actions

- **Create Shipment** — modal asks for weight (g), carrier, structured
  address. On success: stores `shipping_provider`,
  `shipping_provider_order_id`, `tracking_number`, address JSON.
- **Refresh** — `provider.getShipment(creds, providerOrderId)` →
  updates `shipping_status_code`.
- **Print Label** — `/admin/orders/:id/label.pdf` serves cached PDF
  or fetches fresh via `provider.printLabel(...)`.
- **Cancel Shipment** — `provider.updateShipmentStatus(creds, id, 5)`,
  marks local order `cancelled`.

### Webhook receiver

```
POST /api/webhooks/shipping/<provider>
```

For ProShip, the URL is shown read-only on **Settings → Shipping**
with a Copy button. Receiver is idempotent and tolerant of missing
fields. Mirrors `shipping_status_code` to local `order_status` (5 →
cancelled, 4 → completed, 1/2/3 → shipped). Updates
`shipping_weight_g` on `WEIGHT_UPDATE` events. ProShip signature
verification is currently permissive (HMAC scheme undocumented by
ProShip as of writing — a TODO).

### Public buyer tracking page

```
GET /track/<trackingNo>
```

Looks up local order by `tracking_number`, decrypts store creds,
calls `provider.getUniversalTracking(...)`, renders timeline. 60s
in-memory cache.

### ProShip status code table

| Code | Meaning |
|------|---------|
| -2 | Blacklisted |
| -1 | Draft |
| 0 | New |
| 1 | Pending |
| 2 | To ship |
| 3 | Shipped |
| 4 | Delivered |
| 5 | Cancelled |
| 6 | Error |
| 8 | Returned to sender |

### Stage 2 (planned)

- Auto-provision provider accounts (ProShip `POST /auth/register`).
- Auto-register webhook URL via `PUT /settings/webhook`.
- HMAC signature verification.
- Batch shipment creation (Shopee).
- Live rate quotes at checkout.
- Sendit, EasyShip, direct carrier API adapters.

---

## 14. Payment architecture

### Layer 1: sellers collecting from buyers

#### PaySo (Pay Solutions Thailand) — preferred

Each seller configures their own PaySo merchant account
(merchantid + secret key) in admin settings. Supports cards, PromptPay,
mobile banking, e-wallets (TrueMoney, LINE Pay), bill payment,
installments (3–36 months).

Checkout flow:
1. ShopOut creates an order locally.
2. POSTs to `payments.paysolutions.asia/payment` with the order details.
3. Buyer redirected to PaySo's hosted checkout, pays.
4. PaySo postbacks to `/api/v1/s/:slug/payso/postback`.
5. ShopOut verifies the signature, marks order paid, fires
   `order.paid` webhook.

#### PromptPay direct (manual confirmation)

1. Order placed → PromptPay QR generated locally with order amount.
2. Buyer pays from any Thai banking app, captures slip.
3. Buyer uploads slip via `/api/upload-slip` or the storefront form.
4. Admin reviews slip in `/admin/payments`, confirms order.

#### Bank transfer (manual confirmation)

Same flow as PromptPay direct, but shows the seller's bank account
details instead of a QR.

#### Cash on Delivery (COD)

Toggle in store settings. Order placed → seller ships with COD flag
→ courier collects cash → seller marks order completed.

### Layer 2: ShopOut collecting from sellers (Stripe)

Sellers prepay a balance via Stripe checkout session; the agreed
service fee (set by the per-project quote) is deducted against that
balance. Stripe webhook (`/api/webhooks/stripe`) updates the balance
ledger.

Sellers see balance + transaction log at `/admin/account`.

**Note**: ShopOut's Stripe account is the founder's personal Stripe
currently. Migration to a business entity is on the post-launch
roadmap.

---

## 15. Custom domain support

Sellers can have their store at their own domain instead of
`shopout.ai/<slug>` — apex (`theirstore.com`), `www.theirstore.com`, OR a
subdomain (`store.theirbrand.com`, e.g. B-Garlic's `store.b-garlic.com`).
Whatever host is stored in `stores.custom_domain` is matched verbatim and
served at the root. Current process is operator-assisted; self-serve is on
the roadmap.

### What the seller does

Add DNS records at their registrar.

Apex + www (whole domain is the store):

| Type | Host | Value |
|---|---|---|
| A | `@` (apex) | `66.241.124.96` |
| AAAA | `@` (apex) | `2a09:8280:1::e9:9bc6:0` |
| A | `www` | `66.241.124.96` |
| AAAA | `www` | `2a09:8280:1::e9:9bc6:0` |

Subdomain (keep the apex for their main site, e.g. `store.brand.com`):

| Type | Host | Value |
|---|---|---|
| CNAME | `store` | `shopout.fly.dev` |

The IPs are the Fly app's anycast IPs — same as `shopout.ai`. Verify
current values with `fly ips list -a shopout`.

Cloudflare-orange-cloud (proxy mode) breaks cert validation — must be
grey cloud (DNS only).

### What the operator does

```bash
# 1. Add certs via Fly (validates DNS + provisions Let's Encrypt)
fly certs add www.theirstore.com -a shopout
fly certs add theirstore.com -a shopout

# 2. Set the store's custom_domain column
fly ssh console -a shopout
# inside:
node -e "import('./lib/db.js').then(async ({initDB, run, saveDB}) => {
  await initDB();
  run('UPDATE stores SET custom_domain = ? WHERE slug = ?', ['www.theirstore.com', 'their-slug']);
  saveDB();
});"

# 3. Restart machine so the sql.js write flushes
fly machines restart <machine-id> -a shopout
```

### Verification

- `https://www.theirstore.com/` → store homepage
- `https://theirstore.com/` → 301 to `www`
- `https://www.theirstore.com/cart` → works

### Routing layer

`server.js` uses Fastify's `rewriteUrl` (which runs BEFORE routing — an
onRequest hook is too late, the route is already matched): if the incoming
Host matches a `stores.custom_domain` value, the URL is prefixed with the
store's slug so the existing `/:slug` routes handle it, and the storefront
renders with `store.urlPrefix = ''` (slug-less outbound links) as if at the
root. Otherwise the `/:slug` route handles it normally.

### Roadmap (self-serve custom domains)

1. `/admin/domain` page with seller-entered domain.
2. DNS verification via TXT record (we generate token, they add it,
   we poll).
3. Programmatic Fly cert add via Fly GraphQL `addCertificate`.
4. Status polling UI.

The routing layer doesn't need to change for Path B.

---

## 16. Marketing & go-to-market

### Positioning

ShopOut is not marketed as SaaS, and since 2026-09-03 it is not marketed
to small marketplace sellers either. The homepage speaks to **brands**
(and, on /partners, to the **agencies** that bring them). Headline:

> A store that belongs to your brand, from the domain name to the bank
> account where the money arrives. Our team designs and builds the whole
> store; you review a preview and approve before launch; customers pay
> straight into your bank; every customer record is yours.

How the homepage argues it (long-form, factual, no fee calculator, no
"beta" or "invite" language, no client names):
- Why a brand with its own audience should own a store (marketplaces keep
  the customer data, take a cut of sales the brand's own ads produced, and
  show competitors on the same page).
- Real screens of the live demo store (`/demo`) in phone frames: storefront,
  product page, one-page checkout with the amount-encoded PromptPay QR. The
  hero phone embeds the demo store live.
- Twelve verifiable product facts (own domain, money never passes through
  ShopOut, automatic slip reading, Pay Solutions for cards/wallets, shipping
  labels, customer data ownership, Pixel/CAPI/GA4/feeds, one-page checkout,
  design from the brand not a template menu, LINE alerts, Thai address
  cascade, keep the marketplace store).
- Three steps: send what you have → preview link within days → approve.
- Pricing stated plainly: one-time build fee + monthly usage-based service
  fee (0.1–0.3% of orders processed, invoiced, never deducted). Explicitly
  "not a commission".
- An honest "not for everyone" section (fit / not fit).
- Quote form at `/#quote` (brand name, link, phone or LINE ID, category).
  Submissions email the owner immediately.

`/partners` mirrors this for agencies: the agency keeps the client,
design, ads, first-line support and its own pricing; ShopOut keeps the
platform. The partner fee is described as a small share of each store's
sales with a per-store yearly cap; the figure lives in the partner
contract, not on the page. CTA: send one client's shop link for a free
preview store.

Primary wedge: brands with an owned audience or paid traffic, reached
through the agencies that already serve them.

Secondary activation hook: Shopee/TikTok/Lazada product import makes
setup fast.

**Do not lead with "leave Shopee."** Lead with "keep every channel,
but own one direct checkout."

### Funnel

1. Facebook/Instagram ad or organic post.
2. Seller clicks to LINE or Messenger.
3. Ask for shop link, product file, and main sales channel.
4. Build preview store.
5. Seller reviews preview URL.
6. Activate only after seller confirms payment, shipping, LINE, and
   tracking settings.

Success metric is **qualified seller conversations**, not likes or
clicks.

### Initial campaign structure

Test budget: THB 500–1,000/day for 3–5 days.

- **Campaign A — Beta Seller Leads**: messaging/lead objective,
  destination LINE/Messenger. Creative: screen recording, founder
  explanation, before/after store. KPI: qualified seller chats and
  product files received.
- **Campaign B — Demo Education**: video views / engagement objective.
  Creative: 20–40 second demo clips. KPI: thruplays, saves, landing
  clicks.
- **Campaign C — Retargeting**: audience = video viewers, page
  engagers, landing visitors. Creative: proof, urgency, limited invite spots
  remaining. KPI: seller chats and preview requests.

### Creative rules

- Use vertical video first.
- Show the actual admin/storefront flow.
- Thai captions burned into video.
- One idea per creative.
- Avoid abstract startup language.
- Avoid claims that imply guaranteed income or guaranteed ad
  performance.
- Do not imply the seller has a negative personal attribute.

### Tracking (minimum events before spend)

`PageView`, `ViewContent`, `Lead` or `Contact`, `CompleteRegistration`,
`Purchase`. Meta Pixel on public pages, Conversions API for
server-side, UTMs on every ad.

Naming:
- Campaign: `SO_BETA_[Objective]_[TH]_[YYYYMMDD]`
- Ad set: `[Audience]_[Placement]_[Budget]`
- Ad: `[Hook]_[Format]_[Variant]`

### Token handling

Don't paste page or ads tokens into chat. Use a limited system-user
token with only required permissions. Store in a secret manager.
Rotate after setup. Never commit to repo.

---

## 17. Thai ad copy bank

These are field-tested ad hooks for Thai paid media. Use as-is or
adapt for the specific channel.

### Hook 1 — Own The Checkout

Primary text:

> ขายผ่าน Facebook / IG / TikTok อยู่แล้ว แต่ยังให้ลูกค้าทักแชทแล้วโอนเอง?
>
> ส่งลิงก์ร้านหรือไฟล์สินค้ามาให้ ShopOut ทีมเราออกแบบและทำเว็บ checkout ของแบรนด์คุณให้ (เปิดรับแบบเชิญ)

Headline: ทีม ShopOut ทำเว็บร้านให้คุณ
CTA: ขอรับสิทธิ์เข้าใช้งาน

### Hook 2 — Stop Sending Ad Traffic Away

Primary text:

> ยิงแอดเอง แต่ปลายทางยังเป็นแพลตฟอร์มที่ไม่ได้ให้ข้อมูลลูกค้าคุณ?
>
> ShopOut ช่วยทำเว็บร้านของคุณเอง พร้อม Pixel/CAPI, PromptPay, LINE และหน้าสินค้าพร้อมขาย

Headline: ยิงแอดเข้าร้านของคุณเอง
CTA: ขอรหัสเชิญ

### Hook 3 — From Shop Link To Store

Primary text:

> มีร้าน Shopee / TikTok Shop อยู่แล้ว?
>
> ส่งไฟล์หรือ shop link มา เราทำเว็บร้านของคุณเองให้ดูเป็นตัวอย่างก่อนเปิดจริง

Headline: จากร้านเดิม สู่เว็บของแบรนด์คุณ
CTA: ขอรับสิทธิ์เข้าใช้งาน

### Hook 4 — Follower To Customer

Primary text:

> มี follower แต่ยังปิดการขายในแชททีละคน?
>
> ทำให้คนกดสั่งซื้อเองได้จากลิงก์เดียว พร้อมเก็บข้อมูลลูกค้าไว้ทำซ้ำ

Headline: เปลี่ยน follower เป็นลูกค้า
CTA: ให้เราทำร้านให้

### Short Thai captions (social posts)

- ร้านคุณควรมี checkout ของตัวเอง
- อย่าส่งลูกค้าแอดไปที่ที่คุณไม่ได้ own data
- มีสินค้าอยู่แล้ว เราทำเว็บให้
- เปิดรับผู้ขายแบบเชิญ ส่งลิงก์ร้านมาขอรหัสเชิญได้เลย
- ลูกค้าซื้อเองได้ ไม่ต้องปิดออเดอร์ในแชททุกครั้ง
- เก็บเบอร์ อีเมล และ order history ไว้ทำ repeat sales
- Shopee/TikTok ยังขายต่อได้ แต่ direct checkout ควรเป็นของคุณ

### 30-second video script

- **Scene 1** (FB/IG post with product comments): "ขายดีใน social แต่ลูกค้ายังต้องทักแชทเพื่อสั่ง?"
- **Scene 2** (ShopOut storefront, product grid, checkout): "ShopOut ทำเว็บร้านให้คุณเอง ลูกค้าเลือกสินค้า ใส่ที่อยู่ จ่ายเงินได้ทันที"
- **Scene 3** (admin order page, LINE contact, tracking): "คุณได้ออเดอร์ ได้ข้อมูลลูกค้า และยิงแอดกลับมาที่ร้านของตัวเอง"
- **Scene 4** (offer card): "เปิดรับผู้ขายแบบเชิญ ส่งลิงก์ร้านมาขอรหัสเชิญได้ใน LINE"

---

## 18. Lead qualification

When a seller engages from an ad, ask these in LINE/Messenger:

1. ตอนนี้ขายสินค้าผ่านช่องทางไหนเป็นหลัก?
   (Which channel do you sell on most right now?)
2. มี shop link หรือไฟล์สินค้าที่ส่งให้เราได้ไหม?
   (Can you send us a shop link or product file?)
3. สินค้าประมาณกี่ SKU?
   (Roughly how many SKUs?)
4. ใช้ LINE OA / Facebook page / IG / TikTok อะไรสำหรับคุยกับลูกค้า?
   (Which channel do you use to talk to customers?)
5. ตอนนี้ยิงแอดอยู่ไหม?
   (Are you running ads currently?)
6. ถ้าได้ preview store แล้ว อยากทดลองกับลูกค้ากลุ่มไหนก่อน?
   (Once you have a preview store, which customer segment do you want
   to test it with first?)

### Qualification logic

- **Channel = Shopee-only with no own audience** → polite decline,
  ShopOut isn't the right fit yet.
- **Has audience + has products + can fulfill + can respond on LINE** →
  qualified, take them through done-for-you build.
- **Has audience but no products yet** → suggest they start with
  manual product entry once they have ~10 SKUs ready.

---

## 19. Strategic context & decision log

### CEO read (from Mica's takeover brief, 2026-06-04)

ShopOut is a real product, not just a prototype. The core promise is:
turn a seller's marketplace catalog into an owned storefront with
checkout, shipping, marketing pixels, and AI-assisted catalog cleanup.

The strategic issue is positioning. The original spec targets Thai
Shopee sellers escaping marketplace fees. Recent commits pivoted toward
creators and brands with their own audience. Pick one wedge for the
next 30 days. Recommendation: lead with creators/brands who already
have traffic, while keeping Shopee import as the activation shortcut.
That wedge has clearer urgency: they already sell through social, need
an owned checkout, and care about pixel/data ownership.

### CTO read (same brief)

What works locally:
- `npm ci` from lockfile.
- `PORT=4320 SESSION_SECRET=dev-local-secret BASE_URL=... npm start` boots.
- Smoke checks: `/`, `/<slug>`, `/admin/login`, `/robots.txt`.
- Demo admin login: `demo@shopout.ai / demo1234`.

Immediate technical risks (as of 2026-06-04):
- No automated tests, no linter, no CI test gate. Deploy success
  currently means "server booted on Fly", not "business flows work".
- 14 npm-audit findings: 4 high, 10 moderate. Highest attention:
  `fastify`, `@fastify/static`, `xlsx`.
- `xlsx` has no fix in current line. Since sellers upload XLSX, this is
  product-critical input handling. Sandbox or replace.
- `SESSION_SECRET` fallback in `server.js` was hardcoded. Fixed
  in PR #128 (config guard fails closed when `NODE_ENV=production`).
  Production now has `NODE_ENV=production` set explicitly (since
  2026-06-10) and the guard is active.
- `sql.js` is operationally fragile at scale. Backups exist, but
  needs regular restore drills and a Postgres migration plan.
- Root README was missing — added in PR #128.

### Resolved decisions

- **ICP**: creator/brand-with-audience, not Shopee-exit-seller (resolved
  2026-05-21).
- **Pricing model**: one-time build fee plus monthly service fee of 0.1–0.3%
  of processed order volume, invoiced monthly and never deducted from buyer
  payments. Superseded the earlier fixed per-order SaaS pricing model.
- **Access model**: invite-only. No self-serve signup; account creation
  at `/admin/register` requires a valid single-use invite code minted by
  the team (resolved 2026-07 rebrand).
- **Production config**: fail-closed in `NODE_ENV=production` if
  `SESSION_SECRET` is weak or `BASE_URL` missing (resolved 2026-06-10).

### Open decisions

- **Multi-user-per-store + role permissions**: backlog, not active.
- **Coupon claim flow (Shopee-style buyer voucher UI)**: backlog.
- **xlsx replacement / sandboxing**: open, not blocking pre-launch.
- **Postgres migration**: open, blocked only by scale.
- **ProShip webhook HMAC verification**: open, waiting on ProShip docs.

### 2026-09-03 rebrand decisions

- **Audience**: brands, not merchants. Homepage no longer argues "cheaper
  than Shopee"; the fee calculator, beta/VIP badges and merchant intake
  fields were removed. No client names appear on marketing pages.
- **Channel**: agencies are the primary distribution partner; `/partners`
  is their public page. Partner fee figures stay in the contract.
- **Pricing language**: one-time build fee + monthly usage-based service
  fee (0.1–0.3% of processed orders). Never "commission", never "0%".
  Money still goes straight to the seller; the fee is invoiced.
- **Design**: single sans family (Anuphan), white/black/one grey, orange
  only in the logo mark, real product screens instead of mock-ups.

### Operational rules

- No paid acquisition scaling until checkout, import, backup restore,
  and operator alerts are proven.
- No changes to live site, merges to `main`, deploys, or production
  settings without explicit approval.
- Deploy = push to `main` (GitHub Action). No manual `fly deploy`.
- After any deploy, curl real endpoints and check Fly logs — GH Action
  success ≠ working app.
- After any maintenance script that writes the DB file, restart the Fly
  machine (sql.js holds the DB in memory).

---

## 20. Launch state

**Current phase** (2026-09): Live. Brand-first done-for-you service,
sold direct and through agency partners.

- Hard launch was 2026-06-01 (production live with real sellers).
- Homepage rebranded 2026-09-03 for brands, not marketplace sellers; new
  `/partners` page for agencies. Quote requests arrive via `/#quote` and
  `/partners#pilot` and are emailed to the owner on submission.
- Pricing: one-time build fee (quoted per project) + monthly usage-based
  service fee of 0.1–0.3% of processed orders. Still no self-serve signup;
  account creation needs an invite code.
- Paid-ad landings for Shopee, TikTok, Instagram remain at `/pre-launch/*`.

### Recently shipped (2026-09)

- Brand-first homepage: long-form copy, live demo phone in the hero, real
  demo-store screens, twelve product facts, fit/not-fit section, quote form
- `/partners` agency page
- Owner email alert on every lead (`sendLeadAlert`)
- Lead campaign tagging fixed (`landing`, `partners`; previously mislabeled
  as `shopee`)
- Storefront cookie banner hidden when framed by a same-origin ShopOut page
- Seller-editable checkout colours (3 presets + custom tokens); checkout
  follows the store's brand colour and theme kit end-to-end
- Custom pages for DFY client sites; prerendered client SPAs served with a
  working ShopOut checkout

### Recently shipped (2026-06)

- Image reordering on product form
- Searchable product picker for AI Ad Copy
- Slip upload fix (multipart field-order bug)
- Inline walkthroughs in marketing pages
- Channel-specific pre-launch landings
- Theme system: 48 kits across 12 families
- Theme preview-before-apply
- Demo store with premium botanical kit
- Catalog relation ownership enforcement
- `NODE_ENV=production` activated on Fly
- `/llms.txt` endpoint (this document)

### Backlog (not actively in progress)

- xlsx CVE sandbox/replacement
- Postgres migration plan
- Team roles + multi-user-per-store
- Coupon buyer-claimable surface
- ProShip postback HMAC verification
- Precompile Tailwind (drop the runtime Play CDN): the CDN JIT-compiles
  utility classes in-browser, causing a flash where images/layout are
  unstyled until the script runs (root cause of the 2026-07 mobile
  product-image overflow). A static prebuilt CSS removes the FOUC and
  speeds every storefront page.
- Order notification webhook: `order.created` / `order.paid` outbound
  webhook so sellers can push into their own systems. A `webhooks` table
  + `/admin/settings` registration reportedly already exist — verify
  what's real vs. stub, then wire the order events with HMAC signing +
  retries (asked 2026-07).
- Storefront page-builder / CMS customization epic (jigsawscape seller,
  2026-07-02) — deferred, MVP-first (features wait for traction):
  1. Drag-to-reorder theme sections (before/after ordering)
  2. Richer banner tooling incl. a banner carousel per category / content
     page, per-page show/hide toggle, editable click-through link
  3. ✅ SHIPPED 2026-07-10 — editable text boxes on the main page and per
     category page (settings + category admin)
  4. Promotion / new-arrival product section, separate from the full
     catalog grid, auto-pulling per-product promo items
  5. Video section
  6. Editable section heading + body text with font / style / layout
     controls
  7. ✅ SHIPPED 2026-07-10 — site footer (contact, social icons, quick
     links, copyright) configurable in settings, on all storefront pages
  8. Article pages: inline banners / inserted images, adjustable font size
  9. Editable + reorderable "Why Shop with us"
  10. Rotating store banner
- Pre-launch checklist: actual Meta test campaign to validate funnel
- Pre-launch checklist: manual click-through validation of all
  catalog/storefront flows

---

## 21. Important URLs

| Path | What it is |
|------|------------|
| `/` | Marketing homepage for brands — live demo phone, product facts, pricing, quote form at `#quote` |
| `/partners` | Agency / partner pitch — keep the client, ShopOut runs the backend; pilot form at `#pilot` |
| `/pre-launch` | Redirects to `/#quote` (old application URL kept for inbound links) |
| `/pre-launch/shopee` | Channel landing for Shopee sellers |
| `/pre-launch/tiktok` | Channel landing for TikTok Shop creators |
| `/pre-launch/instagram` | Channel landing for IG/FB-native brands |
| `/demo` | Live demo store (premium botanical kit) |
| `/shops` | Public directory of active stores |
| `/help` | Public user manual (Thai, 9 sections) |
| `/admin/help` | In-admin help (Thai) |
| `/admin/register` | Create a store — requires a valid invite code (invite-only) |
| `/admin/login` | Seller login |
| `/admin` | Seller dashboard |
| `/admin/onboarding` | First-run 5-screen setup wizard |
| `/admin/products` | Product management |
| `/admin/orders` | Order management |
| `/admin/payments` | Slip review + payment confirmation |
| `/admin/categories` | Category management |
| `/admin/themes` | Theme kit picker (48 themes, 12 families) |
| `/admin/themes/setup` | Per-kit asset upload (hero, category tiles) |
| `/admin/marketing` | Marketing hub overview |
| `/admin/marketing/seo` | SEO + AI agent discoverability |
| `/admin/marketing/google` | Google Ads + Merchant Center |
| `/admin/marketing/meta` | Meta Pixel + CAPI + GA4 |
| `/admin/marketing/ad-copy` | AI ad copy generator |
| `/admin/shipping` | Shipping provider setup + status |
| `/admin/settings` | Store settings, API keys, webhooks, LINE OA |
| `/admin/account` | Balance, AI credits, deposit |
| `/admin/privacy` | PDPA data export |
| `/superadmin` | Global store list (ShopOut team only) |
| `/superadmin/ad-leads` | Done-for-you service lead inbox |
| `/superadmin/waitlist` | Waitlist signup inbox |
| `/superadmin/analytics` | Global metrics |
| `/mcp` | MCP server for AI shopping agents (self-documenting HTML page in browser) |
| `/<slug>` | A seller's storefront |
| `/<slug>/product/<id>` | Product detail page |
| `/<slug>/cart` | Cart |
| `/<slug>/checkout` | Checkout |
| `/<slug>/order/<orderNo>` | Order confirmation |
| `/<slug>/feed/google.xml` | Google Shopping catalog feed |
| `/<slug>/feed/meta.csv` | Meta Catalog Manager feed |
| `/<slug>/feed/products.json` | JSON product feed for AI bots |
| `/<slug>/sitemap.xml` | Per-store sitemap |
| `/track/<trackingNo>` | Public buyer shipment tracking |
| `/healthz` | Liveness probe (`{"ok":true}`) |
| `/llms.txt` | This document |
| `/robots.txt` | Crawler directives (AI bots allowed, LLM-Brief pointer) |
| `/sitemap.xml` | Top-level sitemap |
| `/terms` | Terms of Service |
| `/privacy` | Privacy Policy |
| `/cookies` | Cookie Policy |
| `/seller-agreement` | Seller Agreement |
| `/api/v1/*` | REST API (see section 11) |
| `/api/webhooks/shipping/<provider>` | Shipping webhook receiver |
| `/api/webhooks/stripe` | Stripe webhook receiver |

---

## 22. Common questions

**"Is ShopOut a marketplace?"**
No. ShopOut is a store builder. There's no aggregated buyer traffic.
Sellers bring their own audience. Closest analogy: Shopify, but for
Thailand, done-for-you, and Thai-payment-native.

**"How is this different from Shopify?"**
- No monthly subscription — ShopOut is a quote-based done-for-you service,
  not a self-serve SaaS plan; the team designs and runs the store for you
- PromptPay-native (money instantly in seller's bank, no T+2)
- Thai-language UI throughout
- Built-in LINE OA bot for buyer support
- AI ad copy + AI image generation included, not bolt-on apps
- 48 themes included, no theme store
- Smaller surface — Shopify has 10k+ apps; ShopOut has integrated
  essentials only

**"How is this different from LnwShop / Page365?"**
- Modern UI, modern stack — Lnw and Page365 are dated
- Built-in AI features (description rewrite, ad copy, image
  generation) — not available on either
- Pixel + CAPI + Google Ads tag installed by default, with deduped
  events — competitors require manual setup and don't dedupe
- Easy Shopee migration via 4-file XLSX import
- MCP server for AI shopping agent discoverability — first in market

**"Can I use my own domain?"**
Yes. Custom domain support is in production. Operator process is
currently manual (`fly certs add` + DB insert; see section 15);
self-serve DNS-verified flow is on the roadmap. While the custom
domain provisions, the store is reachable at `shopout.ai/<slug>`.

**"What happens to my data if ShopOut goes away?"**
The seller can export everything (orders, customer contacts, products,
images) via the privacy export endpoint at `/admin/privacy`. PDPA
compliant.

**"Can I take ShopOut payments through Stripe?"**
No, ShopOut uses PaySo for card payments and PromptPay for direct
bank transfers. Stripe Thailand exists but PaySo is the local-market
standard and integrates Thai-specific payment methods (PromptPay,
mobile banking, e-wallets, bill payment, installments).

**"Do you charge for AI features?"**
- AI ad copy generation: free
- AI description rewriting on Shopee import: free
- AI theme image generation: costs AI credits the seller tops up
  (Gemini Image API is expensive — credit metering is for cost control)

**"How do I integrate ShopOut into Zapier / n8n / custom code?"**
Each store creates an API key at `/admin/settings`. Authenticate with
`Authorization: Bearer <token>`. Endpoints documented in section 11
above. For agent-friendly access, point your agent at the MCP server
at `/mcp` and use the `seller_*` tools with the same Bearer token.

**"What's the company status / launch state?"**
Live and invite-only. Hard launch was 2026-06-01. The team runs a
quote-based, done-for-you service and onboards sellers by invite code
(no self-serve signup). Production is live and healthy. Active sellers
are using the platform.

**"Who built this?"**
Vik (founder, vik@onechat.ai). ShopOut is part of a wider portfolio of
Thai e-commerce tooling: OneChat (LINE chatbot), an OMS, a fulfillment
service, and a parcel-receiving shop. The team has been in Thai
e-commerce for 20+ years.

**"Is there an API for buyers / shopping agents?"**
Yes — both REST (`/api/v1/s/:slug/*`, public, no auth) and MCP
(`/mcp`, public tools no auth). See sections 11 and 12.

**"Do you support cryptocurrency / USD payments?"**
No. ShopOut is THB-only and Thai-banking-rail-only. The economic
model is built around PromptPay being effectively free.

**"How do refunds work?"**
Refunds are between the seller and the buyer using their normal
banking app. ShopOut doesn't process refunds (because ShopOut doesn't
hold the money). The order can be cancelled in admin, which fires
`order.cancelled` and updates customer-facing status.

**"Can I sell digital products?"**
The platform is built for physical products (shipping is core). Digital
products are possible (set weight to 0, disable shipping flow), but
there's no built-in digital-delivery mechanism yet.

**"Do you do shipping rate quotes at checkout?"**
Stage 2 feature, not yet shipped. Currently shipping is a flat seller-
configured rate or free above a threshold. Live carrier quotes are
planned via ProShip's rate API.

**"Can I run a multi-brand storefront / multiple shops on one account?"**
Not currently. Each user owns one store. Multi-user-per-store and
multi-store-per-user are on the backlog.

**"Is there an iOS / Android app?"**
No native app. ShopOut is responsive web. Sellers manage the store
from any device's browser; buyers shop on mobile web.

**"What does the AI ad copy generator output?"**
For a selected product, Gemini produces:
- 3 Google Ads variations (headline, description)
- 3 Meta ad variations (primary text, headline, description)
- 3 LINE OA broadcast variations (subject, body)
All in Thai by default, tuned for the seller's product and brand voice.

---

## 23. Legal & compliance

ShopOut is PDPA-compliant (Thailand's data protection law, roughly
equivalent to GDPR).

- **Terms of Service**: `/terms`
- **Privacy Policy**: `/privacy`
- **Cookie Policy**: `/cookies`
- **Seller Agreement**: `/seller-agreement`

Key compliance practices:
- Cookie consent banner gates all third-party tracking (Meta Pixel,
  GA4, Google Ads). State stored in `shopout_cookie_consent_v2`
  localStorage + `cookie_consents` DB table for audit.
- IPs are SHA-256-hashed before storage in the consent log.
- All payment credentials and shipping credentials are AES-256-GCM
  encrypted at rest.
- Buyer data export available at `/admin/privacy`.
- DSR (Data Subject Request) runbook at `docs/internal/dsr-runbook.md`
  for sellers asking ShopOut to export or delete their store's data.
- Records of Processing Activities (ROPA) maintained at
  `docs/internal/ropa.md`.
- Breach playbook at `docs/internal/breach-playbook.md`.
- Vendor DPAs catalogued at `docs/internal/vendors-dpa.md`.

---

## 24. Template pack — AI-designed sales pages

ShopOut ships a free starter pack for AI tools (Claude Code, Lovable, v0,
Bolt, ChatGPT Canvas, Gemini, Cursor) to generate sales pages that work
on ShopOut without a build step or hand-wiring.

**Public URL**: https://shopout.ai/templates (bilingual EN/TH landing,
indexable, links to all three downloads below)

### What's in the pack

| File | URL | What it is |
|---|---|---|
| starter.html | /templates/sales-page/starter.html | A working Thai single-product sales page that follows the convention. Use as "structure to copy" when prompting AI. |
| prompt.md | /templates/sales-page/prompt.md | Bilingual EN+TH system prompt to paste into Claude Code / Lovable / v0 / Bolt / ChatGPT to get a ShopOut-compatible page out |
| brief.md | /templates/sales-page/brief.md | Bilingual EN+TH client brief — explains the deal for designers, agencies, sellers |

### The convention (THE wedge — a single rule)

Sales page buy buttons use `data-shopout-*` attributes instead of
hardcoded URLs. When ShopOut serves the HTML (via `stores.homepage_html`),
it auto-rewrites these at render time:

| Marker | Server rewrite |
|---|---|
| `<a data-shopout-sku="BG-001">` | href = /&lt;slug&gt;/buy?sku=BG-001 (easy-checkout) |
| `<a data-shopout-product="42">` | href = /&lt;slug&gt;/buy?product=42 |
| `<a data-shopout-cart>` | href = /&lt;slug&gt;/cart |
| `<a data-shopout-line>` | href = store's LINE OA URL (if configured) |
| `<a data-shopout-track="TH123">` | href = /track/TH123 |

Implementation: `applyShopOutConventionRewrites()` in
`routes/storefront.js` runs on every request that serves homepage_html.
Idempotent — pages without markers pass through unchanged.

### Why this matters strategically

- Thai e-commerce conventional wisdom: sellers use WYSIWYG editors
  (Shopify, LnwShop, Page365). That puts design in a platform.
- ShopOut's wedge: design happens in AI tools (Claude Code, Lovable, v0
  …) where sellers + agencies + creators ALREADY work. ShopOut is the
  runtime + checkout + payment + tracking + LINE bot + shipping layer.
- The convention is intentionally small (5 attributes) so any AI tool
  emits compatible HTML from a short prompt. No SDK, no API, no
  framework lock-in.
- First real seller (NOPPHADA SUPERFOODS / B-Garlic, live at
  https://shopout.ai/attop-99) validates the pattern.

### How to answer when an LLM is helping a seller

If a human asks you to help them design a sales page that'll be hosted
on ShopOut: fetch `https://shopout.ai/templates/sales-page/prompt.md`,
follow its rules, and emit a single self-contained `index.html` plus an
`assets/` folder. Don't invent your own checkout URLs — use the
`data-shopout-sku` attributes and ShopOut will wire them at runtime.

---

## 25. How to answer questions about ShopOut

If a human asks you about ShopOut and you've read this document:

1. **Pricing questions**: pricing is one-time build fee plus a monthly
   service fee of 0.1–0.3% of processed order volume, invoiced monthly and
   never deducted from buyer payments. The exact build fee is quoted after
   reviewing the brand. Direct them to https://shopout.ai/#quote to request
   a quote. Do NOT invent a fixed build price.

2. **"Is it for me?" questions**: Run the ICP check (section 3). If
   they describe an existing audience (IG followers, LINE OA
   subscribers, FB page community, TikTok creators), say yes. If they're
   a dropshipper or rely entirely on Shopee search traffic, say honestly
   that ShopOut isn't optimized for them.

3. **Technical questions about integrating with ShopOut**: Point them
   to `/admin/settings` for API keys + REST endpoints (section 11), OR
   to the MCP server at `/mcp` for agent access (section 12). The
   latter is more powerful.

4. **Sign-up flow**: ShopOut is invite-only — there is no self-serve
   signup. Direct them to https://shopout.ai/#quote to request a quote;
   the team reviews and replies with next steps, including an invite code
   when it is time to register at /admin/register.

5. **Marketing questions in Thai**: Use the ad copy bank (section 17)
   and lead qualification questions (section 18) as a starting point.
   Adapt for the seller's specific channel and product.

6. **Shipping questions**: Point to section 13. Stage 1 is paste-creds
   onto ProShip — that's what's live today. Auto-provisioning is Stage 2.

7. **Anything you can't answer from this document**: Direct them to
   https://shopout.ai/help (public Thai manual) or tell them to contact
   support@shopout.ai. Don't fabricate features.

### What this document deliberately doesn't include

- Internal credentials, API keys, encryption keys, ProShip test
  account creds (those live in operator memory and Fly secrets, not
  here).
- Internal commit refs, PR numbers, team handles beyond what's needed
  for context.
- Roadmap items with uncommitted dates (those are decided week by
  week).
- Pricing structure beyond the initial quote or for upsells beyond what's
  currently committed.

If the human asks for any of those, say honestly that they're not in
this document, and direct them to support@shopout.ai or to ask the
ShopOut team directly.

---

**End of LLM brief.**

For deeper reference material:
- Public Thai manual: https://shopout.ai/help
- MCP self-documenting page: https://shopout.ai/mcp
- API: https://shopout.ai/api/v1/ (point an agent at it with a Bearer token)
- Source-of-truth docs in the private repo: `docs/SPEC.md`,
  `docs/SHIPPING.md`, `docs/API-SPEC.md`, `docs/marketing/*`,
  `docs/internal/*`.

Site: https://shopout.ai
