Web Surface
The Schift web application is an Astro project that serves public marketing pages, localized docs, SEO content, and the authenticated dashboard under one browser-facing surface.
Route map
Section titled “Route map”| Routes | Purpose |
|---|---|
/, /pricing | Marketing landing pages |
/docs/* | Docs shell for quickstart, SDK, CLI, concepts, and web reference |
/blog/*, /compare/*, /guides/* | SEO and educational content |
/ko/*, /jp/* | Localized entry points for Korean and Japanese |
/app, /app/workflows, /app/oauth-callback | Authenticated dashboard shell and workflow builder entry points |
Note: The
/app/*routes are excluded from the public sitemap because they require authentication.
Stack and runtime
Section titled “Stack and runtime”| Piece | Current choice |
|---|---|
| Site framework | Astro 6 |
| Interactive UI | React 19 |
| Styling | Tailwind CSS 4 plus local UI primitives |
| Localization | Astro i18n with en, ko, and jp |
| Deploy target | Cloudflare Pages with dist/ output from npm run build |
Local development
Section titled “Local development”Requirements:
- Node.js
>=22.12.0 npm
cd schift-webnpm installnpm run devThe default dev server runs at http://127.0.0.1:4324. To run the Connect surface on a separate port:
npm run dev:connectConnect uses http://127.0.0.1:4325 by default.
Runtime configuration
Section titled “Runtime configuration”The web app reads browser-exposed environment variables for API requests and build-time SEO artifacts:
| Variable | Purpose |
|---|---|
PUBLIC_API_URL | Product API origin |
PUBLIC_AUTH_API_URL | Auth API origin (falls back to PUBLIC_API_URL for local compatibility) |
PUBLIC_CONNECT_ORIGIN | Connect app origin allowed as a post-auth return target |
PUBLIC_COOKIE_DOMAIN | Shared auth cookie domain for app/connect subdomains |
PUBLIC_COOKIE_PREFIX | Prefix for the JS-readable CSRF cookie used by dashboard auth |
PUBLIC_SSO_SECURITY_URL | Optional HTTPS URL for the account-security page linked from 2FA settings |
PUBLIC_GA_MEASUREMENT_ID | Google Analytics measurement ID (override for non-production builds) |
PUBLIC_SITE_URL | Canonical public web origin, required at build time |
PUBLIC_WIDGET_BROWSER_URL | Browser module URL shown in widget embed snippets |
PUBLIC_WIDGET_NPM_PACKAGE | NPM package name shown in React/Next widget install snippets |
Note: If you do not set both
PUBLIC_API_URLandPUBLIC_AUTH_API_URLin production, different parts of the web app can talk to different backends.
Dashboard auth uses backend-set httpOnly cookies plus JS-readable CSRF and return-path cookies derived from PUBLIC_COOKIE_PREFIX. Set PUBLIC_COOKIE_DOMAIN only when app and Connect share a parent domain, and set PUBLIC_CONNECT_ORIGIN when Connect needs to return users to its own origin after login.
Project boundaries
Section titled “Project boundaries”The web repo owns browser-facing UI only. Reusable product contracts live in schift-api, source sync execution lives in schift-worker, and search behavior lives in schift-db.
| Surface | Location | Responsibility |
|---|---|---|
| Public site | apps/www | Marketing, docs, pricing, and content routes |
| Dashboard | apps/app | Authenticated product screens and /app/api/* BFF handlers |
| Connect/onboarding | apps/connect | Source selection, OAuth handoff, business registration, /connect/api/* BFF handlers |
Note: Do not put reusable API contracts in the web repo. Web-local handlers are only for session bootstrap, OAuth returns, onboarding draft state, and screen-specific aggregation.
Deployment
Section titled “Deployment”The site is built as a static Astro site. Cloudflare Pages serves the generated dist/ directory configured in wrangler.toml.
npm run buildnpm run previewNote: The production build requires
PUBLIC_SITE_URLto generate correct SEO artifacts.