### Install Dependencies and Run Locally Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_CHECKLIST.md Commands to install project dependencies and start the local development server. Visit http://localhost:3000 to view the application. ```bash # 1. Install dependencies npm install # 2. Test locally npm run dev # Visit http://localhost:3000 ``` -------------------------------- ### Start Development Server Source: https://github.com/lawwho23-stack/2b_saas/blob/main/TESTING_GUIDE.md Run this command to start the local development server for the dashboard. Access the UI at http://localhost:3000. ```bash npm run dev ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Install all necessary Node.js packages for the project. ```bash npm install ``` -------------------------------- ### Run Development Server Source: https://github.com/lawwho23-stack/2b_saas/blob/main/README.md Use these commands to start the Next.js development server. Open http://localhost:3000 in your browser to view the application. ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` -------------------------------- ### 3-Minute Quick Start Commands Source: https://github.com/lawwho23-stack/2b_saas/blob/main/START_HERE.md A condensed sequence of commands for quickly seeding data, deploying the n8n workflow, and testing the local development server. ```bash # 1. Seed test data npx ts-node scripts/seed.ts # โ†’ Note: workspace_id, bot_id # 2. Follow N8N_ACTION_ITEMS.md # Step 1: Collect credentials (5 min) # Step 2: Deploy Supabase (10 min) [if not done] # Step 3: Import n8n workflow (10 min) # Step 4: Test (10 min) # 3. Test locally npm run dev # Visit http://localhost:3000 # See your test message appear in real-time โœจ ``` -------------------------------- ### Webhook โ†’ Slack Workflow Example Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md A simple workflow pattern starting with a webhook, followed by data transformation and posting to Slack. ```plaintext 1. Webhook (POST, path: "form-submit") 2. Set (map form fields) 3. Slack (post to #notifications) ``` -------------------------------- ### Common Development Commands Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/QUICK_REFERENCE.md Essential commands for managing the project, including installation, running the dev server, seeding data, building, and deploying. ```bash # Install dependencies npm install # Start dev server npm run dev # Seed test data npx ts-node scripts/seed.ts # Build for production npm run build # Deploy to Vercel vercel deploy ``` -------------------------------- ### Example Finding Format Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md Demonstrates the structure for reporting a critical issue, including severity, node details, consequences, and a concrete fix. ```markdown ๐Ÿ”ด **Critical** | Node: `HTTP Request โ€“ Fetch Lead Data` **What**: No `continueOnFail` and no Error Trigger. **Why**: If HubSpot returns 503, the entire execution dies silently and the user gets no response. **Fix**: Enable "Continue On Fail" on this node AND connect an Error Trigger workflow that sends a Slack alert to `#automation-errors`. ``` -------------------------------- ### Expression Syntax Examples Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md Provides examples of using expression syntax within node parameter fields. This includes accessing webhook data, using string and date methods, referencing other nodes, conditional logic, environment variables, and JMESPath queries. ```javascript {{ $json.body.email }} {{ $json.name.toUpperCase() }} {{ $now.toFormat('yyyy-MM-dd') }} {{ $node["Set"].json.total }} {{ $if($json.score > 80, "pass", "fail") }} {{ $env.API_KEY }} {{ $jmespath($json, "items[?active]") }} {{ $execution.id }} ``` -------------------------------- ### React App Component Setup Source: https://github.com/lawwho23-stack/2b_saas/blob/main/design_handoff_2b/2B App.html Sets up the main React application, including state management for screen and sidebar, and integrates with local storage for persistence. It also handles routing to different pages based on the current screen state. ```javascript const TWEAK_DEFAULTS = /\*EDITMODE-BEGIN\*\/{"screen":"inbox","sidebar":"expanded"}/\*EDITMODE-END\*\/; const App = () => { const saved = (() => { try { return JSON.parse(localStorage.getItem('2b_proto') || '{}'); } catch { return {}; } })(); const [screen, setScreenRaw] = React.useState(saved.screen || TWEAK_DEFAULTS.screen || 'inbox'); const [sidebarCollapsed, setSidebarCollapsed] = React.useState(TWEAK_DEFAULTS.sidebar === 'collapsed'); const setScreen = s => { setScreenRaw(s); localStorage.setItem('2b_proto', JSON.stringify({ screen: s })); const el = document.getElementById('tweak-screen'); if (el) el.value = s; }; React.useEffect(() => { window.__setScreen = setScreen; window.__setSidebarCollapsed = setSidebarCollapsed; }); if (screen === 'landing') return setScreen('onboarding')} />; if (screen === 'onboarding') return setScreen('inbox')} />; const renderContent = () => { switch (screen) { case 'inbox': return ; case 'appointments': return ; case 'settings': return ; case 'billing': return ; default: return (
๐Ÿšง
{screen.charAt(0).toUpperCase()+screen.slice(1)} โ€” coming soon
); } }; return (
{renderContent()}
); }; ReactDOM.createRoot(document.getElementById('root')).render(); ``` -------------------------------- ### Scheduled Daily Report Workflow Example Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md An example of a scheduled workflow that fetches data, processes it, sends a report via email, and includes error alerting. ```plaintext 1. Schedule (daily 9 AM) 2. HTTP Request (fetch analytics) 3. Code (aggregate data) 4. Email (formatted report) 5. Error Trigger โ†’ Slack (notify on failure) ``` -------------------------------- ### Tool Calling with Vercel AI SDK Source: https://github.com/lawwho23-stack/2b_saas/blob/main/planning.md Implement agent tool-calling functionality using the Vercel AI SDK. This example shows how to define tools like `check_product` that interact with Supabase. ```typescript import { generateText, tool } from 'ai' import { openai } from '@ai-sdk/openai' const result = await generateText({ model: openai('gpt-4o-mini'), system: bot.system_prompt, messages: history, tools: { check_product: tool({ description: 'Look up a product by name. Returns price, stock, description.', parameters: z.object({ name: z.string() }), execute: async ({ name }) => { return await supabase.rpc('search_products', { bot_id, search_text: name }) }, }), list_products: tool({...}), create_order_draft: tool({...}), }, maxSteps: 5, }) ``` -------------------------------- ### Claude Code Session Initialization Source: https://github.com/lawwho23-stack/2b_saas/blob/main/design_handoff_2b/README.md Paste this at the start of your Claude Code session to provide context about the 2B project, its design handoff, and your tech stack. Replace the placeholder with your current development task. ```text I'm building 2B, a Messenger chatbot SaaS for Myanmar SMEs. Read planning.md for full context. I have a hi-fi design handoff in the design_handoff_2b/ folder. Open 2B App.html in a browser to see the interactive prototype โ€” use the Tweaks panel to switch screens. The README.md in that folder has full specs: colors, spacing, typography, component behavior, and bilingual UI patterns. My stack is Next.js 15 + TypeScript + Tailwind CSS + shadcn/ui. I'm currently working on: [DESCRIBE WHAT YOU WANT TO BUILD] Please read the README and the relevant component file (e.g. components/inbox.jsx) and implement it in the Next.js codebase following the existing file structure in planning.md. ``` -------------------------------- ### Enable Supabase Realtime for Messages Table Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Ensure Realtime is enabled for the 'messages' table by altering the publication. This should ideally be done during initial setup. ```sql ALTER PUBLICATION supabase_realtime ADD TABLE messages; ``` -------------------------------- ### Example n8n Webhook Response Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/N8N_SETUP_FINAL.md This is an example of the expected JSON response from the n8n webhook when a test message is sent. ```json { "responseBody": { "message": "Sure! I can help you book an appointment. What time works best for you?", "recipientId": "user-123" } } ``` -------------------------------- ### Project Structure Overview Source: https://github.com/lawwho23-stack/2b_saas/blob/main/planning.md Illustrates the directory structure for the project, highlighting key directories like `lib` for shared utilities and `app/api` for API routes. ```tree src/ โ”œโ”€โ”€ lib/ โ”‚ โ”œโ”€โ”€ supabase/ # service-role + anon clients (existing) โ”‚ โ”œโ”€โ”€ redis.ts # Upstash client (existing) โ”‚ โ”œโ”€โ”€ meta/ โ”‚ โ”‚ โ”œโ”€โ”€ graph-api.ts # Meta Graph: send message, get user info โ”‚ โ”‚ โ””โ”€โ”€ verify-signature.ts # HMAC SHA256 webhook verification โ”‚ โ”œโ”€โ”€ google/ โ”‚ โ”‚ โ”œโ”€โ”€ sheets.ts # Read/write Google Sheets via googleapis โ”‚ โ”‚ โ””โ”€โ”€ oauth.ts # OAuth refresh token handling โ”‚ โ”œโ”€โ”€ ai/ โ”‚ โ”‚ โ”œโ”€โ”€ agent.ts # Vercel AI SDK + tool definitions โ”‚ โ”‚ โ”œโ”€โ”€ tools/ โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ check-product.ts โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ list-products.ts โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ create-order-draft.ts โ”‚ โ”‚ โ””โ”€โ”€ intent-classifier.ts # GPT-4o-mini wrapper โ”‚ โ”œโ”€โ”€ myanmar-text.ts # Zawgyi โ†’ Unicode normalization โ”‚ โ””โ”€โ”€ pinecone.ts # Vector DB client โ””โ”€โ”€ app/api/ โ”œโ”€โ”€ messenger-webhook/route.ts # Meta posts here. Returns 200 fast, processes async โ”œโ”€โ”€ owner-reply/route.ts # Inbox UI calls when owner sends manual message โ”œโ”€โ”€ order-approve/route.ts # Inbox UI calls when owner clicks Approve โ”œโ”€โ”€ toggle-mode/route.ts # Inbox UI calls when owner flips AI/Human (existing) โ””โ”€โ”€ cron/ โ””โ”€โ”€ inventory-sync/route.ts # Vercel Cron calls every 5 min ``` -------------------------------- ### GET /api/auth/google/url + GET /api/auth/google/callback Source: https://context7.com/lawwho23-stack/2b_saas/llms.txt Handles the Google OAuth flow for connecting to Google Sheets. The '/url' endpoint generates an authorization URL with offline access to obtain a refresh token. The '/callback' endpoint exchanges the authorization code for credentials and stores them. ```APIDOC ## `GET /api/auth/google/url` + `GET /api/auth/google/callback` โ€” Google OAuth for Sheets access Two-step OAuth flow for connecting a bot to a Google Sheets inventory. The URL endpoint generates an authorization URL with `offline` access (to get a refresh token). The callback exchanges the authorization code for credentials and stores them in `channel_connections.google_sheets_creds`. ```bash # Step 1: Get the OAuth URL (redirect user to this) curl "https://yourdomain.com/api/auth/google/url?botId=uuid-of-bot" # โ†’ { "url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&scope=spreadsheets..." } # Redirect the user's browser to that URL # Step 2: Google redirects back to /api/auth/google/callback?code=...&state=botId # The callback handler: # 1. Calls exchangeCode(code) โ†’ { access_token, refresh_token, expiry_date } # 2. Stores creds in channel_connections WHERE bot_id = state # 3. Redirects to /dashboard/settings/inventory?connected=true # Error redirects: # /dashboard/settings/inventory?error=missing_code # /dashboard/settings/inventory?error=exchange_failed # /dashboard/settings/inventory?error=db_save_failed ``` ``` -------------------------------- ### Copy .env.local File Source: https://github.com/lawwho23-stack/2b_saas/blob/main/SETUP_GUIDE.md Copy the template .env.local file to your project. This file will store all your service credentials and configurations. ```bash cp .env.local .env.local ``` -------------------------------- ### Populate .env.local with Service Credentials Source: https://github.com/lawwho23-stack/2b_saas/blob/main/SETUP_GUIDE.md Fill in all the required environment variables in your .env.local file. This includes credentials for Supabase, n8n, Meta, Upstash, Anthropic, and Pinecone. ```env # Supabase NEXT_PUBLIC_SUPABASE_URL=your-project-url NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key SUPABASE_SERVICE_ROLE_KEY=your-service-key # n8n N8N_API_URL=https://your-railway-domain.up.railway.app/api N8N_API_KEY=your-n8n-api-key N8N_WEBHOOK_URL=https://your-railway-domain.up.railway.app/webhook # Meta META_VERIFY_TOKEN=your-verify-token META_APP_SECRET=your-app-secret # Upstash UPSTASH_REDIS_URL=https://your-instance.upstash.io UPSTASH_REDIS_TOKEN=your-upstash-token # Anthropic ANTHROPIC_API_KEY=your-anthropic-key # Pinecone PINECONE_API_KEY=your-pinecone-api-key PINECONE_INDEX=meeting-agent-faqs ``` -------------------------------- ### Seed Test Data in Supabase Source: https://github.com/lawwho23-stack/2b_saas/blob/main/SETUP_GUIDE.md Run these SQL queries in the Supabase SQL Editor to set up initial data, including workspaces, members, bots, and channel connections. Ensure you replace placeholders with actual IDs and tokens. ```sql -- 1. Create your user in Supabase Auth first -- 2. Get your user UUID from Auth โ†’ Users -- 3. Run these queries: -- Create workspace insert into workspaces (name, plan) values ('My First Workspace', 'trial') returning id; -- Add yourself as owner insert into workspace_members (workspace_id, user_id, role) values ('', '', 'owner'); -- Create bot insert into bots (workspace_id, name, system_prompt, pinecone_namespace) values ( '', 'Test Bot', 'You are an appointment booking assistant. Keep replies short and friendly.', 'test-bot-001' ) returning id; -- Add Facebook page connection insert into channel_connections (bot_id, fb_page_id, fb_page_name, fb_page_access_token) values ('', '', 'Your Page Name', ''); ``` -------------------------------- ### Project File Structure Overview Source: https://github.com/lawwho23-stack/2b_saas/blob/main/START_HERE.md This tree displays the directory and file structure of the 2b-saas project, highlighting key components like the app directory, lib, docs, scripts, and configuration files. ```tree 2b-saas/ โ”œโ”€โ”€ app/ โ”‚ โ”œโ”€โ”€ auth/login/page.tsx (magic link login) โ”‚ โ”œโ”€โ”€ auth/callback/page.tsx (email verification) โ”‚ โ”œโ”€โ”€ dashboard/page.tsx (inbox UI - 3 panel) โ”‚ โ””โ”€โ”€ page.tsx (redirect to login/dashboard) โ”‚ โ”œโ”€โ”€ lib/supabase/ โ”‚ โ”œโ”€โ”€ client.ts (browser client) โ”‚ โ”œโ”€โ”€ server.ts (server client) โ”‚ โ””โ”€โ”€ service.ts (service-role for n8n) โ”‚ โ”œโ”€โ”€ docs/ โ”‚ โ”œโ”€โ”€ schema-notes.md (table guide) โ”‚ โ”œโ”€โ”€ n8n-meeting-agent-supabase.json โญ (YOUR WORKFLOW) โ”‚ โ”œโ”€โ”€ N8N_SETUP_FINAL.md (detailed setup) โ”‚ โ””โ”€โ”€ QUICK_REFERENCE.md (cheat sheet) โ”‚ โ”œโ”€โ”€ scripts/ โ”‚ โ””โ”€โ”€ seed.ts (create test data) โ”‚ โ”œโ”€โ”€ supabase/migrations/ โ”‚ โ””โ”€โ”€ 001_initial_schema.sql (database schema) โ”‚ โ”œโ”€โ”€ N8N_ACTION_ITEMS.md โญ (READ THIS FIRST) โ”œโ”€โ”€ PHASE_1_GUIDE.md (supabase setup reference) โ”œโ”€โ”€ PHASE_1_CHECKLIST.md (verification checklist) โ”œโ”€โ”€ .env.local (credentials template) โ””โ”€โ”€ package.json (dependencies) ``` -------------------------------- ### Example n8n HTTP Request Configuration for Supabase Messages Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/N8N_INTEGRATION_GUIDE.md A complete JSON configuration for an n8n HTTP Request node to POST messages to the Supabase 'messages' table. ```json { "method": "POST", "url": "https://xxxxx.supabase.co/rest/v1/messages", "authentication": "none", "sendHeaders": true, "headers": { "parameters": [ { "name": "apikey", "value": "{{ $env.NEXT_PUBLIC_SUPABASE_ANON_KEY }}" }, { "name": "Authorization", "value": "Bearer {{ $env.NEXT_PUBLIC_SUPABASE_ANON_KEY }}" }, { "name": "Content-Type", "value": "application/json" } ] }, "sendBody": true, "specifyBody": "json", "jsonBody": { "conversation_id": "{{ $json.conversation_id }}", "role": "user", "content": "{{ $json.userMessage }}", "message_type": "text", "created_at": "{{ new Date().toISOString() }}" } } ``` -------------------------------- ### Project File Structure Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/QUICK_REFERENCE.md Overview of the project's directory and file organization. Useful for understanding where different modules and configurations are located. ```tree 2b-saas/ โ”œโ”€โ”€ app/ โ”‚ โ”œโ”€โ”€ auth/ โ”‚ โ”‚ โ”œโ”€โ”€ login/page.tsx (magic link form) โ”‚ โ”‚ โ””โ”€โ”€ callback/page.tsx (email verification) โ”‚ โ”œโ”€โ”€ dashboard/ โ”‚ โ”‚ โ””โ”€โ”€ page.tsx (inbox UI: 3-panel layout) โ”‚ โ””โ”€โ”€ page.tsx (root redirect) โ”œโ”€โ”€ lib/supabase/ โ”‚ โ”œโ”€โ”€ client.ts (browser) โ”‚ โ”œโ”€โ”€ server.ts (server-side) โ”‚ โ””โ”€โ”€ service.ts (n8n bypass RLS) โ”œโ”€โ”€ docs/ โ”‚ โ”œโ”€โ”€ schema-notes.md (table guide) โ”‚ โ”œโ”€โ”€ N8N_INTEGRATION_GUIDE.md (setup) โ”‚ โ”œโ”€โ”€ N8N_WORKFLOW_STEPS.md (step-by-step) โ”‚ โ”œโ”€โ”€ n8n-meeting-agent-original.json (original workflow) โ”‚ โ””โ”€โ”€ error-handler.json (error workflow) โ”œโ”€โ”€ scripts/ โ”‚ โ””โ”€โ”€ seed.ts (create test data) โ”œโ”€โ”€ supabase/migrations/ โ”‚ โ””โ”€โ”€ 001_initial_schema.sql (schema) โ”œโ”€โ”€ PHASE_1_GUIDE.md (deploy & test) โ””โ”€โ”€ PHASE_1_CHECKLIST.md (verification) ``` -------------------------------- ### Return Format for Code Nodes in JavaScript Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md All Code nodes must return an array of objects, where each object has a 'json' key containing the data. This example shows the basic structure and how to map over items. ```javascript return [{ json: { result: "success", count: 42 } }]; ``` ```javascript return items.map(item => ({ json: { ...item.json, processed: true } })); ``` -------------------------------- ### Environment Variables Reference Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md List of all environment variables required for Phase 1 and subsequent phases of the 2B SaaS project. ```env # Supabase (required for Phase 1) NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... SUPABASE_SERVICE_ROLE_KEY=eyJ... # n8n (required later, can stub for now) N8N_API_URL=http://localhost:5678/api N8N_API_KEY=xxx N8N_WEBHOOK_URL=http://localhost:5678/webhook # Meta (required for Phase 2) META_VERIFY_TOKEN=xxx META_APP_SECRET=xxx # Upstash Redis (required for Phase 3) UPSTASH_REDIS_URL=https://xxx.upstash.io UPSTASH_REDIS_TOKEN=xxx # Anthropic (required for n8n) ANTHROPIC_API_KEY=sk-ant-xxx # Pinecone (required for Phase 5) PINECONE_API_KEY=xxx PINECONE_INDEX=meeting-agent-faqs # Stripe (required for Phase 5) STRIPE_SECRET_KEY=sk_live_xxx STRIPE_PUBLISHABLE_KEY=pk_live_xxx ``` -------------------------------- ### Create Messenger Webhook Receiver Source: https://github.com/lawwho23-stack/2b_saas/blob/main/planning.md Implement the Messenger webhook receiver endpoint. This includes handling GET requests for verification and POST requests for message events, ensuring HMAC signature verification. ```typescript import { type NextRequest, NextResponse } from "next/server"; import crypto from "crypto"; const APP_SECRET = process.env.MESSENGER_APP_SECRET; export const GET = async (req: NextRequest) => { const mode = req.nextUrl.searchParams.get("hub_mode"); const token = req.nextUrl.searchParams.get("hub_verify_token"); const challenge = req.nextUrl.searchParams.get("hub_challenge"); // Replace 'YOUR_VERIFY_TOKEN' with your actual verify token const VERIFY_TOKEN = process.env.MESSENGER_VERIFY_TOKEN; if (mode && token && mode === "subscribe" && token === VERIFY_TOKEN) { console.log("Webhook verified successfully!"); return new Response(challenge, { status: 200 }); } console.error("Webhook verification failed."); return new Response("Verification failed", { status: 403 }); }; export const POST = async (req: NextRequest) => { const signature = req.headers.get("x-hub-signature-256"); const body = await req.text(); // Read body as text first for signature verification // 1. Verify HMAC SHA256 signature if (!signature || !APP_SECRET) { console.error("Missing signature or APP_SECRET"); return NextResponse.json({ error: "Bad Request" }, { status: 400 }); } const expectedSignature = crypto .createHmac("sha256", APP_SECRET) .update(body) .digest("hex"); if (signature !== `sha256=${expectedSignature}`) { console.error("Invalid signature"); return NextResponse.json({ error: "Invalid signature" }, { status: 403 }); } // 2. Parse Meta payload try { const payload = JSON.parse(body); // 3. Return 200 immediately // Process the message asynchronously if (payload.object === "page") { payload.entry.forEach(async (entry: any) => { const webhookEvent = entry.messaging[0]; // 4. Fire `void handleMessage(event)` for async processing // Assuming handleMessage is imported from './handle-message' // await handleMessage(webhookEvent); console.log("Received message event (async processing):", webhookEvent); }); return NextResponse.json({ message: "Events received" }); } } catch (error) { console.error("Error parsing payload or handling message:", error); return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); } return NextResponse.json({ message: "Received" }); }; ``` -------------------------------- ### Meta Messenger Webhook Receiver Source: https://context7.com/lawwho23-stack/2b_saas/llms.txt Handles Facebook Messenger webhook verification (GET) and incoming message events (POST). It verifies the HMAC signature and returns a 200 OK response immediately, deferring message processing to an asynchronous task. ```bash # Step 1: Facebook webhook verification (Meta calls this during setup) curl "https://yourdomain.com/api/messenger-webhook\ ?hub.mode=subscribe\ &hub.verify_token=YOUR_META_VERIFY_TOKEN\ &hub.challenge=CHALLENGE_CODE" # โ†’ Returns: CHALLENGE_CODE (plain text, 200) # Step 2: Incoming message event (Meta sends this on every customer message) curl -X POST https://yourdomain.com/api/messenger-webhook \ -H "Content-Type: application/json" \ -H "X-Hub-Signature-256: sha256=" \ -d '{ "object": "page", "entry": [{ "id": "PAGE_ID", "messaging": [{ "sender": { "id": "USER_PSID" }, "recipient": { "id": "PAGE_ID" }, "message": { "mid": "m_abc123", "text": "Hello, what products do you have?" } }] }] }' # โ†’ Response: { "status": "ok" } (200, returned before AI runs) ``` -------------------------------- ### Deploy to Vercel Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_CHECKLIST.md Commands for committing changes, pushing to the repository, and deploying the application to Vercel. Remember to set environment variables in the Vercel dashboard. ```bash # 4. Deploy to Vercel git add . git commit -m "feat: Phase 1 foundation" git push vercel deploy # 5. Set env vars in Vercel dashboard ``` -------------------------------- ### Shop System Prompt Template Source: https://github.com/lawwho23-stack/2b_saas/blob/main/shop-vertical-prompt.md This is the main system prompt for the shop's customer service assistant. Customize placeholders like {{SHOP_NAME}} and {{SHOP_DESCRIPTION}} for your specific shop. It defines the bot's persona, available tools, and rules for customer interaction. ```text You are the customer service assistant for {{SHOP_NAME}}, an online shop in Myanmar. ## About this shop {{SHOP_DESCRIPTION}} Location: {{SHOP_LOCATION}} Contact: {{SHOP_PHONE}} Delivery areas: {{DELIVERY_AREAS}} Payment methods: {{PAYMENT_METHODS}} ## Your role You help customers browse products, check prices and stock, answer questions about delivery and payment, and collect order details. You do NOT finalize orders or take payment yourself โ€” you gather what the customer wants and hand off to {{OWNER_NAME}} for confirmation. ## Tone - Warm and friendly, like a helpful shop assistant - Use Myanmar language (Unicode) by default - Switch to English only if the customer writes in English first - Use polite register (แ€…แ€ฌแ€ธ for male owners, แ€™ for female owners as appropriate) - Keep messages short โ€” Facebook Messenger is not the place for long paragraphs - Use emojis sparingly (1-2 per message max) ## What you know You have access to these tools: 1. **check_product** โ€” look up a product by name or partial name. Returns price, stock, description, image. 2. **list_products** โ€” get the full catalog, optionally filtered by category. 3. **search_faq** โ€” answer common questions (delivery time, return policy, sizing, etc.) from the shop's FAQ. When a customer asks about a product, ALWAYS use check_product first โ€” never guess at prices or stock levels. ## Critical rules **Price accuracy:** Only quote prices returned by check_product. If the tool returns no result, say "แ€กแ€ฒแ€’แ€ฎ product แ€€แ€ญแ€ฏ แ€€แ€ปแ€ฝแ€”แ€บแ€แ€ฑแ€ฌแ€บแ€แ€ญแ€ฏแ€ท แ€™แ€พแ€ฌ แ€™แ€แ€ฝแ€ฑแ€ทแ€žแ€ฑแ€ธแ€˜แ€ฐแ€ธ แ€›แ€พแ€„แ€บแ‹ Admin แ€€ แ€•แ€ผแ€”แ€บแ€†แ€€แ€บแ€žแ€ฝแ€šแ€บแ€•แ€ฑแ€ธแ€•แ€ซแ€™แ€šแ€บแ‹" Never make up prices. **Stock accuracy:** If check_product returns stock = 0, say the item is out of stock. Suggest similar products from the catalog if possible. Do not accept orders for out-of-stock items. **Ordering:** - When a customer wants to buy, collect: product name, quantity, size/color if applicable, delivery address, phone number - Confirm the total with the customer before handing off - Tell them: "{{OWNER_NAME}} แ€€ order แ€€แ€ญแ€ฏ แ€กแ€แ€Šแ€บแ€•แ€ผแ€ฏแ€•แ€ผแ€ฎแ€ธ แ€•แ€ผแ€”แ€บแ€†แ€€แ€บแ€žแ€ฝแ€šแ€บแ€•แ€ฑแ€ธแ€•แ€ซแ€™แ€šแ€บ แ€›แ€พแ€„แ€บแ‹" - Do NOT say the order is confirmed โ€” only the owner can do that **When you don't know:** - Questions about custom requests, wholesale pricing, very specific complaints โ†’ say you'll hand off to the owner - Use this exact phrase: "แ€’แ€ฎแ€™แ€ฑแ€ธแ€แ€ฝแ€”แ€บแ€ธแ€€แ€ญแ€ฏ Admin แ€€ แ€•แ€ญแ€ฏแ€•แ€ผแ€ฎแ€ธแ€€แ€ฑแ€ฌแ€„แ€บแ€ธแ€€แ€ฑแ€ฌแ€„แ€บแ€ธ แ€–แ€ผแ€ฑแ€•แ€ฑแ€ธแ€”แ€ญแ€ฏแ€„แ€บแ€•แ€ซแ€แ€šแ€บแ‹ แ€แ€แ€œแ€ฑแ€ฌแ€€แ€บ แ€…แ€ฑแ€ฌแ€„แ€ทแ€บแ€•แ€ฑแ€ธแ€•แ€ซแ‹" **What NOT to do:** - Never promise discounts or price changes - Never confirm delivery times beyond what's in {{DELIVERY_AREAS}} - Never share other customers' information - Never accept payment or give bank/wallet details (only the owner handles payment) - Never engage with off-topic conversations (politics, relationships, etc.) โ€” politely redirect: "แ€’แ€ฎแ€™แ€พแ€ฌแ€แ€ฑแ€ฌแ€ท shopping แ€กแ€€แ€ผแ€ฑแ€ฌแ€„แ€บแ€ธแ€•แ€ฒ แ€€แ€ฐแ€Šแ€ฎแ€”แ€ญแ€ฏแ€„แ€บแ€•แ€ซแ€แ€šแ€บ แ€›แ€พแ€„แ€บแ‹" ## Example conversations **Customer:** แ€™แ€„แ€บแ€นแ€‚แ€œแ€ฌแ€•แ€ซ **You:** แ€™แ€„แ€บแ€นแ€‚แ€œแ€ฌแ€•แ€ซแ€›แ€พแ€„แ€บ ๐ŸŒธ {{SHOP_NAME}} แ€€แ€ญแ€ฏ แ€แ€„แ€บแ€œแ€Šแ€บแ€แ€ฌ แ€€แ€ปแ€ฑแ€ธแ€‡แ€ฐแ€ธแ€แ€„แ€บแ€•แ€ซแ€แ€šแ€บแ‹ แ€˜แ€ฌแ€กแ€€แ€ฐแ€กแ€Šแ€ฎแ€œแ€ญแ€ฏแ€•แ€ซแ€žแ€œแ€ฒแ€›แ€พแ€„แ€บ? **Customer:** Body lotion แ€›แ€พแ€ญแ€œแ€ฌแ€ธ? **You:** (use check_product with "body lotion") โ†’ แ€›แ€พแ€ญแ€•แ€ซแ€แ€šแ€บแ€›แ€พแ€„แ€บ ๐ŸŒฟ Cerave Moisturizing Lotion 473ml แ€€แ€ญแ€ฏ 32,000 MMK แ€”แ€ฒแ€ท แ€›แ€•แ€ซแ€แ€šแ€บแ‹ Stock แ€œแ€Šแ€บแ€ธ แ€›แ€พแ€ญแ€•แ€ซแ€แ€šแ€บแ‹ แ€™แ€พแ€ฌแ€šแ€ฐแ€แ€ปแ€„แ€บแ€•แ€ซแ€žแ€œแ€ฌแ€ธ? **Customer:** แ€’แ€ฎแ€กแ€›แ€ฑแ€ฌแ€„แ€บแ€€ แ€˜แ€šแ€บแ€œแ€ฑแ€ฌแ€€แ€บแ€œแ€ฒ? **You:** (use check_product with the referenced item) โ†’ ... price from tool ... **Customer:** Delivery แ€˜แ€šแ€บแ€œแ€ฑแ€ฌแ€€แ€บแ€€แ€ผแ€ฌแ€œแ€ฒ แ€›แ€”แ€บแ€€แ€ฏแ€”แ€บแ€กแ€แ€ฝแ€„แ€บแ€ธ? **You:** แ€›แ€”แ€บแ€€แ€ฏแ€”แ€บแ€™แ€ผแ€ญแ€ฏแ€ทแ€แ€ฝแ€„แ€บแ€ธ 1-2 แ€›แ€€แ€บแ€กแ€แ€ฝแ€„แ€บแ€ธ แ€•แ€ญแ€ฏแ€ทแ€•แ€ฑแ€ธแ€•แ€ซแ€แ€šแ€บแ€›แ€พแ€„แ€บแ‹ Delivery fee 3,000 MMK แ€•แ€ซแ‹ **Customer:** 2 แ€แ€ฏ แ€šแ€ฐแ€™แ€šแ€บแŠ แ€›แ€”แ€บแ€€แ€ฏแ€”แ€บ แ€แ€ฌแ€™แ€ฝแ€ฑแŠ แ€–แ€ฏแ€”แ€บแ€ธ 09xxx **You:** แ€™แ€พแ€แ€บแ€œแ€ญแ€ฏแ€€แ€บแ€•แ€ผแ€ฎแ€›แ€พแ€„แ€บ ๐Ÿ“ - Cerave Moisturizing Lotion ร— 2 = 64,000 MMK - Delivery (แ€›แ€”แ€บแ€€แ€ฏแ€”แ€บแ€แ€ฝแ€„แ€บแ€ธ) = 3,000 MMK - Total = 67,000 MMK - แ€œแ€ญแ€•แ€บแ€…แ€ฌ: แ€แ€ฌแ€™แ€ฝแ€ฑ, แ€›แ€”แ€บแ€€แ€ฏแ€”แ€บ - แ€–แ€ฏแ€”แ€บแ€ธ: 09xxx {{OWNER_NAME}} แ€€ order แ€€แ€ญแ€ฏ แ€กแ€แ€Šแ€บแ€•แ€ผแ€ฏแ€•แ€ผแ€ฎแ€ธ แ€•แ€ผแ€”แ€บแ€†แ€€แ€บแ€žแ€ฝแ€šแ€บแ€•แ€ฑแ€ธแ€•แ€ซแ€™แ€šแ€บแ€›แ€พแ€„แ€บ ๐Ÿ™ ## Handoff triggers (set mode to human automatically if possible) These situations should flag the conversation for owner attention: - Customer explicitly asks to speak to the owner ("Admin แ€€แ€ญแ€ฏ แ€•แ€ผแ€ฑแ€ฌแ€แ€ปแ€„แ€บแ€แ€šแ€บ", "แ€œแ€ฐแ€€แ€ญแ€ฏแ€šแ€บแ€แ€ญแ€ฏแ€„แ€บแ€•แ€ผแ€ฑแ€ฌแ€แ€ปแ€„แ€บ") - Customer has a complaint or return request - Custom/bulk order request - Technical question you can't answer from FAQ - Customer seems frustrated (uses words like แ€…แ€ญแ€แ€บแ€•แ€ปแ€€แ€บ, แ€แ€ญแ€ฏแ€„แ€บแ€€แ€ผแ€ฌแ€ธแ€™แ€šแ€บ, แ€”แ€ฑแ€ฌแ€บแ€€แ€ญแ€แ€บ) Do not flip the mode yourself. Just respond with the handoff phrase and let the owner see the conversation in their inbox. ``` -------------------------------- ### Accessing Data in Python Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md Shows how to access various data sources in Python, including all items, the first item, the current item, specific node data, webhook bodies, and environment variables. ```python items = _input.all() # All items first = _input.first() # First item current = _input.item # Current item (Each Item mode) data = _node["HTTP Request"]["json"] # Specific node email = _json["body"]["email"] # Webhook body (CRITICAL: nested under body) ``` -------------------------------- ### Accessing Data in JavaScript Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md Demonstrates how to access different data sources in JavaScript, including all items, the first item, the current item, specific node data, webhook bodies, and environment variables. ```javascript const items = $input.all(); // All items const first = $input.first(); // First item const current = $input.item; // Current item (Each Item mode) const data = $node["HTTP Request"].json; // Specific node const email = $json.body.email; // Webhook body (CRITICAL: nested under body) const apiKey = $env.API_KEY; // Environment variable ``` -------------------------------- ### Seed Test Data into Supabase Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Populate the Supabase database with initial test data using the provided script. ```bash npx ts-node scripts/seed.ts ``` -------------------------------- ### Common Gotchas and Solutions Source: https://github.com/lawwho23-stack/2b_saas/blob/main/app/dashboard/SKILL.md A table summarizing common problems encountered when using the platform and their corresponding solutions. This includes issues with webhook payload access, item processing modes, API authentication, execution order, expression formatting, and sub-workflow publishing. ```text | Problem | Solution | |---|---| | Can't access webhook payload | Data is under `$json.body` โ€” always | | Node processes all items, I want one | Use "Execute Once" mode or `$json[0].field` | | API calls failing with 401/403 | Configure credentials in the Credentials section, not parameters | | Nodes executing in unexpected order | Check Settings โ†’ Execution Order (use v1: connection-based) | | Expressions showing as literal text | Wrap in `{{ }}` | | Sub-workflow not picking up changes | You must **publish** the sub-workflow โ€” drafts aren't referenced | ``` -------------------------------- ### Commit and Push Changes Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Use these Git commands to stage all changes, commit them with a descriptive message, and push to the main branch. ```bash git add . git commit -m "feat: Phase 1 foundation โ€” auth, schema, dashboard" git push origin main ``` -------------------------------- ### Environment Variables Configuration Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/QUICK_REFERENCE.md Configuration for Supabase and n8n Cloud credentials and URLs. Ensure these are set in your .env.local file for development. ```env # PHASE 1 (Required) NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... SUPABASE_SERVICE_ROLE_KEY=eyJ... # PHASE 2+ (For n8n) N8N_API_URL=https://your-instance.app.n8n.cloud/api/v1 N8N_API_KEY=xxx N8N_WEBHOOK_URL=https://your-instance.app.n8n.cloud/webhook/meeting-agent ANTHROPIC_API_KEY=sk-ant-xxx ``` -------------------------------- ### AI Tool: Look up product by name Source: https://context7.com/lawwho23-stack/2b_saas/llms.txt Performs a case-insensitive search on the products table. Returns up to 3 matching products or 'Product not found.' ```typescript import { checkProductTool } from '@/lib/ai/tools/check-product' import { generateText, tool } from 'ai' // Used inside runAgent โ€” shown here for direct testing const result = await generateText({ model: openrouter('deepseek/deepseek-v4-flash'), system: 'You are a shop bot.', messages: [{ role: 'user', content: 'How much is the face cream?' }], tools: { check_product: checkProductTool('bot-uuid-here'), }, maxSteps: 3, }) // Tool execute receives: { name: "face cream" } // Queries: SELECT id, name, description, price, stock, category, sku // FROM products WHERE bot_id = ? AND is_active = true // AND name ILIKE '%face cream%' LIMIT 3 // Returns: [{ id: "...", name: "Whitening Face Cream", price: 8500, stock: 12, ... }] ``` -------------------------------- ### Create AI Agent Tools Source: https://github.com/lawwho23-stack/2b_saas/blob/main/planning.md Define tools for the AI agent to interact with the system. These tools allow the agent to perform actions like checking product availability and listing products. ```typescript import { z } from "zod"; import { db } from "@/lib/db"; import { products } from "@/lib/schema"; import { asc, ilike } from "drizzle-orm"; export const checkProduct = { description: "Check the stock availability of a product.", parameters: z.object({ name: z.string().describe("The name of the product to check."), }), execute: async ({ name }): Promise<{ stock: number | null; available: boolean } | null> => { const product = await db.query.products.findFirst({ where: ilike(products.name, `%${name}%`), columns: { stock: true }, }); if (!product) { return { stock: null, available: false }; } return { stock: product.stock, available: (product.stock ?? 0) > 0 }; }, }; export const listProducts = { description: "List available products. Optionally filter by name.", parameters: z.object({ name: z.string().optional().describe("Optional name to filter products by."), }), execute: async ({ name }): Promise<{ id: string; name: string; price: number; stock: number | null }[]> => { const query = db.select({ id: products.id, name: products.name, price: products.price, stock: products.stock, }).from(products); if (name) { query.where(ilike(products.name, `%${name}%`)); } const productList = await query.orderBy(asc(products.name)); return productList; }, }; // Add other tools like createOrderDraft here ``` -------------------------------- ### Deploy to Vercel Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Deploy the project to Vercel after committing and pushing changes. Remember to set environment variables in the Vercel dashboard. ```bash vercel deploy ``` -------------------------------- ### Supabase Migration for Pending Jobs Table Source: https://github.com/lawwho23-stack/2b_saas/blob/main/planning.md SQL migration script to create the 'pending_jobs' table and a 'decrement_product_stock' RPC function. ```sql CREATE TABLE pending_jobs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), job_type TEXT NOT NULL, payload JSONB NOT NULL, created_at TIMESTAMPTZ DEFAULT NOW(), processed_at TIMESTAMPTZ ); CREATE OR REPLACE FUNCTION decrement_product_stock(p_product_id TEXT, p_quantity INT) RETURNS VOID AS $$ BEGIN UPDATE products SET stock = stock - p_quantity WHERE id = p_product_id; END; $$ LANGUAGE plpgsql; ``` -------------------------------- ### Set Environment Variables for Supabase Source: https://github.com/lawwho23-stack/2b_saas/blob/main/docs/N8N_SETUP_FINAL.md Add your Supabase project URL and anon public key to your .env.local file. These are required for Supabase integration. ```env NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... ``` -------------------------------- ### Update .env.local with Supabase Credentials Source: https://github.com/lawwho23-stack/2b_saas/blob/main/PHASE_1_GUIDE.md Configure your local environment variables with Supabase project URL and API keys. ```env NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ... SUPABASE_SERVICE_ROLE_KEY=eyJ... ``` -------------------------------- ### Core Feature: Mode System Explanation Source: https://github.com/lawwho23-stack/2b_saas/blob/main/START_HERE.md Illustrates the two modes ('ai' and 'human') for conversations, explaining how the bot responds or accepts owner input and how changes to the conversation mode are managed. ```text Every conversation has a MODE: 'ai' โ†’ Bot responds, input DISABLED 'human' โ†’ Owner responds, input ACTIVE Owner toggles in dashboard โ†’ updates `conversations.mode` โ†’ n8n reads it ```