{"id":50073464,"url":"https://github.com/majdukovic/frontrow","last_synced_at":"2026-05-23T20:00:58.483Z","repository":{"id":356026847,"uuid":"1230592219","full_name":"majdukovic/frontrow","owner":"majdukovic","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-06T10:22:58.000Z","size":692,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-06T10:44:19.154Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/majdukovic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-06T06:26:53.000Z","updated_at":"2026-05-06T10:23:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/majdukovic/frontrow","commit_stats":null,"previous_names":["majdukovic/frontrow"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/majdukovic/frontrow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/majdukovic%2Ffrontrow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/majdukovic%2Ffrontrow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/majdukovic%2Ffrontrow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/majdukovic%2Ffrontrow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/majdukovic","download_url":"https://codeload.github.com/majdukovic/frontrow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/majdukovic%2Ffrontrow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33410345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T18:09:33.147Z","status":"ssl_error","status_checked_at":"2026-05-23T18:09:31.380Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-22T04:00:51.039Z","updated_at":"2026-05-23T20:00:58.468Z","avatar_url":"https://github.com/majdukovic.png","language":"TypeScript","funding_links":[],"categories":["Mobile Testing","Training (Includes developer training for automation testers)"],"sub_categories":["A/B Testing"],"readme":"\u003cdiv align=\"center\"\u003e\n\n# FrontRow\n\n**An open-source mobile app designed as a QA automation training playground.**\n\n[![License](https://img.shields.io/github/license/majdukovic/frontrow?color=FF3B5C)](LICENSE)\n[![CI](https://img.shields.io/github/actions/workflow/status/majdukovic/frontrow/ci.yml?branch=main\u0026label=CI)](https://github.com/majdukovic/frontrow/actions/workflows/ci.yml)\n[![Latest release](https://img.shields.io/github/v/release/majdukovic/frontrow?color=FF3B5C)](../../releases)\n[![Platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20Android-2D2D2D)](#install-a-prebuilt-binary)\n[![React Native](https://img.shields.io/badge/built%20with-React%20Native%20%2B%20Expo-2D2D2D)](https://expo.dev)\n\n\u003cbr /\u003e\n\n\u003cimg src=\"docs/media/01-events.png\" alt=\"FrontRow events feed\" width=\"280\" /\u003e\n\n\u003cbr /\u003e\n\nA concert \u0026 events ticketing app for QA automation engineers, automation learners, and manual testers. Stable test IDs, a deep QA Debug Menu, deterministic seed data, bridged native screens, a full Maestro suite, and ready-to-extend scaffolds for Appium, Espresso, and XCUITest — all targeting the same identifiers.\n\nClone, run on a simulator in under five minutes, then use it to learn — or teach — mobile test automation against a realistic surface.\n\n\u003c/div\u003e\n\n\u003e [!TIP]\n\u003e\n\u003e ### ⭐ Find FrontRow useful?\n\u003e\n\u003e **If it helps you practice mobile testing, please [star the repo](https://github.com/majdukovic/frontrow).** It surfaces the project for the next QA engineer searching for a sandbox, and tells me it's worth investing more time in.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/majdukovic/frontrow\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/%E2%AD%90%20Star%20this%20repo-on%20GitHub-FF3B5C?style=for-the-badge\u0026labelColor=2D2D2D\" height=\"42\" alt=\"Star this repo on GitHub\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## See it in action\n\nA Maestro flow driving the ticket-purchase journey — events list → event detail → tier selection → confirmation — captured on a Pixel 7a running the release APK:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/media/maestro-buy.gif\" alt=\"Maestro driving the buy flow on Android\" width=\"280\" /\u003e\n\u003c/p\u003e\n\nThe full flow YAML — the entire test that produced that recording:\n\n```yaml\n# tests/maestro/tickets/buy.yaml\nappId: app.frontrow.qa\n---\n- runFlow: ../_setup.yaml # signs in the demo user via deep link\n\n- tapOn:\n    id: 'tab.events'\n- assertVisible:\n    id: 'screen.events'\n- tapOn:\n    id: 'events.item.evt_001'\n- assertVisible:\n    id: 'screen.eventDetail'\n\n- tapOn:\n    id: 'eventDetail.buyButton'\n- assertVisible:\n    id: 'screen.buyTicket'\n- tapOn:\n    id: 'buyTicket.payButton'\n\n- assertVisible: 'Ticket purchased'\n\n- tapOn:\n    id: 'tab.myTickets'\n- assertVisible:\n    id: 'screen.myTickets'\n```\n\nAnd a JS-to-native bridge flow exercising a hand-rolled Swift `UIViewController` / Kotlin `Activity` from the QA Debug Menu:\n\n```yaml\n# tests/maestro/native/native-demo.yaml (excerpt)\nappId: app.frontrow.qa\n---\n- runFlow: ../_setup.yaml\n- tapOn:\n    id: 'tab.debug'\n- scrollUntilVisible:\n    element:\n      id: 'debug.openNativeDemo'\n    direction: DOWN\n- tapOn:\n    id: 'debug.openNativeDemo'\n- assertVisible: '0'\n- tapOn: 'Increment'\n- tapOn: 'Increment'\n- assertVisible: '2'\n- tapOn: 'Close'\n```\n\nBoth flows pass on Android emulator and iPhone simulator without changes — the `id:` matchers map to `resource-id` on Android and `accessibilityIdentifier` on iOS via the central registry in [`src/testIds.ts`](src/testIds.ts).\n\n## Screen tour\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/01-events.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEvents feed\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/02-eventDetail.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eEvent detail + lineup\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/03-buyTicket.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTier picker\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/04-ticketQr.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eYour ticket (QR)\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/05-debugMenu.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eQA Debug Menu\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003cimg src=\"docs/media/06-nativeDemo.png\" width=\"200\" /\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBridged native screen\u003c/b\u003e\u003c/sub\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Who this is for\n\n- **QA automation engineers** picking up Maestro, Appium, Espresso, or XCUITest — or comparing them side by side against the same testID contract.\n- **Anyone learning mobile test automation** from scratch and wanting a real app instead of a TODO list.\n- **Manual testers** who want a realistic surface with controllable failure modes (network errors, expired tickets, denied permissions, declined purchases) — no flaky backend, no shared test account.\n- **Educators, bootcamps, and team leads** building hands-on labs: MIT-licensed, fork-friendly, runs offline.\n- **Tool authors** validating frameworks, recorders, or accessibility audits against a non-trivial production-style app.\n\n## What you can practice\n\nEach item maps to features and dedicated docs in the repo — nothing is hand-wavy.\n\n- **Build cross-platform selectors that actually work.** Central testID registry → `accessibilityIdentifier` on iOS + `resource-id` on Android. Same matcher in every framework. See [docs/TEST_IDS.md](docs/TEST_IDS.md).\n- **Drive an app into any state via deep links** instead of brittle UI navigation. `frontrow://debug/seed/\u003cscenario\u003e`, `frontrow://debug/trigger/\u003ckind\u003e/on`, `frontrow://e2e/setup`. Catalog: [docs/DEEPLINKS.md](docs/DEEPLINKS.md).\n- **Simulate the failure modes that bite in production**: 4xx / 5xx / timeout / offline, on demand, per-request or globally. Network profiles for slow-3G/2G testing.\n- **Test in-app purchase flows deterministically** — flip outcomes to success, decline, cancel, or pending without a sandbox account. Restore purchases works too.\n- **Practice time-travel testing** for expired tickets, refund windows, and stale data without waiting in real time. `+1h`, `+1d`, `+1w`, `+1mo` presets.\n- **Exercise device capabilities under test**: camera, microphone, GPS, biometric, haptics, calendar, share, notifications — each with its own screen and stable testIDs.\n- **Bridge to raw native code** (Swift `UIViewController`, Kotlin `Activity`) using the same testID contract — practice driving native surfaces, not just JS.\n- **Write the same flow in four frameworks** and see which fits your team. `tests/maestro/auth/login.yaml` and `tests/appium/specs/login.spec.ts` target identical IDs.\n\n## Quick start\n\nRequires Node 20+ and either Xcode or Android Studio.\n\n```bash\ngit clone https://github.com/majdukovic/frontrow.git\ncd frontrow\nnpm install\nnpm run ios       # or: npm run android\n```\n\nThat's it. No backend to run, no accounts to create, no secrets to configure.\n\n\u003e Some Phase 5+ capabilities (MMKV, real local notifications) require a development build. The standard `npm run ios` / `npm run android` covers that — Expo Go alone is not enough once `expo prebuild` has run.\n\n### On a real device\n\nThe defaults above target a simulator/emulator. To build from source onto a USB-connected phone:\n\n**Android phone**\n\n1. Enable Developer Options → USB debugging on the phone.\n2. Plug it in and confirm `adb devices` lists it as `device` (not `unauthorized`).\n3. `npm run android` — `expo run:android` auto-detects the connected device and prompts if both an emulator and a phone are available.\n\n**iPhone**\n\n1. Open `ios/FrontRow.xcworkspace` in Xcode at least once, pick your team under Signing \u0026 Capabilities, and change the bundle identifier from `app.frontrow.qa` to something unique to your account (mirror the change in `app.config.ts`). A free Apple ID works for development builds.\n2. Trust your developer certificate on the device: Settings → General → VPN \u0026 Device Management.\n3. `npm run ios -- --device` — passes through to `expo run:ios --device`, which lists connected iPhones to pick from. The first build is slow; subsequent ones are fast.\n\nIf you just want to poke at the app without a toolchain, grab the prebuilt artifacts from [Releases](https://github.com/majdukovic/frontrow/releases) — Android sideloads on real devices, iOS is Simulator-only.\n\n## Install a prebuilt binary\n\nGrab the latest artifacts from the [Releases page](https://github.com/majdukovic/frontrow/releases) — each tagged release ships an Android APK and an iOS Simulator `.app.zip` so you can poke at FrontRow without setting up a React Native toolchain.\n\n### Android — `FrontRow.apk` (real device or emulator)\n\nThe APK is a release-variant build signed with a debug keystore. It installs side-by-side with anything from the Play Store, but `adb` and the device installer will both flag it as \"from an unknown source\" — that's expected.\n\n**On an emulator** (Android Studio AVD running):\n\n```bash\nadb install FrontRow.apk\nadb shell am start -n app.frontrow.qa/.MainActivity\n```\n\n**On a real device** (USB debugging enabled, device paired with `adb devices`):\n\n```bash\nadb install -r FrontRow.apk\n```\n\n**No `adb`?** Email/AirDrop/download the APK to the device, tap it in Files, accept the \"install unknown apps\" prompt for whatever app is handling it (usually Chrome or Files). The app launches from the home screen as **FrontRow**.\n\n### iOS — `FrontRow.app.zip` (iOS Simulator only)\n\nThe `.app` inside is a Release build for the iOS Simulator on Apple Silicon (`arm64`). It will not run on a physical iPhone or on Intel Macs.\n\n```bash\n# 1. Unzip the artifact\nunzip FrontRow.app.zip\n\n# 2. Make sure a simulator is booted. If `xcrun simctl list devices booted`\n#    prints no devices, open Xcode → Window → Devices and Simulators and\n#    boot any iOS 18+ iPhone, or run:\nxcrun simctl boot \"iPhone 17 Pro\"        # or any device from `xcrun simctl list devices`\n\n# 3. Install + launch\nxcrun simctl install booted FrontRow.app\nxcrun simctl launch booted app.frontrow.qa\n```\n\nTip: you can also drag-and-drop the unzipped `FrontRow.app` onto a running Simulator window — same effect.\n\n**For a real iPhone**: you'll need to build from source with your own provisioning profile (see [Quick start](#quick-start)). A signed `.ipa` for TestFlight may land in a later release.\n\n## First five minutes\n\nOnce the app is on a device or simulator:\n\n\u003e **Manual testers — start at step 5.** The Debug tab is built for you: flip scenarios, force errors, and time-travel through ticket states without any code or automation runner. Steps 1–4 are the happy path you'll want to know first.\n\n1. **Onboarding** — three intro slides. Tap \"Skip\" or swipe through and \"Get started\".\n2. **Sign in** — Profile tab → Sign in. Demo creds are filled in (`demo@frontrow.app` / `password`). Or skip auth entirely; most of the app works signed out.\n3. **Browse events** — the Events tab opens to a feed of mocked concert listings. Search, filter by genre, scroll for infinite pagination.\n4. **Buy a ticket** — tap any event → **Buy** → choose a tier → **Confirm purchase**. The flow ends in My Tickets with a QR code.\n5. **Visit the Debug tab** — this is where the QA showcase lives. Try:\n   - **Scenarios** → \"Empty state\" / \"Expired tickets\" / \"Many events\" — reseed mock data with one tap.\n   - **Network → Force error → 5xx** — every API call returns a 500 until you set it back to None.\n   - **In-app purchases → Decline** — flip the IAP outcome and re-run the buy flow.\n   - **Time travel → +1w** — fast-forward the clock to see expired tickets and stale events.\n   - **Device capabilities → Native demo** — opens a hand-rolled Swift `UIViewController` / Kotlin `Activity` bridged to JS (the testID contract carries through to raw native code).\n   - **First-run → Replay onboarding** — reset the onboarding flag without wiping data.\n   - **Reset → Wipe all local data** — full reset, useful between manual runs.\n6. **Trigger a deep link** to jump to a specific state without tapping through. From a terminal:\n\n   ```bash\n   # Android\n   adb shell am start -W -a android.intent.action.VIEW -d \"frontrow://debug/seed/empty_state\"\n   # iOS Simulator\n   xcrun simctl openurl booted \"frontrow://debug/seed/expired_tickets\"\n   ```\n\n   Full deep-link catalog: [docs/DEEPLINKS.md](docs/DEEPLINKS.md).\n\n## Try a Maestro flow\n\nWith the app installed and Metro running:\n\n```bash\n# Single flow:\nmaestro --device \u003cudid-or-emulator-id\u003e test tests/maestro/native/native-demo.yaml\n\n# Full suite (handles per-platform tag exclusions + retries):\n./scripts/maestro.sh android        # or: ./scripts/maestro.sh ios\n```\n\nThe driver auto-installs on first run on iOS (~90s). Subsequent runs are fast.\n\n## What's inside\n\n**Test infrastructure**\n\n- **Stable test IDs** — central registry in `src/testIds.ts` maps to `accessibilityIdentifier` (iOS) and `resource-id` (Android). A custom ESLint rule (`frontrow/require-testid`) flags interactive elements that ship without one.\n- **QA Debug Menu** — Build info · Jump-to-screen · Device-capability demos · Seed scenarios · Time travel · Force error (4xx / 5xx / timeout / offline) · Network delay · Locale override · Replay onboarding · Fake push · Crash · IAP outcome control · Analytics event log · Reset.\n- **Deep-link contract** — every public deep link is documented, including `frontrow://debug/seed/\u003cscenario\u003e` to put the app into a known state from a single `launchApp` directive. See [docs/DEEPLINKS.md](docs/DEEPLINKS.md).\n- **Mock IAP** — products, receipts, restore-purchases, with QA-controlled outcomes (success, decline, cancel, pending). See [docs/tutorials/SCENARIOS_AS_FIXTURES.md](docs/tutorials/SCENARIOS_AS_FIXTURES.md).\n\n**Product surfaces (every feature ships with at least one Maestro flow)**\n\n- **Realistic UX** — onboarding pager · debounced search with genre + favorites filters · skeleton loaders · paginated infinite scroll · star-rated reviews · ticket detail with QR + cancel + transfer · Active/Past ticket filter · saved payment methods CRUD · edit-profile with dirty-state guard · forgot-password (email → OTP → reset) · notification inbox with unread badge · offline banner · share to system sheet · retry on error.\n- **Device capabilities** — camera, microphone, location, biometric, haptics, calendar, share, notifications. Each has a dedicated screen with stable testIDs.\n\n**Native code, on purpose**\n\n- **Hand-rolled native screen** — a Swift `UIViewController` (iOS) and Kotlin `AppCompatActivity` (Android) bridged to JS so QA can drive raw native surfaces with the same testID contract used everywhere else. Open it from the Debug tab → \"Native demo\", or via `tests/maestro/native/native-demo.yaml`. Source: [`native-showcase/`](native-showcase/) — copied into the host iOS/Android projects on every `expo prebuild` by [`plugins/with-native-showcase.js`](plugins/with-native-showcase.js).\n\n**Engineering**\n\n- **React Native + Expo (prebuilt)** — single TypeScript codebase, native iOS and Android projects committed.\n- **Local-first** — all data lives in MMKV, seeded from JSON fixtures, no backend, no accounts.\n\n## Test frameworks\n\n| Framework                 | Lives in          | Coverage today                           | Tutorial                                       |\n| ------------------------- | ----------------- | ---------------------------------------- | ---------------------------------------------- |\n| Maestro                   | `tests/maestro/`  | 30 flows across 8 areas — the full suite | [Maestro 101](docs/tutorials/MAESTRO_101.md)   |\n| Appium (WebdriverIO + TS) | `tests/appium/`   | Smoke + login specs, full WDIO infra     | [Appium 101](docs/tutorials/APPIUM_101.md)     |\n| Espresso (Android)        | `tests/espresso/` | Smoke template — wired to project hooks  | [Espresso 101](docs/tutorials/ESPRESSO_101.md) |\n| XCUITest (iOS)            | `tests/xcuitest/` | Smoke + sign-in templates                | [XCUITest 101](docs/tutorials/XCUITEST_101.md) |\n\nA flow is a flow regardless of framework. Look at `tests/maestro/auth/login.yaml` and `tests/appium/specs/login.spec.ts` side by side — they target identical test IDs.\n\nMaestro is the only framework with full coverage today; Appium, Espresso, and XCUITest ship with working examples and the same testID contract, so adding new flows is mechanical — see [Roadmap](#roadmap) for what's next.\n\n## Documentation map\n\n- [docs/DEEPLINKS.md](docs/DEEPLINKS.md) — full deep-link contract.\n- [docs/DEBUG_MENU.md](docs/DEBUG_MENU.md) — every QA Debug Menu action.\n- [docs/SCENARIOS.md](docs/SCENARIOS.md) — seed scenario catalog.\n- [docs/TEST_IDS.md](docs/TEST_IDS.md) — testID conventions and lint rules.\n- [docs/A11Y.md](docs/A11Y.md) — accessibility checklist.\n- [docs/NATIVE_TESTING.md](docs/NATIVE_TESTING.md) — how testIDs map to native identifiers.\n- [docs/CI.md](docs/CI.md) — CI strategy (free PR checks + opt-in cloud labs).\n- [docs/tutorials/](docs/tutorials/) — framework-by-framework walkthroughs.\n\n## Roadmap\n\n| Phase | Scope                                                                                      | Status |\n| ----- | ------------------------------------------------------------------------------------------ | ------ |\n| 0     | Repo skeleton, toolchain, CI, navigation                                                   | ✓      |\n| 1     | Mock API + persistence + core flows + first Maestro flows                                  | ✓      |\n| 2     | QA Debug Menu + hermetic mode + deep-link-to-anywhere                                      | ✓      |\n| 3     | Device capability demos (camera, mic, location, biometric, haptic, calendar, share, push)  | ✓      |\n| 4     | Mock IAP (success, decline, cancel, restore, refund)                                       | ✓      |\n| 5     | `expo prebuild`, MMKV migration, Espresso + XCUITest scaffolding                           | ✓      |\n| 6     | Appium WebdriverIO suite + Maestro Cloud CI                                                | ✓      |\n| 7     | Tutorials, scenario recipes, README polish                                                 | ✓      |\n| 8     | Realistic product surfaces (onboarding, favorites, ticket transfer, payment methods, etc.) | ✓      |\n| 9     | Mirror representative Maestro flows in Appium / Espresso / XCUITest                        | next   |\n\nPhase 0–8 are complete. Phase 9 is the active focus: bring Appium, Espresso, and XCUITest from \"smoke template\" to real coverage by porting the higher-value Maestro flows (auth, events browse, buy, ticket transfer, debug-menu interactions) so the side-by-side framework comparison the README promises is actually side by side.\n\nFurther out, ideas are very welcome: more framework examples (Detox, KIF), contract-testing playgrounds, visual regression scaffolds, accessibility audit recipes. File an issue with a scenario you'd love to see — that's the fastest way to shape what lands next.\n\n## A note on the Debug tab\n\nThe `Debug` tab is registered unconditionally in `src/navigation/RootNavigator.tsx` and ships visible in release builds. That is **intentional** — exposing the QA surface is the whole point of this app. If you fork FrontRow as the base for a real product, gate that registration behind `__DEV__` or a build flag before publishing.\n\nThe deep-link handler in `src/hooks/useDeepLinkScenario.ts` follows the same principle: `frontrow://debug/*` URLs are honored regardless of build configuration. Same caveat applies for downstream forks.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md). Issues, scenario ideas, and tutorials are all welcome.\n\n## Show your support\n\nIf FrontRow helped you learn something, here are four small things that make a big difference:\n\n- **Star the repo** at the top of the page — it's the strongest signal that helps other QA engineers find it through GitHub search.\n- **Share it with your team or community** — Slack, Discord, LinkedIn, a course channel. The more testers who can practice on a realistic surface, the better the discipline gets.\n- **File an issue with a scenario you'd love to see** — a missing failure mode, a tricky flow, a framework you'd add. Concrete asks shape the roadmap faster than abstract feedback.\n- **Send a PR** — even a tiny one. New Maestro flows, a typo fix, a tutorial, a translation. Start with [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\n[MIT](LICENSE) — free for personal, educational, and commercial use. Fork it, rebrand it, drop it into your training program. (See the [note above](#a-note-on-the-debug-tab) if you're using FrontRow as a base for a real product.)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmajdukovic%2Ffrontrow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmajdukovic%2Ffrontrow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmajdukovic%2Ffrontrow/lists"}