Skip to content

Member app, Outhere HQ and the pnpm and Turborepo monorepo - #6

Merged
EmotiveImpact merged 13 commits into
mainfrom
claude/web-app-build-nig9rl
Oct 16, 2026
Merged

EmotiveImpact merged 13 commits into
mainfrom
claude/web-app-build-nig9rl

Conversation

@EmotiveImpact

@EmotiveImpact EmotiveImpact commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Requested by Edem · project thread

Before: Outhere only had the phone app. The web app and the staff tools existed only as a clickable mockup, and the repository was a single npm project.

After: apps/app is the member app. It covers every page in the mockup: home, feed, battles, pick-ups, club chat, calendar, league, clubs, my profile, membership and Club HQ (members, runs and check-in, page and QR kit, club fund). It also has the public pages people reach from a link or QR code: club pages at /<club>, the join flow, Outhere Locals and public profiles at /@handle. apps/admin is Outhere HQ, the staff app. The repository is now a pnpm and Turborepo monorepo, and apps/web is left free for the website.

Both apps run on example data until the Supabase variables are set. After that they read and write through SupabaseData, with email link sign in.

How

  • Workspace
    • pnpm workspaces with Turborepo tasks (dev, build, typecheck, test, lint), plus a shared tsconfig.base.json and ESLint config.
    • packages/core holds the types, rules (including RESERVED_SLUGS and canPostStory), the OuthereData interface, and the example and Supabase sources. packages/ui holds the shared components and the stylesheet.
    • apps/mobile still installs with npm for now: one of its dependencies is a GitHub tarball, and its patches and overrides move in the same change.
  • Member app
    • React Router in framework mode with server rendering, on Vite. Every write goes through one /act action, and pages reload their data after it.
    • Built files and images live under /_app/, so weouthere.app can pass any path it doesn't own through to the app.
  • Payments: web memberships use Stripe Checkout. A signed /webhooks/stripe endpoint writes subscriptions, and the database then sets the ring and pays the club.
  • Schema: packages/core/src/supabase/SCHEMA_GAPS.md lists what the schema on Outhere mobile app, every prototype screen, on Supabase #4 still needs before every screen shows real numbers.
  • CI: .github/workflows/app.yml and admin.yml run typecheck, tests, lint and build for each app and the packages it uses.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp

Replaces the old Anything web app with a workspace for the new web app,
admin and shared packages. packages/core holds the domain types, the game
and money rules, the data source interface and a typed mock.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
Every page of the web app mockup as a React Router app with server
rendering: home, feed, battles, pick-ups, club chat, calendar (with an
iCal feed), league, clubs, my profile, membership and Club HQ (members,
runs and check-in, page and QR kit, club fund), plus the public pages:
club pages, the join flow, Outhere Locals and public profiles at /@handle.

Outhere HQ (apps/admin) covers the overview, club verification, fair
play, seasons and draws, and the audit log.

Both run on example data until the Supabase variables are set, then on
the SupabaseData source with email link sign in. Stripe Checkout and a
signed webhook that writes subscriptions handle web memberships.
SCHEMA_GAPS.md lists what the schema still needs.

CI runs typecheck, tests and build for the web workspace.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
On example data the join flow keeps the mockup's Apple, Google and phone
buttons. With real data, signed-out visitors now sign in by email link
and come back to the pace step; signed-in members just continue.
Before this, a signed-out visitor was told "You're in" without joining.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
- Captains can add a club run or walk from Club HQ (createRun), which
  the mockup only described.
- The Sunday reveal replays the viewer's own last derby (lastReveal)
  instead of a fixed Peckham result; home previews this week's scores.
- Story labels, the home club pill and RSVP messages come from the
  member's own club and run, not from the example data.
- Only Pro and Black members post stories (canPostStory); Free members
  get a Go Pro prompt where the post button was.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
…/app

- apps/web becomes apps/app (@outhere/app), leaving apps/web for the
  website. apps/admin, packages/core and packages/ui stay where they are.
- pnpm workspaces with a flat node_modules (what Expo expects), Turborepo
  tasks (dev, build, typecheck, test, lint), a shared tsconfig.base.json
  and a shared ESLint config. CI runs per app.
- apps/mobile stays on npm for now: one dependency is a GitHub tarball,
  and its patch-package patches and npm overrides move in the same change.
- The member app keeps its built files, images and favicon under /_app/
  and loads its full route list up front, so weouthere.app can pass any
  path it doesn't own through to it. The website's top-level paths are
  now reserved club slugs.
- Stripe return links use SITE_URL; Outhere HQ's link back to the app is
  VITE_APP_URL.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
@EmotiveImpact EmotiveImpact changed the title Web app and Outhere HQ, built from the approved mockup Member app, Outhere HQ and the pnpm and Turborepo monorepo Oct 15, 2026
@EmotiveImpact
EmotiveImpact marked this pull request as ready for review October 15, 2026 12:42
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
@vercel

vercel Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
outhere-site Ignored Ignored Preview Oct 15, 2026 3:12pm UTC

Copy link
Copy Markdown
Owner Author

The Vercel outhere-site deployment failing here isn't caused by this PR. That project builds the website from apps/site, and this branch has no apps/site folder: the website lives on its own branch. It also can't build on main, which doesn't have the folder either.

Under the new layout the website goes in apps/web. Once the website branch lands, the project's Root Directory setting should change to apps/web, and an Ignored Build Step such as npx turbo-ignore will skip branches that don't touch the site. The member app's own checks (Member app and Outhere HQ) both pass.


Generated by Claude Code

The root vercel.json belongs to the website, so the member app and HQ
projects must build from apps/app and apps/admin. HQ gets its own
vercel.json so page paths fall back to index.html.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
Anyone in the UK can join, so the web app no longer assumes London.
Cities (launch nights in the ten biggest, smaller towns playing for their
region) drive Find clubs, the league's club table and areas, the
calendar's city scope, feed and home area cards, club pages, profiles
and the HQ verification and fair play filters. Cities without a tile
map show a ranked list of areas instead.

Club links stay short (weouthere.app/<club>) with no clashes: the
reserved list now covers future page words, UK nations, regions and
cities, and suggestClubSlug puts the city on the end when two clubs
share a name.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
…at's left

Maps SupabaseData onto the database thread's web_gaps migration (types copied
from the mobile branch at 88966e3): private profiles and profile cards, pace
groups and join requests, club tags, filters and renames, badges, chat
reactions, unread counts and channel descriptions, area step totals on home,
the feed, the league and the reveal, staff actions through verify_club,
review_steps, remove_from_squad and set_reveal_held, notification faces,
pick-up activity, stakes in words and five day battles.

SCHEMA_GAPS.md now lists only what the schema still lacks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
… closest town to 100

Reads city_eligible_counts and cities.image_path (types copied from the
mobile branch at 50282c1). The rising towns card picks the viewer's own place
if it still plays for its region, else the closest in their region, else the
closest anywhere.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
Wires the second web gaps migration (types copied from the mobile branch at
7291756): pick-ups near you and posting with a rough location, open battle and
Locals pick-ups, squad numbers, averages and turnout, season and week points,
area leaders, reveal movement and squad places, plans from the database
(monthly only where there is no yearly price), public club leaders, turnout,
fund totals and gallery, the cover library, poster scans traced through
/join/<club>?c=<code>, run crew, leaders-only channels, fund spending,
treasurer, kit sales, answering Locals offers, daily actives in HQ, and
verification evidence, manual checks and decisions.

SCHEMA_GAPS.md now lists only what is left open on purpose and what the apps
must do for the new tables to fill.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
Types copied from the mobile branch at 96f67b7. A city's "launch" now means
it has a launch night (cities.launch_night) rather than that it plays as
itself, and whether its parts are boroughs or areas comes from boroughs.kind.
The yearly prices are in the plans table, so the gaps list only asks for the
matching Stripe prices.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjgiGhtizcV8QSXPvEyErp
@EmotiveImpact
EmotiveImpact merged commit d09aa61 into main Oct 16, 2026
6 checks passed
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.

2 participants