MahalliMahalli Handbook
Session handoffs

Foundation session — 2026-09-18

State of the repository after the foundation session, what was verified, what is pending, and how to resume.

Foundation session — 2026-09-18

This page is the resume point for the next working session. It records the state of the tree, what was verified with evidence, and what still needs the owner.

Repository state

  • Branch claude/foundation/supastarter-seed, uncommitted (164 modified, 47 deleted, 15 new paths). No origin remote yet; upstream = supastarter/supastarter-nextjs (shallow clone, HEAD fecf16b, 2026-09-17).
  • Root package renamed to mahalli; workspaces apps/*, packages/*, modules/*, tooling/*.
  • New packages: @repo/sms, @repo/core, @repo/module-registry; new files tooling/tailwind/glass.css, packages/ui/lib/direction.ts, packages/utils/lib/phone.ts, packages/payments/provider/moyasar/, packages/i18n/translations/ar/, apps/marketing/modules/home/lib/contact-action.ts, docs/**.
  • CHANGELOG.md has a "Mahalli — Unreleased" section on top of the upstream changelog.

Verified in this session (evidence)

CheckResult
pnpm format:check / pnpm lintpass (lint: inherited warnings only)
pnpm type-check22/22 tasks
pnpm test (vitest)99/99 (@repo/api 31, saas 26, marketing 32, @repo/permissions 6, @repo/sms 4)
Cohesion audit (branding leftovers, physical-direction classes, i18n key parity en↔ar, Arabic in docs, glass tokens/utilities)clean
Glass renderingscreenshots reviewed: marketing light/dark/mobile, pricing, login ar/en dark, signup, docs; overflowX = 0 on 390px
Phone OTP loginend to end on local Postgres: non-Saudi number rejected client-side, OTP sent through the console SMS provider, verify creates a session with phoneNumberVerified = true
Handbookapps/docs renders this folder

Not exercised: organization creation + branded empty dashboard flow, trial billing (needs a PSP that serves Saudi merchants), Playwright e2e suites (pnpm --filter saas e2e needs the app on port 3000).

Local development notes

  • Local Postgres 17 (Homebrew) on localhost:5432, database mahalli created and pushed with pnpm --filter @repo/database push.
  • .env.local is gitignored: DATABASE_URL=postgresql://postgres@localhost:5432/mahalli, locally generated BETTER_AUTH_SECRET, MAIL_PROVIDER=console, SMS_PROVIDER=console, PAYMENTS_PROVIDER=stripe.
  • Ports 3000/3001 are used by other projects on this machine. Run from the repo root so .env.local loads:
NEXT_PUBLIC_SAAS_URL=http://localhost:3100 NEXT_PUBLIC_MARKETING_URL=http://localhost:3101 \
  pnpm exec dotenv -c -- pnpm --filter saas exec next dev --port 3100
NEXT_PUBLIC_SAAS_URL=http://localhost:3100 NEXT_PUBLIC_MARKETING_URL=http://localhost:3101 \
  pnpm exec dotenv -c -- pnpm --filter marketing exec next dev --port 3101
pnpm --filter docs dev   # port 3002
  • Stop only Mahalli servers by port (3100, 3101, 3002); never by a broad next dev pattern.
  • agentRules: false is set in every next.config.ts so next dev does not generate per-app AGENTS.md/CLAUDE.md.

Conventions established (see AGENTS.md)

  • English for docs, comments, commits; product UI Arabic-first (ADR-0009).
  • Glass contract names are stable API (docs/design/glass-design-system.md).
  • Providers (mail, SMS, payments) are selected by env and must initialise lazily (MAIL_PROVIDER, SMS_PROVIDER, PAYMENTS_PROVIDER).
  • Glossary in Arabic UI: محل (physical shop), المنشأة (organization), الواجهة (storefront), دومين, الباقة, رمز التحقق, مفتاح المرور.
  • Roles in @repo/core mirror Better Auth (owner | admin | member); finer merchant roles come later through Permix.

Pending owner decisions

Q1 name/domain, Q2 PSP (Tabby/Tamara support + partner programme), Q5 Postgres region (PDPL), Q12 deployment target, Q13 Moyasar recurring model — all in 08-open-questions.md.

Suggested next steps

  1. Create the GitHub origin, commit this branch, open the PR (owner request required for commit/merge).
  2. Decide Q2/Q13, then implement the Moyasar provider against the same interface as Stripe.
  3. Exercise onboarding → organization creation → dashboard in ar, then Phase 1 (sites + payments).

On this page