> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getkardy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dashboard and reporting

> Filter recorded visits, reward claims and outlet performance by date.

export const FeatureIllustration = ({type}) => {
  const FeatureIcon = ({name = "coffee"}) => {
    const paths = {
      coffee: "M4 8h12v7a5 5 0 0 1-5 5H9a5 5 0 0 1-5-5Z M16 9h2a3 3 0 0 1 0 6h-2 M7 3v2m4-3v3m4-2v2",
      check: "m5 12 4 4L19 6",
      arrow: "M4 12h16m-6-6 6 6-6 6",
      people: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2m20 0v-2a4 4 0 0 0-3-3.9 M9 3a4 4 0 1 0 0 8 4 4 0 0 0 0-8m8 0a4 4 0 0 1 0 8",
      pin: "M20 10c0 6-8 12-8 12S4 16 4 10a8 8 0 1 1 16 0Z M15 10a3 3 0 1 1-6 0 3 3 0 0 1 6 0",
      wallet: "M3 6h16v14H3V6Zm0 0 13-3v3m-2 6h7v5h-7v-5Z",
      mail: "M3 5h18v14H3V5Zm0 0 9 8 9-8",
      plug: "M8 3v5m8-5v5M6 8h12v5a6 6 0 0 1-12 0V8Zm6 11v3",
      gift: "M3 8h18v4H3V8Zm2 4v9h14v-9M12 8v13m0-13H8a3 3 0 1 1 3-3l1 3Zm0 0h4a3 3 0 1 0-3-3l-1 3Z",
      search: "M16 10a6 6 0 1 1-12 0 6 6 0 0 1 12 0Zm-1 5 6 6",
      lock: "M5 10h14v11H5V10Zm3 0V6a4 4 0 0 1 8 0v4m-4 5v2",
      sliders: "M4 6h16M4 12h16M4 18h16M8 3v6m8 0v6m-6 0v6"
    };
    return <svg className="bf-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
        <path d={paths[name] || paths.coffee} />
      </svg>;
  };
  const FeatureBrand = ({name = "sunday-coffee"}) => <img className="bf-brand" src={`/images/landing/${name}-wordmark.svg`} alt="" />;
  const FeatureAvatar = ({name, green = false}) => <span className={green ? "bf-avatar bf-avatar-green" : "bf-avatar"}>
      {name.slice(0, 1)}
    </span>;
  const FeatureRow = ({title, detail, end, icon}) => <div className="bf-row">
      {icon && <FeatureIcon name={icon} />}
      <div>
        <b>{title}</b>
        {detail && <small>{detail}</small>}
      </div>
      {end && <span className="bf-row-end">{end}</span>}
    </div>;
  const FeatureField = ({label, value}) => <div className="bf-field">
      <small>{label}</small>
      <div>{value}</div>
    </div>;
  const FeaturePill = ({children}) => <span className="bf-pill">{children}</span>;
  const FeaturePanel = ({title, subtitle, children}) => <div className="bf-panel">
      {title && <div className="bf-panel-title">
          <b>{title}</b>
          {subtitle && <small>{subtitle}</small>}
        </div>}
      {children}
    </div>;
  const FeatureCard = ({full = false}) => <div className="bf-pass">
      <div className="bf-pass-top">
        <FeatureBrand />
        <span>
          <small>STAMPS</small>
          <b>
            {full ? "8" : "5"}
            <small> / 8</small>
          </b>
        </span>
      </div>
      <div className="bf-pass-body">
        <b>Coffee</b>
        <div className="bf-stamps">
          {Array.from({
    length: 8
  }, (_, i) => <i key={i} className={i < (full ? 8 : 5) ? "bf-stamped" : ""} />)}
        </div>
      </div>
      <div className="bf-pass-foot">
        <span>
          <small>MEMBER</small>Amelia
        </span>
        <span>
          <small>REWARD</small>A coffee, on us
        </span>
      </div>
    </div>;
  const FeatureBranches = ({children}) => <>
      <svg className="bf-wires" viewBox="0 0 480 46" preserveAspectRatio="none">
        <path d="M240 0V46M240 0v10q0 13-13 13H80q-13 0-13 13v10M240 0v10q0 13 13 13h147q13 0 13 13v10" />
      </svg>
      <div className="bf-branches">{children}</div>
    </>;
  const FeaturePerson = ({name, detail, green}) => <div className="bf-person">
      <FeatureAvatar name={name} green={green} />
      <div>
        <b>{name}</b>
        <small>{detail}</small>
      </div>
    </div>;
  const FeaturePhone = ({children}) => <div className="bf-phone">
      <div className="bf-phone-status">
        <span>9:41</span>
        <i />
        <span>•••</span>
      </div>
      <div className="bf-phone-content">{children}</div>
      <div className="bf-home-bar" />
    </div>;
  const featureSceneCopy = {
    "branded-cards": ["sliders", "Branded cards", "Your brand.", "In their wallet."],
    rewards: ["gift", "Stamps & rewards", "Make every stamp", "worth coming back for."],
    scanning: ["search", "Scan & redeem", "One identity.", "One confirmed action."],
    referrals: ["people", "Referral programme", "Bring a friend.", "Both get rewarded."],
    "qr-signs": ["pin", "QR signs", "At your counter.", "Into their wallet."],
    "join-pages": ["people", "Customer join pages", "Your next regular", "starts here."],
    "browser-wallet": ["wallet", "Browser wallet", "Open in a browser.", "Keep on the home screen."],
    "native-wallets": ["wallet", "Native wallet passes", "Another way", "to keep your card close."],
    "kardy-network": ["search", "The Kardy network", "Get discovered.", "Become their usual."],
    "email-preferences": ["mail", "Email preferences", "Their inbox.", "Their choice."],
    members: ["people", "Members", "Know your regulars.", "See their progress."],
    analytics: ["sliders", "Reporting", "Your programme.", "At a glance."],
    outlets: ["pin", "Outlets", "Different neighbourhoods.", "One programme."],
    "team-access": ["people", "Team access", "Your team.", "The right access."],
    "multiple-brands": ["people", "Multiple brands", "Your brands.", "One merchant account."],
    broadcasts: ["mail", "Broadcasts", "A little news.", "Another visit."],
    "merchant-mcp": ["plug", "Merchant MCP", "Your favourite agent.", "Meet your workspace."],
    "usage-limits": ["sliders", "Usage & limits", "Room to grow.", "Clear boundaries."]
  };
  const FeatureScene = ({type}) => {
    if (type === "branded-cards" || type === "rewards") return <div className="bf-pair">
          <FeaturePanel title={type === "rewards" ? "Your reward" : "Card design"}>
            <FeatureField label={type === "rewards" ? "Reward" : "Business name"} value={type === "rewards" ? "A coffee, on us" : "Sunday Coffee"} />
            {type === "rewards" ? <>
                <FeatureField label="Stamps to unlock" value="8 stamps" />
                <FeatureRow title="Redeem at" detail="Orchard outlet" icon="pin" />
              </> : <>
                <small className="bf-label">Brand colour</small>
                <div className="bf-swatches">
                  {["#ca1c67", "#e5b8c9", "#dbe5ce", "#171a18"].map((color, i) => <span key={color} style={{
      background: color
    }}>
                        {i === 0 && <FeatureIcon name="check" />}
                      </span>)}
                </div>
                <FeatureRow title="Saved design" detail="Gradient · round stamps" icon="sliders" />
              </>}
          </FeaturePanel>
          <div className="bf-card-wrap">
            <small className="bf-label">MEMBER CARD PREVIEW</small>
            <FeatureCard />
          </div>
        </div>;
    if (type === "referrals") return <>
          <div className="bf-pair">
            <FeaturePanel>
              <FeaturePerson name="Jamie" detail="Your conversation" />
              <div className="bf-chat">
                Coffee at my usual spot? Use my invite—we both get bonus stamps
                after your first purchase.
              </div>
              <div className="bf-invite">
                <FeatureBrand />
                <FeatureRow title="Join with Amelia’s invite" end="↗" />
              </div>
              <small className="bf-receipt">Sent by Amelia ✓✓</small>
            </FeaturePanel>
            <FeaturePanel title="First purchase" subtitle="At Sunday Coffee">
              <div className="bf-coffee">
                <FeatureIcon />
              </div>
              <FeatureRow title="Purchase confirmed" detail="Staff issue Jamie’s first stamp." icon="check" />
              <FeaturePill>Qualification complete</FeaturePill>
            </FeaturePanel>
          </div>
          <div className="bf-bonus">
            <span className="bf-label">BOTH EARN BONUS STAMPS</span>
            <div className="bf-pair">
              <div>
                <FeaturePerson name="Amelia" detail="Invited a friend" />
                <strong>
                  +2 <small>bonus stamps</small>
                </strong>
              </div>
              <div>
                <FeaturePerson name="Jamie" detail="Joined through the invite" green />
                <strong>
                  +1 <small>bonus stamp</small>
                </strong>
              </div>
            </div>
            <small>
              After the first qualifying purchase and staff-issued stamp—not
              just signup.
            </small>
          </div>
        </>;
    if (type === "merchant-mcp") return <>
          <FeaturePanel>
            <FeatureRow title="kardy-mcp" detail="Your merchant workspace" end={<FeaturePill>3 tools</FeaturePill>} icon="plug" />
            {["get_programme", "list_rewards", "list_outlets"].map(name => <div className="bf-tool" key={name}>
                <span>{name}</span>
                <FeatureIcon name="check" />
              </div>)}
            <div className="bf-split-note">
              <span>Read-only access</span>
              <span>Owner-approved OAuth</span>
            </div>
          </FeaturePanel>
          <FeatureBranches>
            {["Claude", "Codex", "Other clients"].map((name, i) => <div className="bf-client" key={name}>
                <span className={`bf-client-mark bf-client-${i}`}>
                  {i < 2 ? <img src={`/images/landing/${name.toLowerCase()}.svg`} alt="" /> : <FeatureIcon name="plug" />}
                </span>
                <b>{name}</b>
              </div>)}
          </FeatureBranches>
        </>;
    if (type === "broadcasts") return <FeaturePanel>
          <FeatureRow title="Sunday Coffee" detail="Member broadcast" end={<FeaturePill>Draft</FeaturePill>} icon="coffee" />
          <FeatureField label="To" value="Opted-in members only" />
          <div className="bf-email">
            <small>SUBJECT</small>
            <b>Something new is brewing.</b>
            <span>Your next neighbourhood favourite is here.</span>
            <span>Come by this weekend and try our new menu.</span>
          </div>
          <div className="bf-split-note">
            <span>Unsubscribe · Manage preferences</span>
            <span>Preview only</span>
          </div>
        </FeaturePanel>;
    if (type === "members") return <FeaturePanel title="Members" subtitle="Sunday Coffee · example records">
          <div className="bf-search">
            <FeatureIcon name="search" />
            Search members
          </div>
          {[["Amelia", "5 / 8 stamps"], ["Jamie", "2 / 8 stamps"], ["Sarah", "Ready to redeem"]].map(([name, detail], i) => <div className="bf-member-row" key={name}>
              <FeaturePerson name={name} detail="Active membership" green={i === 1} />
              <FeaturePill>{detail}</FeaturePill>
            </div>)}
        </FeaturePanel>;
    if (type === "analytics") return <FeaturePanel title="Overview" subtitle="This month · UTC · example data">
          <div className="bf-metrics">
            {[["Visits", "248"], ["Rewards redeemed", "38"], ["Active stores", "2"]].map(([label, value]) => <div key={label}>
                <small>{label}</small>
                <strong>{value}</strong>
              </div>)}
          </div>
          <FeatureRow title="Location performance" detail="Visits and redemptions by outlet" icon="pin" />
          <FeatureRow title="Orchard" detail="164 recorded visits" end="26 claims" />
          <FeatureRow title="Joo Chiat" detail="84 recorded visits" end="12 claims" />
        </FeaturePanel>;
    if (type === "usage-limits") return <FeaturePanel title="Usage & limits" subtitle="Illustrative Growth workspace">
          <div className="bf-usage">
            <FeatureRow title="Stored members" end="800 / 1,000" />
            <div className="bf-meter">
              <span style={{
      width: "80%"
    }} />
            </div>
            <FeaturePill>80% used · plan ahead</FeaturePill>
            <FeatureRow title="MCP tool calls" detail="This UTC calendar month" end="250 / 1,000" />
            <div className="bf-meter">
              <span style={{
      width: "25%"
    }} />
            </div>
          </div>
          <FeatureRow title="Usage stops at the limit" detail="No automatic overage billing." icon="lock" />
        </FeaturePanel>;
    if (["outlets", "team-access", "multiple-brands"].includes(type)) return <>
          <div className="bf-root">
            <FeaturePanel>
              {type === "outlets" ? <FeatureBrand /> : <FeaturePerson name="Amelia Tan" detail={type === "multiple-brands" ? "One merchant account" : "Organisation Owner"} />}
            </FeaturePanel>
          </div>
          <FeatureBranches>
            {(type === "outlets" ? [["Orchard", "Active outlet"], ["Joo Chiat", "Active outlet"], ["Tiong Bahru", "Active outlet"]] : type === "team-access" ? [["Amelia", "Owner"], ["Daniel", "Manager"], ["Jamie", "Staff"]] : [["Sunday Coffee", "Owner"], ["Forma Studio", "Manager"], ["Good Company", "Staff"]]).map(([name, detail], i) => <div className="bf-node" key={name}>
                {type === "outlets" ? <FeatureIcon name="pin" /> : type === "multiple-brands" ? <FeatureBrand name={["sunday-coffee", "forma-studio", "good-company"][i]} /> : <FeatureAvatar name={name} green={i === 1} />}
                <b>{name}</b>
                <small>{detail}</small>
              </div>)}
          </FeatureBranches>
          <div className="bf-under-note">
            {type === "outlets" ? "Shared rewards and member progress across the brand." : type === "team-access" ? "Roles apply to the organisation, not to individual outlets." : "Separate teams, programmes and permissions for each brand."}
          </div>
        </>;
    if (type === "email-preferences") return <FeaturePanel title="Email preferences" subtitle="Choose separately for each brand">
          {[["Sunday Coffee", true], ["Forma Studio", false]].map(([name, enabled]) => <div className="bf-member-row" key={name}>
              <FeatureRow title={name} detail="Member emails" icon="mail" />
              <div className="bf-toggle-wrap">
                <span className={enabled ? "bf-toggle bf-toggle-on" : "bf-toggle"} />
                <small>{enabled ? "Opted in" : "Opted out"}</small>
              </div>
            </div>)}
          <FeatureRow title="You’re in control" detail="Change your choice at any time." icon="check" />
        </FeaturePanel>;
    if (type === "kardy-network") return <FeaturePanel>
          <div className="bf-search">
            <FeatureIcon name="search" />
            Search places or perks
          </div>
          <div className="bf-categories">
            <FeaturePill>All</FeaturePill>
            <span>Food & drink</span>
            <span>Wellness</span>
          </div>
          <div className="bf-offer">
            <FeatureBrand />
            <div>
              <b>A coffee, on us.</b>
              <FeatureIcon />
            </div>
            <small>Sunday Coffee · member reward</small>
          </div>
        </FeaturePanel>;
    if (type === "scanning") return <div className="bf-pair">
          <div className="bf-card-wrap">
            <FeatureCard />
            <div className="bf-under-note">Customer shows their Kardy QR</div>
          </div>
          <FeaturePanel title="Membership found" subtitle="Sunday Coffee">
            <FeaturePerson name="Amelia" detail="Active membership" />
            <FeatureRow title="5 / 8 stamps" detail="A coffee, on us" icon="gift" />
            <div className="bf-action">Add stamp</div>
            <small className="bf-under-note">
              Staff confirm the action after the purchase. Scanning alone adds
              nothing.
            </small>
          </FeaturePanel>
        </div>;
    if (type === "qr-signs") return <div className="bf-pair">
          <FeaturePanel title="Join our programme">
            <FeatureBrand />
            <div className="bf-qr-placeholder">
              <FeatureIcon name="search" />
              <span>
                Your generated
                <br />
                join QR
              </span>
            </div>
            <div className="bf-under-note">Sunday Coffee · Orchard</div>
          </FeaturePanel>
          <div className="bf-card-wrap">
            <FeatureField label="Destination" value="Customer join page" />
            <FeatureField label="Outlet" value="Orchard" />
            <FeatureRow title="Print, place, test" detail="A sign at the counter helps customers join." icon="check" />
          </div>
        </div>;
    if (type === "join-pages") return <div className="bf-device-pair">
          <FeaturePhone>
            <FeatureBrand />
            <b className="bf-device-heading">Your next coffee starts here.</b>
            <FeatureField label="Name" value="Amelia Tan" />
            <FeatureField label="Email" value="amelia@example.com" />
            <div className="bf-action">Create account & join</div>
          </FeaturePhone>
          <div className="bf-device-note">
            <FeaturePill>Sunday Coffee</FeaturePill>
            <b>One Kardy account.</b>
            <span>Join this programme with your new or existing account.</span>
            <FeatureRow title="Membership ready" detail="Then earn stamps in store." icon="wallet" />
          </div>
        </div>;
    if (type === "browser-wallet") return <div className="bf-device-pair">
          <FeaturePhone>
            <b className="bf-device-heading">Wallet</b>
            <FeatureCard />
            <div className="bf-action">Show my QR</div>
          </FeaturePhone>
          <div className="bf-device-note">
            <span className="bf-app-mark">k.</span>
            <b>Kardy on your home screen</b>
            <span>Choose Add to Home Screen in a supported browser.</span>
            <FeaturePill>Progressive web app</FeaturePill>
            <small>No app-store download.</small>
          </div>
        </div>;
    if (type === "native-wallets") return <>
          <div className="bf-pair">
            <div className="bf-card-wrap">
              <FeatureCard />
            </div>
            <FeaturePanel title="Keep your pass close">
              <FeatureRow title="Apple Wallet" detail="Signed pass, when configured" icon="wallet" />
              <FeatureRow title="Google Wallet" detail="Save link, when configured" icon="wallet" />
              <FeaturePill>Availability depends on setup</FeaturePill>
            </FeaturePanel>
          </div>
          <div className="bf-under-note">
            Use the browser wallet for current stamp progress. Saving a native
            pass is optional.
          </div>
        </>;
    return null;
  };
  const copy = featureSceneCopy[type];
  if (!copy) return null;
  return <div className="kardy-feature-art" role="img" aria-label={`${copy[1]} illustration. ${copy[2]} ${copy[3]} Example interface; see the caption and instructions below.`}>
      <div aria-hidden="true">
        <div className="bf-intro">
          <span>
            <FeatureIcon name={copy[0]} />
            {copy[1]}
          </span>
          <div className="bf-headline">
            {copy[2]}
            <br />
            <em>{copy[3]}</em>
          </div>
        </div>
        <div className={`bf-scene bf-scene-${type}`}>
          <FeatureScene type={type} />
        </div>
        <div className="bf-example">
          Illustrative example · not a live account
        </div>
      </div>
    </div>;
};

**Where:** Merchant workspace → **Overview**.

<Frame caption="Illustrative reporting, not live business totals.">
  <FeatureIllustration type="analytics" />
</Frame>

## Core metrics and filters

| Metric           | Meaning                                            |
| ---------------- | -------------------------------------------------- |
| Visits           | Recorded stamp events during the reporting period  |
| Rewards redeemed | Recorded reward claims during the reporting period |
| Active stores    | Current active outlets in the programme            |

Overview starts at **This month · UTC**. Use **Add filter** or the Store chip to choose a store, and open
**Dates**. The calendar has quick presets, two months side by side, and editable
start/end dates. Choose **Apply** to update totals and location rankings, or
**Cancel** to leave the current dates unchanged. One top filter row controls the
totals, chart and location performance. Ranges support up to 366 days, including
today (partial). Active stores and
member progress are current snapshots, not historical counts. Sample data is
labelled separately.

## Filter and inspect graphs

Overview's **Show** selector switches between **Member visits** and **Rewards
redeemed**, using the same dates and store as the summary cards. Visits mean
stamp-issued events, not unique visitors. The chart's vertical scale shows event
counts and its horizontal scale shows UTC dates. When today is included, the
current period is partial and comparison is against the full previous period.

Outside Overview, Reward redemptions and Successful referrals have their own
filter row with **Dates** and **Compare** chips. Choose a preset such as Last 7 days, Last 30
days or Last 90 days, or click a start and end date, then choose **Apply**.
Ranges support up to **366 complete UTC days**, ending before today; unavailable
presets and future dates cannot be selected.
These other graph dates are independent of Overview and reward/referral tables.

Graphs compare against the immediately preceding equal-length period. Remove the
**Compare** chip to hide it, or choose **Compare** under **Add filter** to restore
it. Hover to inspect a day; the tooltip follows
the plotted value. Click a start date, move across the graph, then click an end
date to finish highlighting a range. **Clear** or Escape removes the selection.
With the graph focused, use arrow keys to move and Enter or Space to set each
boundary. The selected total does not change the date filter.

Rewards, Referrals and store graphs also offer **View data** for the underlying
values. Overview offers **View live** instead.

## Activities and Live view

Choose **View live** on Member activity to open the [Live view globe](/features/live-view)
and latest recorded events. Use [Activities](/features/activities) to search the
audit history by member and filter by store or event type. These views require
Owner or Manager access; map pins represent stores, not customer positions.

## Location and member progress

**Location performance** shows visit/redemption leaders and the top three locations
by visits. Ties remain visible. Only activity attributed to an outlet belongs in
that outlet's totals. **View all locations** opens the full locations view.

**Working towards a reward** groups loaded active members into Goal reached, On
track and Not started. This is a current snapshot, not a forecast.

<Note>
  Individual location pages retain Daily · Last 30 days and Monthly · Last 12
  months views. Unlike the complete-day graphs above, these include today's or
  this month's partial activity. Location activity timestamps use the outlet's
  time zone; reporting buckets use UTC.
</Note>

Unavailable data is not zero. Complete daily history reads are bounded; if the
requested period exceeds the read limit, narrow the dates and retry rather than
treating a partial trend as complete. Do not infer revenue, conversion or profit
from visit counts alone.

For store configuration, see [Outlet management](/features/outlets). Reward-specific
claim definitions live in [reward performance](/features/rewards#understand-performance).
