Skip to content

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.


  • Route: Use the existing Home route (/appapp._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.1 Top: Banners (contextual, one at a time or stacked)

Section titled “2.1 Top: Banners (contextual, one at a time or stacked)”
ConditionBanner typeMessage / CTA
Free plan + replies used ≥ 80% of capWarning”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 ≤ thresholdWarning”Your AI credit balance is $X.XX. Add credits so chat keeps working.” → Buy credits
Paid plan + balance healthySuccess (optional, dismissible)“Credit balance: $X.XX. Each reply uses a variable amount; buy more on Billing when needed.”
Widget disabledWarning”Chat widget is turned off. Customers won’t see the chat. Turn it on in Settings.”
No knowledge / no chunksInfo”Your AI has no product or website knowledge yet. Sync Data Sync and add Knowledge so replies are helpful.”
First-time / no chats yetInfo”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.


Data comes from existing DB and loaders; no new tables. All scoped by current shop.

CardTitleContentData source
Plan & creditsPlan & creditsFree: “X of 50 replies used this month” + progress bar. Paid: “Credit balance: $X.XX” (from shops.credit_balance).Shop: plan, creditBalance, freeCreditLimit, freeCreditsUsed
Chat activityChat activity (last 30 days)Sessions: N. Messages (replies): M.ChatSession.count, ChatMessage.count where role = 'assistant', createdAt >= 30 days ago
AI usage costAI 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 & dataKnowledge & dataProducts: 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):

StateShown items
Widget disabled1. Turn on chat widget in Settings.
No products synced2. Sync products in Data Sync so the AI can answer product questions.
No website knowledge3. Add website knowledge in Knowledge for better answers.
Free, high usage4. Upgrade to paid to avoid hitting the reply limit.
Paid, low balance5. 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).


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.


File: app/routes/app._index.jsx (or the route that serves /app).

Loader:

  1. Authenticate with authenticate.admin(request); get session.shop.
  2. Resolve shop:
    db.shop.findFirst({ where: { shopDomain: session.shop }, select: { id, plan, creditBalance, freeCreditLimit, freeCreditsUsed, widgetEnabled, websiteKnowledge } }).
  3. If no shop: return minimal payload (e.g. { plan: 'free', dashboard: null }) and render a generic “Welcome” or “Shop not found” state.
  4. 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 } }).
  5. 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. repliesUsedPct for free plan).

Use the same date window as Billing (e.g. last 30 days) so numbers are consistent.


  • Page: title="Dashboard" (or “Home”); no primary action or a single “Open Billing” if you want.
  • Banners: Use Polaris Banner at the top. One banner per condition; order by priority. Use tone: warning for upgrade / low balance / widget off, info for setup/first-time.
  • Cards: Use Polaris Card for Plan & credits, Chat activity, AI usage, Knowledge & data. Inside each card: Text for title, key number, optional ProgressBar for free reply usage, and a Link to the related page.
  • Next steps: A Card with title “Next steps” or “Get started”, and a BlockStack of Link + short text.
  • Quick links: Optional Card or InlineStack of Link components.

Keep the layout simple: Banners → Summary cards → Next steps → Quick links.


  • Upgrade (free): plan === 'free' and (optional) repliesUsed / freeRepliesLimit >= 0.8 → show upgrade banner.
  • Low balance (paid): plan === 'paid' and creditBalanceDollars <= threshold (e.g. 2.0 or from minBalanceForAlertCents / 100) → show “Buy credits” banner.
  • Widget disabled: widgetEnabled === false → show “Turn on widget” banner.
  • No knowledge: chunkCount === 0 or no websiteKnowledge (and no products) → show “Add knowledge” / “Sync data” banner.
  • First-time: repliesLast30 === 0 and sessionsLast30 === 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.


  • 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).

ItemFileAction
Dashboard routeapp/routes/app._index.jsxReplace loader and default component: load dashboard data, render banners, summary cards, next steps, quick links. Remove template product/metaobject actions and UI.
Nav labelapp/routes/app.jsxOptionally 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.


  • 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.

  • 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.