Skip to content

feat: monorepo restructure, landing page, and production CI#20

Merged
AnganSamadder merged 70 commits intomainfrom
feat/landing-page
Feb 14, 2026
Merged

feat: monorepo restructure, landing page, and production CI#20
AnganSamadder merged 70 commits intomainfrom
feat/landing-page

Conversation

@AnganSamadder
Copy link
Owner

@AnganSamadder AnganSamadder commented Feb 13, 2026

Summary

Restructures the codebase into a Turborepo + Bun workspaces monorepo, adds a polished landing page for the web app, rewrites the CI pipeline for cost-efficiency, and resolves all quality gate issues across web, backend, and iOS.

Monorepo Structure

  • Turborepo + Bun workspaces with apps/* and packages/* layout
  • apps/web — Vite + React + TanStack Router + Tailwind v4
  • apps/backend — Convex functions (moved from root convex/)
  • apps/android — scaffold placeholder for future Gradle app
  • apps/ios — existing Xcode project (unchanged)
  • packages/config-eslint — shared ESLint config
  • packages/config-prettier — shared Prettier config
  • packages/config-typescript — shared TSConfig base
  • packages/design-tokens — shared design tokens

Landing Page (apps/web)

  • Neumorphic dark-themed landing page with animated gradients and micro-interactions
  • Responsive layout (mobile-first) with Karla + Sora typography
  • Waitlist CTA with toast notification (slide-up dismiss animation, neumorphic styling)
  • Footer with legal/social links
  • Vercel deployment config with SPA fallback routing
  • Playwright E2E and Vitest unit test setup

Developer Experience

  • bun run dev starts web + Convex backend together (was web-only)
  • bun run format / format:check — Prettier integration across the monorepo
  • bun run lint:fix — ESLint autofix across workspaces
  • bun run ci — full local CI pipeline (lint + typecheck + format:check + test + build)
  • bun run clean — removes all build artifacts and reinstalls cleanly
  • Turbo pipeline uses inputs arrays for precise cache invalidation
  • Added TESTING.md documenting CI strategy, local commands, and caching

CI Pipeline Rewrite (.github/workflows/ci.yml)

Replaced the single-job monolith with a 2-tier, 7-job architecture:

                    quality-gate (ubuntu, ~1min)
                    ┌──────────┴──────────┐
           Linux (cheap)              macOS (10x cost)
     ┌──────┼──────┐──────┐        ┌──────┼──────┐
  backend  web   web    web     ios-build  ios-tests
  tests   tests  build  e2e              (3x sanitizer matrix)

Key optimizations:

  • quality-gate on Ubuntu catches lint/type/format errors in ~1 min — all other jobs depend on it
  • If quality-gate fails, zero macOS minutes are consumed
  • iOS jobs on macos-14 (not macos-15) for lower cost
  • [skip-ios] in PR title skips all macOS jobs for web/backend-only PRs
  • Concurrency group cancels stale runs on same PR
  • Bun dependency cache on all Linux jobs with --frozen-lockfile
  • Reduced timeouts: Linux 10-15 min, macOS 45 min (down from 60)
  • Unique artifact names per CI run attempt to avoid 409 conflicts on re-runs

Backend Fixes

  • Remove all Supabase and Firebase references and artifacts
  • Fix TypeScript errors across all backend Convex functions
  • Re-export groups:listPaginated and groups:leaveGroup
  • Fix group membership check to use canonical member ID and aliases
  • Ensure clearAllForUser removes user from shared groups
  • Stop auto-friending in groups:create
  • Add @edge-runtime/vm dependency for vitest edge-runtime environment
  • Add setup.ts with modules export for convex-test to find _generated directory
  • Add vite dev dependency for test setup types
  • Suppress lint errors for ts-nocheck files

iOS Fixes

  • Add completeAuthenticationAndWait async method for reliable test authentication
  • Fix thread-safety issue in Dependencies.reset() by moving assignment inside lock
  • Add comprehensive SwiftLint config with disabled rules matching codebase patterns
  • Fix SwiftLint violations across source and test files (trailing whitespace, line length, force_try, shorthand operators, etc.)
  • Add missing @EnvironmentObject var store: AppStore declaration in ExpenseDetailView
  • Rename variable g to directGroup for clarity
  • Fix mock service user email in AppStore link request test
  • Remove duplicate commented code causing brace mismatch
  • Revert test assertions to match mock behavior

Codebase Cleanup

  • Apply Prettier formatting (semi, no singleQuote, no trailing comma, printWidth 100, tabWidth 2) across all JS/TS/MD/JSON files
  • Remove verbose comments and install missing deps

Initialize Bun workspaces and Turbo orchestration. Migrate from npm to Bun.
Migrate Convex backend to a dedicated workspace package. Update root convex.json to point to the new location.
Add React/Vite-based web application package to the monorepo. Includes basic routing, Tailwind CSS setup, and testing configuration.
Add basic Android application structure and configuration to the monorepo.
Update GitHub Actions and local test scripts to handle the new monorepo layout. Support running tests and builds across multiple workspace packages using Turbo.
Update README and AGENTS.md to reflect the new monorepo structure. Add migration plan and technical documentation for the new architecture.
- Add slide-up dismiss animation to toast notification
- Style dismiss button with neumorphic recessed-to-raised effect
- Update page title to 'PayBack — Split bills, keep friends.'
- Remove stale variant references from CSS selectors
- Remove em-dash from toast notification
- Place subtitle on its own line for readability
- Add .vercelignore to exclude unnecessary files from deploy
- Remove @payback/design-tokens (unused in source)
- Remove @payback/config-eslint (dev-only, not in git)
- Fixes Vercel build failure from missing workspace packages
- Remove dependency on untracked packages/config-typescript
- Target ES2022 with bundler moduleResolution
- Enable esModuleInterop, strict, skipLibCheck
- Fixes all TypeScript errors on Vercel CI
- Add root prettier.config.mjs and .prettierignore
- Overhaul turbo.json: remove wasteful ^deps, add inputs arrays for
  cache efficiency, add lint:fix/clean/deploy tasks
- Update root scripts: dev now starts web+backend together, add
  format/format:check, lint:fix, clean, deploy commands
- Add lint:fix and clean scripts to all JS workspaces
- Fix web lint glob (remove non-existent tests/ pattern)
- Add passWithNoTests to web vitest config
- Rewrite CI with 2-tier cost-optimized architecture: quality-gate on
  ubuntu blocks all other jobs, iOS on macos-14 with [skip-ios] support,
  granular parallel Linux jobs, Bun cache, concurrency groups
- Add TESTING.md documenting CI strategy and local commands
Apply Prettier (semi, no singleQuote, no trailing comma, printWidth 100,
tabWidth 2) across all JS/TS/MD/JSON files. Pure whitespace and style
changes, no logic modifications.
- Re-export groups:listPaginated and groups:leaveGroup
- Fix group membership check to use canonical member ID and aliases
- Ensure clearAllForUser removes user from shared groups
- Stop auto-friending in groups:create
- Add @payback/config-eslint workspace package
- Add Playwright smoke test
@vercel
Copy link

vercel bot commented Feb 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
payback Ready Ready Preview, Comment Feb 14, 2026 6:11am

@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@AnganSamadder AnganSamadder changed the title Landing Page + CI Fixes feat: monorepo restructure, landing page, and production CI Feb 13, 2026
… PR gating

Sanitizer flags were never passed to xcodebuild — all 3 matrix jobs ran
identical unsanitized tests. Combined with SwiftLint overhead, clean builds,
and sequential test execution, every job timed out at 45 min.

- Compute sanitizer/coverage flags from matrix value (thread/address/none)
- Remove SwiftLint from test jobs (already runs in ios-build)
- Split into build-for-testing + test-without-building (no clean rebuild)
- Enable parallel testing (-parallel-testing-enabled YES)
- Gate thread/address sanitizers to main-only pushes (PRs run none only)
- Gate coverage steps to sanitizer=none only
- Per-sanitizer timeouts (none: 25 min, thread/address: 45 min)
- Update local CI script for parity (two-step build, parallel testing)
- Document local sanitizer testing commands in AGENTS.md
… CI)

test-without-building produced zero output for 30+ min and timed out.
Revert to single xcodebuild test command which actually runs tests.
Keep all other optimizations: correct sanitizer/coverage flags, no
SwiftLint in test jobs, PR gating, parallel testing enabled.
Bump none timeout to 60 min to give tests headroom.
xcpretty was buffering ALL test output, producing zero visible lines
for 2 hours. Remove it so we can see raw xcodebuild output and
determine if tests are running or stuck. Set timeout to 60 min.
Analysis of run 22010253496 showed tests hung for 41 minutes with zero
output when AppStoreEdgeCaseTests and AppStoreBalanceExtendedTests ran
on parallel simulator clones with coverage instrumentation enabled.
Root cause: parallel clones + coverage = resource exhaustion on M1 runner.

Changes:
- Disable parallel testing for coverage (none) job, keep for sanitizers
- Add per-test 120s timeout to kill any individually hanging test
- Bump none job timeout to 90 min as safety net
The 120s per-test timeout was killing AppStoreBalanceExtendedTests and
AppStoreEdgeCaseTests before their setUp() could complete with coverage
instrumentation. This caused Xcode to restart and retry the same tests
in an infinite loop (29 restarts in 86 minutes, zero tests completed).
… to hang

Root cause: Dependencies.reset() acquired stateLock, then called
Dependencies() which calls makeDefaultAccountService() →
getConvexClient() → stateLock.lock() again. NSLock is not reentrant,
so this deadlocked every time. All 52 tests in AppStoreEdgeCaseTests
and AppStoreBalanceExtendedTests call Dependencies.reset() in setUp,
causing them to hang until the per-test timeout killed them (29 crash
cycles consuming the entire 90-min job timeout).

Fix: create the fresh Dependencies instance outside the lock. Also
re-enable parallel testing and reduce timeout to 45 min now that the
actual hang is resolved.
@AnganSamadder AnganSamadder merged commit ef73917 into main Feb 14, 2026
11 checks passed
@AnganSamadder AnganSamadder deleted the feat/landing-page branch February 14, 2026 07:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant