User Guide — v1

How to use
CardStack.

CardStack is an interactive ranking of Canadian premium credit cards. Plug in your spending, set your point-value confidence, and see which card — or two-card stack — actually wins on the math. Everything below explains what the site does, what it doesn't, and the assumptions baked into every number.

01

Quick start

Three minutes from open to answer

    Step 01
    Set your spend

    On the home page, open the Assumptions panel and enter your annual spend per category (groceries, dining, travel, gas, recurring, all-other, foreign). Numbers persist locally in your browser.

    Step 02
    Pick a point-value preset

    Choose conservative, blended, or aggressive — or override per currency. This is the biggest lever in the model: small ¢/pt changes swing the ranking.

    Step 03
    Read the ranking

    The table re-sorts live by net value (rewards + credits − annual fee − FX cost). Click any card name for the full per-category breakdown.

02

What it does — and doesn't

Be clear-eyed about the scope

What CardStack does
  • Ranks a curated set of Canadian premium cards by net value at your spend profile.
  • Models per-category caps, including shared caps split proportionally across categories.
  • Shows the best card per category and the optimal two-card stack.
  • Lets you submit any Canadian card by URL. We scrape the issuer page and normalize it into the same schema so it ranks alongside the curated set.
  • Persists your assumptions in your browser — no account, no tracking.
What CardStack doesn't do
  • × Apply for cards on your behalf, check eligibility, or pull credit reports.
  • × Account for sign-up bonuses, limited-time promos, or referral offers — only steady-state earn.
  • × Model income requirements, approval odds, or churn / downgrade strategies.
  • × Cover U.S., business, or no-fee cards. Canadian premium personal cards only.
  • × Tell you what to do with your money. See the disclaimer below.
03

Features tour

Where to find each piece

Ranking table
Home (/)
Cards sorted by net value. Columns: rewards, credits, annual fee, FX cost, net, effective return. Click a card name for the full breakdown.
Assumptions panel
Home (/)
Annual spend per category and ¢/pt per loyalty currency. Three preset confidence levels (conservative / blended / aggressive) plus per-currency override.
Add a card
Home (/) — Add Card panel
Paste a public issuer URL. We scrape it, normalize the earn rates, fees, and credits with AI, and add it to your ranking. You see live pipeline status as it runs.
Category drill-downs
/categories/[category]
Per-category leaderboard — which card wins on groceries, dining, travel, etc. at your current assumptions.
Card detail
/cards/[card]
Full per-category math for a single card, including cap utilization and overflow.
Methodology
/methodology
The exact formulas, cap-handling rules, FX treatment, and point-value preset table.
04

Submitting your own cards

How the community pipeline works

Paste any Canadian credit card's official product page URL into the Add Card panel. The pipeline runs through visible stages so you can see exactly where your submission is:

  1. Validating URL
  2. Checking quota (3 submissions per browser)
  3. Checking for duplicates
  4. Scraping the page
  5. Normalizing with AI
  6. Deduping community entries
  7. Saving

Failures retry automatically with exponential backoff (up to 3 retries) for transient errors. You can cancel an in-flight submission at any time.

Visibility

Your submitted cards appear in your ranking immediately, markedCommunity · pending. Once an admin approves a submission, it becomes visible to everyone.

Limits & accuracy

Three submissions per browser. Scraped pages are normalized by an LLM, which can misread fine print, promotional rates, or category mappings. Treat submitted-card values as a directional estimate — verify against the issuer page before acting.

05

End-to-end example

One submission, start to finish

Here's exactly what happens when you submit a card. We'll walk through a real-looking run for the American Express Cobalt Card, including the JSON the AI normalizer returns and where it ends up in the UI.

Step 01

Paste a card URL

On the home page, open the Add Card panel and drop in the issuer's official product page.

https://www.americanexpress.com/ca/credit-cards/cobalt-card/
Step 02

Watch the live pipeline

Each stage streams its status in real time. Elapsed time per stage is shown so you can see where slow runs spend their time.

validateURL parsed, scheme + host checks pass
0.01s
quota1 of 3 submissions used on this browser
0.08s
duplicate-checkNo matching source URL on file
0.12s
scrapeFetched 18.4 KB of markdown via Firecrawl
2.41s
normalizeGemini 2.5 Flash returned valid tool-call JSON
3.07s
dedupeNo fingerprint collision (issuer + card_name)
0.09s
saveInserted as community card · pending review
0.18s

Transient failures (network blips, rate limits) auto-retry with exponential backoff up to 3 times. Validation errors and malformed AI JSON are non-retryable.

Step 03

Review the returned JSON

The AI emits a strict JSON object validated against our normalized card schema. If anything is missing or out of range, the submission is rejected before it ever reaches the database.

{
  "card_name": "Cobalt Card",
  "issuer": "American Express",
  "annual_fee": 155.88,
  "fx_fee": 2.5,
  "point_currency": "Membership Rewards",
  "credits_value_estimate": 0,
  "insurance_score": 6,
  "lounge_access_score": 0,
  "earn_rates": {
    "groceries":  { "rate": 5, "cap": "$30,000/year" },
    "dining":     { "rate": 5, "cap": "$30,000/year" },
    "travel":     { "rate": 2, "cap": null },
    "gas":        { "rate": 2, "cap": null },
    "recurring":  { "rate": 3, "cap": null },
    "all_other":  { "rate": 1, "cap": null }
  },
  "notes": "5x cap is shared across eligible groceries and dining."
}
  • rate — points/cashback multiplier (1 = 1%, 5 = 5x).
  • cap — verbatim cap string from the page, or null if uncapped.
  • point_currency — drives which ¢/pt preset is applied during ranking.
  • credits_value_estimate — annual CAD value of recurring credits (travel, dining, etc.).
Step 04

See it in your ranking

The card appears immediately in your local ranking with a Community · pending badge and contributes to the live math at your current spend assumptions. Open the card detail page to inspect per-category earn, cap utilization, and overflow.

Step 05

If something goes wrong

Scrape failed

Page is paywalled, JS-rendered, or blocked the crawler. Try the issuer's plain product page (no /apply, no logged-in URLs).

AI returned malformed JSON

Schema validation failed. Marked non-retryable to avoid burning credits. Usually means the page wasn't a card terms page.

Duplicate detected

A card with the same issuer + name already exists. We surface that record instead of creating a duplicate.

06

FAQ

Common questions, limits, and troubleshooting

Tap a question

07

Failure modes & error messages

Exact text you'll see — and what to do next

Submissions can fail at any pipeline stage. Each row below shows the literal error string the UI surfaces, the stage it came from, whether it auto-retries, and the recommended action. Transient errors (network, gateway 5xx) retry automatically up to 3 times with exponential backoff; everything else fails fast.

validatingcode: validation
"That doesn't look like a valid URL."
Why · The string you pasted couldn't be parsed as a URL.
Do · Paste a full URL including the scheme (https://…). No spaces or quotes.
Auto-retryNo
validatingcode: validation
"URL must start with http:// or https://"
Why · The URL uses an unsupported scheme (ftp:, file:, javascript:, etc.).
Do · Use the issuer's public https:// product page.
Auto-retryNo
validatingcode: validation
"Private/local URLs are not allowed."
Why · Hostname resolves to localhost, an RFC1918 range, or link-local.
Do · Submit a public-internet URL on the issuer's domain.
Auto-retryNo
checking_quotacode: quota
"You've reached the limit of 3 card submissions. Thanks for trying CardStack!"
Why · This browser has used all 3 lifetime submissions.
Do · Wait for an admin to approve your existing submissions, or use a different browser. Quota is per-browser, not per-card.
Auto-retryNo
scrapingcode: scrape
"Failed during \"Scraping the page with Firecrawl\": Firecrawl error [4xx/5xx]: …"
Why · The page is paywalled, JS-rendered behind auth, blocked the crawler, or Firecrawl is rate-limiting.
Do · Try the issuer's plain product page (no /apply, no logged-in URLs). 5xx and timeouts auto-retry — wait and resubmit if it persists.
Auto-retryYes (transient only)
scrapingcode: scrape
"FIRECRAWL_API_KEY is not configured"
Why · Server-side configuration issue — the scraper credentials are missing.
Do · Not fixable from your side. Report it; the maintainer needs to wire the connector.
Auto-retryNo
normalizingcode: ai
"AI did not return a normalized card."
Why · The model responded but skipped the required tool-call. Usually means the scraped page wasn't a credit card terms page.
Do · Double-check the URL is the card's product / details page — not a landing page, blog post, or comparison article.
Auto-retryNo
normalizingcode: ai
"AI returned invalid JSON."
Why · Tool-call arguments couldn't be parsed as JSON.
Do · Resubmit once. If it fails again, the page likely lacks structured card terms — try the issuer's main card page.
Auto-retryNo (fails fast to save credits)
normalizingcode: ai
Zod validation error (e.g. "Required at \"earn_rates.groceries\"")
Why · AI produced JSON that doesn't match the normalized card schema — missing fields or wrong types.
Do · Same as above — usually a page-content issue. A different URL on the same issuer often works.
Auto-retryNo
normalizingcode: ai
"AI gateway error [4xx/5xx]: …"
Why · Lovable AI Gateway returned an error or is rate-limited.
Do · Auto-retries on transient codes. If it still fails, wait a minute and try again.
Auto-retryYes (transient only)
savingcode: server
"Failed during \"Saving your submission\": …"
Why · Database insert failed — usually a transient connection issue.
Do · Resubmit. If it persists, the backend is down — check status and retry later.
Auto-retryYes (transient only)
anycode: server
"Stream ended unexpectedly."
Why · The SSE connection dropped before a result event arrived.
Do · Check your network and resubmit. Long scrapes (>30s) on flaky connections are the usual cause.
Auto-retryManual
anycode: server
"Request failed (5xx)"
Why · The submission endpoint itself returned a server error.
Do · Wait a few seconds and try again. Persistent failures = report it.
Auto-retryManual
Heads up · Auto-retry uses exponential backoff (500 ms → 1 s → 2 s → 4 s, capped at 8 s, with jitter). Validation errors, quota errors, and schema (Zod) failures never retry — they need an input change to succeed.
08

Disclaimer

Information only — not financial advice

Important — please read

For information purposes only. CardStack is a personal-project comparison tool. Nothing on this site is financial, tax, legal, accounting, or investment advice, and nothing here should be treated as a recommendation to apply for, hold, or close any credit card or financial product.

Information may be inaccurate or out of date. Earn rates, annual fees, FX fees, credits, insurance benefits, and lounge access change frequently. Curated card data is updated periodically; community-submitted cards are normalized by an automated pipeline that can make mistakes. Always verify the exact terms on the issuer's official website and current cardholder agreement before making any decision.

Point values are estimates. The ¢/pt presets reflect a blend of redemption strategies and assume you actually execute them. Real-world redemptions vary widely; sub-optimal redemptions can drop a currency's value by 50% or more. Past redemption rates do not guarantee future availability.

No relationship with issuers. CardStack is not affiliated with, endorsed by, or compensated by any bank or card issuer. There are no affiliate links and no referral revenue.

Your decisions are your own. Credit card products carry real financial risk: interest charges, foreign-exchange exposure, annual fees, opportunity cost of capital tied up in credits, and impact on your credit score. Consult a licensed financial advisor before making decisions based on the information shown here. By using this site you acknowledge that the authors accept no liability for any loss arising from reliance on its content.