Hosted web + backend home for heydex.ai.
This repo owns the DexDiff hosted contract:
- browser auth and registration
- Dex Pi linking
- review sessions and publish
- public profiles and public diff browse
- adoption metadata APIs
It does not own the long-term portable /diff-* command runtime. That belongs in dex-core. dex-pi is reference material for the current Dex Pi bridge, not the final runtime owner.
React-owned routes:
/connect//diff//diff/profile//diff/review//diff/@:handle/
Static/editorial routes still served from repo HTML:
//privacy//diff/community//diff/company//diff/love-letters//diff/roadmap//diff/welcome//diff/admin//diff/@dave/snapshot
Read docs/ROUTES.md before changing route ownership.
Frontend:
- Vite + React app mounted from
index.html - Browser router handles the exact product paths above
- unknown paths intentionally render nothing so static surfaces can own them
- live edge routing is Caddy, mirrored in
ops/Caddyfile.heydex
Backend:
- Convex auth + database in
convex/ - browser auth uses hosted OAuth providers
- the website lives on
https://heydex.ai - Convex HTTP actions are exposed on
https://api.heydex.ai - Dex Pi auth uses
https://api.heydex.ai/api/connect/redeemto exchange a short sign-in code for a session token - Dex Pi review publish uses that session token via
https://api.heydex.ai/api/review/create
Identity model:
- Convex
tokenIdentifierremains the canonical backend identity key - CLI clients no longer carry raw
tokenIdentifier - mutations now resolve the viewer from server-side auth and sync
tokenIdentifieron the stored user record when needed
Read docs/ARCHITECTURE.md for the end-to-end flow.
Prereqs:
- Node 18+
- npm
Env:
VITE_CONVEX_URL=https://<your-convex-deployment>.convex.cloud
CONVEX_DEPLOYMENT=dev:<your-deployment-name>
CONVEX_URL=https://<your-convex-deployment>.convex.cloud
CONVEX_SITE_URL=https://<your-convex-site>.convex.siteRecommended local setup:
.env.localis for normal local development- point it at the dev Convex deployment, not production
Example:
CONVEX_DEPLOYMENT=dev:brave-ibex-877
CONVEX_URL=https://brave-ibex-877.eu-west-1.convex.cloud
CONVEX_SITE_URL=https://brave-ibex-877.eu-west-1.convex.site
VITE_CONVEX_URL=https://brave-ibex-877.eu-west-1.convex.cloudDo not point local Vite at production unless you explicitly want to test against live data.
Run:
npm install
npm run convex:dev
npm run devVite runs on http://localhost:3000.
Hosted backend:
npm run convex:deployHosted frontend routes on the VPS:
./deploy.sh
./deploy.sh --dry-run
./deploy.sh --skip-testsWhat deploy.sh actually does:
- Runs
./test-production.shunless skipped - Builds the React app
- Creates separate
/diff/and/connect/copies with route-scoped<base href>values - Rsyncs those builds to staging
- Promotes the built app into both
/diff/and/connect/ - Overlays the static editorial subdirectories listed in
deploy.sh - Runs
npm run db:ensure
It does not deploy the root marketing landing.
The live edge host is currently ubuntu@57.129.134.24.
The checked-in mirror of the live route precedence is:
ops/Caddyfile.heydex
Read docs/DEPLOYMENT.md before touching deploy behavior.
Quick hosted smoke check:
./test-production.sh https://heydex.aiThis currently verifies:
/connect//diff//diff/profile//diff/review//diff/@route-smoke/
TEST_SETUP.md covers the real remaining gaps.
Allowed-environment API host smoke:
E2E_ALLOW_LIVE_API_SMOKE=1 npm run smoke:api:prodThat path is intentionally opt-in because direct probes to api.heydex.ai can still be blocked by Cloudflare from untrusted environments.
Browser E2E harness:
npm run e2e:install
npm run e2eThe seeded Playwright flow expects:
E2E_BASE_URLE2E_API_BASE_URLE2E_TEST_SECRET
The optional live Google auth smoke also expects:
E2E_GOOGLE_EMAILE2E_GOOGLE_PASSWORD- optional
E2E_GOOGLE_AUTH_STATE_PATH
Google auth note:
- the hosted website should use the web OAuth client via
AUTH_GOOGLE_CLIENT_ID/AUTH_GOOGLE_CLIENT_SECRET - do not point hosted Convex Auth at the desktop OAuth client; that client has no redirect URI allowlist and will break browser sign-in
Refresh the saved Google auth session:
npm run e2e:google:redirect-uri
npm run e2e:google:setupRun the reusable Google auth smoke:
npm run e2e:googlesrc/App.jsx- canonical React route mapsrc/pages/ConnectPage.jsx- web auth + CLI linking UIsrc/pages/ReviewPage.jsx- review/publish flowsrc/pages/PublicProfilePage.jsx- dynamic public profile routeconvex/connect.ts- code exchange + CLI session token issuanceconvex/review.ts- review session lifecycleconvex/users.ts- registration/profile/account lifecycleconvex/viewer.ts- server-side viewer resolution helpersdeploy.sh- VPS deploy logic
AGENTS.mddocs/ARCHITECTURE.mddocs/ROUTES.mddocs/DEPLOYMENT.mddocs/KNOWN_DEBT.md