This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- @vitejs/plugin-react uses Babel (or oxc when used in rolldown-vite) for Fast Refresh
- @vitejs/plugin-react-swc uses SWC for Fast Refresh
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see this documentation.
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])| Name | Description |
|---|---|
SESSION_SECRET |
Used to sign the Express session cookie. Must be stable in production; the server refuses to start when it is missing. |
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET |
OAuth credentials for Gmail access. |
GEMINI_API_KEY |
API key used for AI-assisted order inference. |
ARDA_TENANT_ID |
Tenant ID for Arda API calls. |
DATABASE_URL |
Postgres connection string (DATABASE_URL) with TLS enabled in production. |
REDIS_URL |
Used for session storage, job persistence, and the distributed Cognito sync scheduler. Required in production. |
POSTMARK_INBOUND_USERNAME / POSTMARK_INBOUND_PASSWORD |
HTTP Basic Auth credentials for /api/inbound/postmark webhook requests. |
INBOUND_CONFIDENCE_THRESHOLD |
Confidence guardrail for auto-syncing forwarded receipts (default 0.78). |
INBOUND_PROCESS_BATCH_SIZE |
Max inbound receipts claimed per worker tick (default 10). |
INBOUND_MAX_RETRIES |
Max transient retry attempts for inbound processing (default 5). |
INBOUND_RETENTION_DAYS |
Days to keep raw inbound email headers/bodies before purge (default 30). |
ENABLE_ACCOUNTING_CONNECTORS |
Feature flag for QuickBooks/Xero integrations (true to enable API routes/UI controls). |
ACCOUNTING_SYNC_INTERVAL_MINUTES |
Scheduled incremental sync interval in minutes (default 15). |
QUICKBOOKS_CLIENT_ID / QUICKBOOKS_CLIENT_SECRET |
OAuth credentials for QuickBooks Online. |
QUICKBOOKS_WEBHOOK_VERIFIER_TOKEN |
HMAC verifier used for POST /api/integrations/webhooks/quickbooks signature checks. |
XERO_CLIENT_ID / XERO_CLIENT_SECRET |
OAuth credentials for Xero. |
FRONTEND_URL / BACKEND_URL |
CORS origin and OAuth callback URL (set both on Vercel / Railway). |
SENTRY_DSN (optional) |
When provided, captured errors are sent to Sentry via @sentry/node. |
ENABLE_COGNITO_SYNC |
Set to true to enable the scheduled GitHub → Cognito sync. |
COGNITO_SYNC_HOUR |
Optional hour (UTC) at which the scheduled sync should run (default 2). |
VITE_API_URL: optional API base URL override. Leave unset in production so the app uses same-origin/authand/apirewrites. No other frontend production env vars are required by default.
npm run build(frontend) – this runstsc -bandvite build. Manual chunking is configured viavite.config.tsto keep the bundle sizes small.npm run build(server) – compiles the Node API viatsc(thestartscript runs the emitteddist/index.js).
- In Vercel Project Settings → General, set Node.js Version to 20.x (this repo enforces
>=20 <21). - Set
FRONTEND_URLto the deployed Vercel domain so OAuth redirects and CORS match. - Set
BACKEND_URLfor OAuth callbacks inserver/src/routes/auth.tsandserver/src/routes/integrations.ts. - Store the Redis URL and Postgres
DATABASE_URLin the platform secrets; both are required before deploying. - If accounting connectors are enabled, configure QuickBooks webhook delivery to
POST /api/integrations/webhooks/quickbooks. - Ensure
ENABLE_COGNITO_SYNCistrueon the instance that should perform the nightly sync and that Redis is reachable so the distributed lock works. - Prefer
/health/readyfor platform readiness checks. It verifies Postgres, Redis availability, and Gemini configuration status, while/healthremains a shallow liveness probe. - Keep Vercel rewrites for
/auth/*and/api/*enabled so browser requests stay first-party. - Runbook: if users hit onboarding errors like
Not authenticated, first verifyVITE_API_URLwas not set to the Railway URL in Vercel.
- When
SENTRY_DSNis set, Sentry picks up HTTP errors and uncaught exceptions automatically. The API logs the Cognito sync status on startup and reports Redis issues to the server logs.
Use these commands to avoid accidental dirty-state drift:
npm run worktree:statusnpm run worktree:check-cleannpm run worktree:backup-cleannpm run hooks:install
Notes:
worktree:check-cleanfails if tracked or untracked files are present.worktree:backup-cleancreates a local backup branch (codex/wip-backup-<timestamp>), commits all current changes, then resets and cleans the current branch.hooks:installconfigurescore.hooksPath=.githooks.- The repo hooks block direct commits to
mainby default and block push when the worktree is dirty. - For emergency commits on
main, setALLOW_MAIN_COMMIT=1for that command only.