Skip to main content

APP_CONTEXT.md — forsyt.io Application Knowledge

Living document. Update this file whenever Claude discovers new information about the app — real selectors, confirmed flows, new pages, UI changes. This is the domain knowledge base that lets Claude write tests with minimal prompting.


What the App Is​

forsyt.io is a mobile-first sports web application — likely a sports betting or live sports tracking platform. It is designed primarily for mobile browsers (402×874 viewport, matching the Figma canvas). A desktop layout also exists.

  • Live URL: https://forsyt.io
  • Primary device: Mobile (402×874, touch, is_mobile=true)
  • Browser default: Chromium (configurable via .env)
  • Auth: Session-based. Saved auth state: .auth/state.json

Known Pages​

PageURLAuthStatusPage Object
Splash / Root/NoConfirmed loads (test passes)None yet
Sports Feed/sportsNoUnknown — not yet testedNone yet
Live / In-Play/liveNoUnknown — not yet testedNone yet
Login/loginNoSkeleton page object existspages/login_page.py (placeholder selectors)
Dashboard/dashboardYesSkeleton page object existspages/dashboard_page.py (placeholder selectors)
My Bets/my-betsYesNot yet testedNone yet
Account / Profile/accountYesNot yet testedNone yet
Event Detail/event/<id>NoNot yet testedNone yet
404 / Error/nonexistentNoNot yet testedNone yet

Note on placeholder selectors: login_page.py and dashboard_page.py use [data-testid='...'] selectors that do not yet correspond to real elements in the live app. Tests using these page objects will fail until real selectors are discovered and updated.


UI Structure — From Figma Analysis​

Splash Screen (Figma node 837:22442)​

  • Viewport: 402×874 (iPhone-sized)
  • Background: Dark/solid colour
  • Centre: forsyt.io logo (logo_white2) — white logo centred vertically and horizontally
  • Top: iPhone-style Status Bar (iPhone / Status Bar) — time, signal, battery indicators
  • Bottom: Navigation bar frame is present in the DOM but hidden on the splash screen
  • Behaviour: Transitions to the main app automatically or via user action

Key Figma nodes observed:

837:22442  → Splash Screen frame (root)
837:22443 → iPhone / Status Bar
837:22465 → Logo group (logo_white2 1)
837:22467 → Frame 43474 — bottom nav (hidden="true" on splash)

Bottom Navigation Bar (Mobile)​

Observed from Figma node 837:22467 (hidden on splash, visible on other pages):

  • 5 navigation slots (icon + optional label each)
  • Tab 1: Sports — has icon + text label "Sports"
  • Tabs 2–5: Icons only (no labels confirmed yet)
  • Notification badge: Visible on at least one tab — shows number "2" (Figma node 837:22497)
  • Structure: Horizontal bar pinned to bottom of screen
  • Touch targets: Must be ≥ 44×44px each
Frame 43474 (bottom nav root)
├── Frame 43473 → Sports tab (icon + "Sports" label)
│ ├── Frame (icon slot)
│ └── Text "Sports"
├── Frame (tab 2 icon)
├── Frame (tab 3 icon)
├── Frame (tab 4 icon)
├── Frame (tab 5 icon)
└── Frame 43474 → badge container → Text "2"

Status Bar (Mobile)​

  • Present at top of every screen
  • Contains: left side (time display), right side (signal, wifi, battery icons)
  • Height: ~44px
  • Content below must not overlap with the status bar

Known User Flows​

Flow 1: App Entry (Splash → Home)​

User opens forsyt.io
→ Splash screen appears (logo visible, status bar visible, bottom nav hidden)
→ Auto-transition OR user taps to continue
→ Lands on Sports Feed / Home
→ Bottom nav becomes visible

Flow 2: Tab Navigation (Mobile)​

User is on Sports Feed
→ Taps "Live" tab in bottom nav
→ Live / In-Play page loads
→ Active tab indicator moves to "Live"

User taps "My Bets" tab
→ If authenticated → My Bets page loads
→ If not authenticated → Redirected to Login

Flow 3: Login​

User arrives at /login (directly or via redirect)
→ Email field visible
→ Password field visible
→ Submit button visible
→ User enters credentials → taps submit
→ Valid credentials → redirects to main app (dashboard or sports feed)
→ Invalid credentials → error banner appears, stays on login page
→ Empty form submit → field-level validation shown

Flow 4: Protected Page Access (Unauthenticated)​

User navigates to /my-bets or /account without being logged in
→ App redirects to /login

Flow 5: Event Navigation​

User is on Sports Feed
→ Sees list of event cards (teams, odds, time/status)
→ Taps an event card
→ Event detail page loads (match info, full odds)
→ Taps browser back
→ Returns to Sports Feed at the same scroll position

UI Patterns Confirmed / Observed​

PatternWhereNotes
Logo centred on dark backgroundSplashWhite logo, logo_white2
iPhone status barAll pages (mobile)Time + icons, ~44px height
Bottom nav — 5 tabsAll pages except Splash (mobile)Tab 1 = Sports confirmed
Notification badgeBottom navShows "2" in Figma
Event cards with oddsSports FeedTeams + 2+ odds values + time
Loading spinnerAny data pageAppears during fetch, disappears when ready
Error bannerLogin, form pagesAppears inline on bad credentials
Field validationLogin formAppears on empty submit

Confirmed Selectors​

Selectors are confirmed only once tested against the live site. Do not use unconfirmed selectors in tests. Mark them with # UNCONFIRMED until verified.

ElementSelectorStatusPage object location
(none confirmed yet)———

When a selector is discovered from the live site (via browser DevTools, Playwright inspector, or a passing test), add it to the table above AND update the corresponding page object.


Placeholder Selectors (Not Yet Verified)​

These exist in the codebase but are not confirmed to work on the live site:

SelectorUsed inLikely real?
[data-testid='username-input']pages/login_page.pyUnknown
[data-testid='password-input']pages/login_page.pyUnknown
[data-testid='login-submit']pages/login_page.pyUnknown
[data-testid='login-error']pages/login_page.pyUnknown
h1[data-testid='login-heading']pages/login_page.pyUnknown
h1[data-testid='dashboard-heading']pages/dashboard_page.pyUnknown
[data-testid='welcome-message']pages/dashboard_page.pyUnknown
[data-testid='stats-card']pages/dashboard_page.pyUnknown
nav[role='navigation']components/navbar.pyUnknown

How to Discover Real Selectors​

When the user asks to implement a test for a page with no confirmed selectors:

  1. Flag it clearly — state that selectors are unknown and tests will be skeletons
  2. Use the most stable selector strategy — prefer data-testid, then ARIA role, then text
  3. Mark unconfirmed selectors with # UNCONFIRMED — update after live site inspection
  4. Update this file once selectors are confirmed from a passing test or DevTools inspection

To inspect selectors on the live site:

# Launch Playwright inspector on forsyt.io
HEADLESS=false python -c "
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
b = p.chromium.launch(headless=False)
ctx = b.new_context(viewport={'width':402,'height':874}, is_mobile=True)
page = ctx.new_page()
page.goto('https://forsyt.io')
page.pause() # opens Playwright Inspector
"

What Claude Should Infer from This Document​

  • If asked to "add a test for the bottom nav" → bottom nav has 5 tabs, tab 1 is Sports, one tab has badge "2", hidden on splash screen
  • If asked to "add a test for the splash screen" → check logo visibility, check status bar, check bottom nav is hidden, check no console errors
  • If asked about selectors → assume data-testid attributes exist (common pattern), but mark as unconfirmed until a test passes
  • If asked to "add a smoke test for any page" → page load + key element visible + no console errors is the minimum smoke set
  • If told "the selector is X" → update the page object _PRIVATE_CONSTANT and this file's Confirmed Selectors table