Dashboard Plan — AppiFire AI Chat
This document is the plan for the merchant Dashboard (Home screen) of AppiFire AI Chat. It replaces the template “Home” with an insightful, handholding overview and clear calls to action.
Prerequisites: Phases 1–5 (RAG, chat API, settings, billing) and existing routes: Settings, Billing, AI Chats, Data Sync, Knowledge.
1. Objective
Section titled “1. Objective”- Route: Use the existing Home route (
/app→app._index.jsx) as the Dashboard. - Purpose: Give merchants a single place to see status, usage, and next steps. Surface upgrade and setup prompts so they know what to do next.
- Tone: Insightful (real numbers from their shop), handholding (clear actions and links), and concise (no template demos).
2. What to Show on the Dashboard
Section titled “2. What to Show on the Dashboard”2.1 Top: Banners (contextual, one at a time or stacked)
Section titled “2.1 Top: Banners (contextual, one at a time or stacked)”| Condition | Banner type | Message / CTA |
|---|---|---|
| Free plan + replies used ≥ 80% of cap | Warning | ”You’ve used X of 50 free replies this month. Upgrade to the paid plan for a credit balance and no reply cap.” → Link: Upgrade to paid |
| Free plan + replies used < 80% | Info (optional) | “You’re on the Free plan (X of 50 replies used). Need more? Upgrade for $20/mo and buy credits as you go.” → Upgrade |
| Paid plan + credit balance ≤ threshold | Warning | ”Your AI credit balance is $X.XX. Add credits so chat keeps working.” → Buy credits |
| Paid plan + balance healthy | Success (optional, dismissible) | “Credit balance: $X.XX. Each reply uses a variable amount; buy more on Billing when needed.” |
| Widget disabled | Warning | ”Chat widget is turned off. Customers won’t see the chat. Turn it on in Settings.” |
| No knowledge / no chunks | Info | ”Your AI has no product or website knowledge yet. Sync Data Sync and add Knowledge so replies are helpful.” |
| First-time / no chats yet | Info | ”No chats yet. Enable the widget in Settings and add knowledge; customers will see the chat on your storefront.” |
Priority order for multiple banners: Upgrade (free → paid) or low balance (paid) first, then widget disabled, then no knowledge, then generic first-time.
2.2 Summary cards (at-a-glance metrics)
Section titled “2.2 Summary cards (at-a-glance metrics)”Data comes from existing DB and loaders; no new tables. All scoped by current shop.
| Card | Title | Content | Data source |
|---|---|---|---|
| Plan & credits | Plan & credits | Free: “X of 50 replies used this month” + progress bar. Paid: “Credit balance: $X.XX” (from shops.credit_balance). | Shop: plan, creditBalance, freeCreditLimit, freeCreditsUsed |
| Chat activity | Chat activity (last 30 days) | Sessions: N. Messages (replies): M. | ChatSession.count, ChatMessage.count where role = 'assistant', createdAt >= 30 days ago |
| AI usage cost | AI usage (last 30 days) | N API calls. Total charged: $X.XX. (Optional: tokens.) | OpenRouterCall aggregate: _count, _sum(chargedCost) for shopId and createdAt >= 30 days ago (same as Billing page) |
| Knowledge & data | Knowledge & data | Products: P. Chunks: C. Last product sync: date or “Never”. Optional: “Website knowledge: Yes / No”. | Product.count, KnowledgeChunk.count, ShopSyncState for resourceType = 'products', Shop.websiteKnowledge (non-empty = Yes) |
Layout: 2×2 grid on desktop; stack on small screens. Each card links to the relevant page (Billing, AI Chats, Data Sync, Knowledge).
2.3 Handholding: “Next steps” or “Get started”
Section titled “2.3 Handholding: “Next steps” or “Get started””A short list of actions based on current state (not all at once):
| State | Shown items |
|---|---|
| Widget disabled | 1. Turn on chat widget in Settings. |
| No products synced | 2. Sync products in Data Sync so the AI can answer product questions. |
| No website knowledge | 3. Add website knowledge in Knowledge for better answers. |
| Free, high usage | 4. Upgrade to paid to avoid hitting the reply limit. |
| Paid, low balance | 5. Buy credits to keep chat running. |
| All set | ”You’re all set. View AI Chats to see conversations, or Billing to manage your plan.” |
Show at most 3–5 items; prefer the most impactful (widget, sync, knowledge, upgrade, buy credits).
2.4 Quick links (optional)
Section titled “2.4 Quick links (optional)”A small “Quick links” or “Go to” section: Settings, Billing, AI Chats, Data Sync, Knowledge. Reuses existing nav but gives a clear “dashboard → detail” flow.
3. Data to Load in the Dashboard Loader
Section titled “3. Data to Load in the Dashboard Loader”File: app/routes/app._index.jsx (or the route that serves /app).
Loader:
- Authenticate with
authenticate.admin(request); getsession.shop. - Resolve shop:
db.shop.findFirst({ where: { shopDomain: session.shop }, select: { id, plan, creditBalance, freeCreditLimit, freeCreditsUsed, widgetEnabled, websiteKnowledge } }). - If no shop: return minimal payload (e.g.
{ plan: 'free', dashboard: null }) and render a generic “Welcome” or “Shop not found” state. - Aggregates (all for
shopId = shop.id):- Sessions (last 30 days):
db.chatSession.count({ where: { shopId, startedAt: { gte: thirtyDaysAgo } } }). - Replies (last 30 days):
db.chatMessage.count({ where: { role: 'assistant', session: { shopId }, createdAt: { gte: thirtyDaysAgo } } }). - OpenRouter usage (last 30 days):
db.openRouterCall.aggregate({ where: { shopId, createdAt: { gte: thirtyDaysAgo } }, _count: { id: true }, _sum: { chargedCost: true, tokens: true } }). - Data counts:
db.product.count,db.knowledgeChunk.count. - Last product sync:
db.shopSyncState.findFirst({ where: { shopId, resourceType: 'products' }, select: { lastSyncedAt } }).
- Sessions (last 30 days):
- Return:
{ shop, plan, creditBalanceDollars, freeRepliesUsed, freeRepliesLimit, sessionsLast30, repliesLast30, usageLast30: { totalCalls, chargedCost, tokens }, productCount, chunkCount, lastProductSyncAt, widgetEnabled, hasWebsiteKnowledge }
plus any fields needed for banners (e.g.repliesUsedPctfor free plan).
Use the same date window as Billing (e.g. last 30 days) so numbers are consistent.
4. UI Structure (Polaris)
Section titled “4. UI Structure (Polaris)”- Page:
title="Dashboard"(or “Home”); no primary action or a single “Open Billing” if you want. - Banners: Use Polaris
Bannerat the top. One banner per condition; order by priority. Usetone:warningfor upgrade / low balance / widget off,infofor setup/first-time. - Cards: Use Polaris
Cardfor Plan & credits, Chat activity, AI usage, Knowledge & data. Inside each card:Textfor title, key number, optionalProgressBarfor free reply usage, and aLinkto the related page. - Next steps: A
Cardwith title “Next steps” or “Get started”, and aBlockStackofLink+ short text. - Quick links: Optional
CardorInlineStackofLinkcomponents.
Keep the layout simple: Banners → Summary cards → Next steps → Quick links.
5. Banner Logic (summary)
Section titled “5. Banner Logic (summary)”- Upgrade (free):
plan === 'free'and (optional)repliesUsed / freeRepliesLimit >= 0.8→ show upgrade banner. - Low balance (paid):
plan === 'paid'andcreditBalanceDollars <= threshold(e.g. 2.0 or fromminBalanceForAlertCents / 100) → show “Buy credits” banner. - Widget disabled:
widgetEnabled === false→ show “Turn on widget” banner. - No knowledge:
chunkCount === 0or nowebsiteKnowledge(and no products) → show “Add knowledge” / “Sync data” banner. - First-time:
repliesLast30 === 0andsessionsLast30 === 0→ optional “No chats yet” info banner.
Avoid showing too many banners at once; 1–2 is enough. Prefer: upgrade or low balance > widget off > knowledge/setup.
6. What Not to Show
Section titled “6. What Not to Show”- Template content: Remove “Generate a product”, “productCreate mutation”, “Next steps” (template links). The Dashboard is app-specific.
- Raw API demos: No GraphQL JSON dumps or metaobject examples on the Dashboard.
- Duplicate Billing details: Keep subscription and one-time charge history on Billing; Dashboard only shows high-level plan and balance (and link to Billing).
7. Files to Create or Change
Section titled “7. Files to Create or Change”| Item | File | Action |
|---|---|---|
| Dashboard route | app/routes/app._index.jsx | Replace loader and default component: load dashboard data, render banners, summary cards, next steps, quick links. Remove template product/metaobject actions and UI. |
| Nav label | app/routes/app.jsx | Optionally change the nav link text from “Home” to “Dashboard” and keep href="/app". |
No new routes. No new Prisma models or migrations; use existing Shop, ChatSession, ChatMessage, OpenRouterCall, Product, KnowledgeChunk, ShopSyncState.
8. Checklist
Section titled “8. Checklist”- Dashboard loader: authenticate, resolve shop, compute 30-day aggregates (sessions, replies, OpenRouter usage), product/chunk counts, last product sync, widget and knowledge flags.
- Banners: upgrade (free), low balance (paid), widget disabled, no knowledge, first-time (optional); priority order; links to Billing/Settings/Data Sync/Knowledge.
- Summary cards: Plan & credits (free: X of Y replies + progress; paid: $ balance), Chat activity (sessions, replies), AI usage (calls, charged cost), Knowledge & data (products, chunks, last sync, website knowledge).
- Next steps / Get started: conditional list (widget, sync, knowledge, upgrade, buy credits, or “all set”) with links.
- Quick links (optional): Settings, Billing, AI Chats, Data Sync, Knowledge.
- Remove template content from
app._index.jsx(product create, metaobject, template specs). - Nav: “Home” → “Dashboard” (optional).
- Empty/error state when shop not found or no data.
9. Optional Later Enhancements
Section titled “9. Optional Later Enhancements”- Date range selector: Last 7 / 30 / 90 days for usage and chat activity.
- Sparkline or mini chart: Replies or cost over last 7 days (would require daily aggregates or client-side grouping).
- “Recent chats” preview: Last 3–5 sessions with first message and date; link to AI Chats.
- Dismissible banners: Store “dismissed until X” in shop or localStorage so repeat visitors aren’t nagged.
This plan keeps the Dashboard focused on insight (real metrics), handholding (clear next steps and CTAs), and upgrade/billing (banners and links to Billing) without duplicating full Billing or Data Sync flows.