Skip to content

Full-stack hosting examples: React Router 7, TanStack Start, Astro 6#15

Open
netanelgilad wants to merge 7 commits into
mainfrom
claude/session-m669xy
Open

Full-stack hosting examples: React Router 7, TanStack Start, Astro 6#15
netanelgilad wants to merge 7 commits into
mainfrom
claude/session-m669xy

Conversation

@netanelgilad

Copy link
Copy Markdown
Collaborator

Three real flagship example apps for Base44 full-stack hosting (preview) — server-rendered framework apps whose Worker code talks to Base44 through the server SDK, deployed with base44 deploy. Each pins preview builds of the SDK and CLI via npm aliases (@base44/sdknpm:@base44-preview/sdk, base44npm:@base44-preview/cli); they flip to the real packages at GA.

The apps

App Framework What it showcases
Base44 Estates — real-estate agency site React Router 7 (SSR) Edge-cached public SSR listings + dynamic /property/:id pages (Cache-Control: public), RLS-protected inquiries (only the property's agent reads them), strictly-private favorites, hosted-login redirect, an estate-assistant agent
Base44 CRM — private team sales CRM TanStack Start (SSR) Owner-scoped RLS (reps see only their contacts/deals/activities; managers see the team), SSR pipeline dashboard, kanban with optimistic client writes, email/password + Google login, a sales-copilot agent wired to live chat, everything no-store
Meridian — coffee-roaster storefront Astro 6 (SSR) Edge-cached catalog + dynamic product/category pages with a visible rendered-at timestamp (cache HIT/MISS is demonstrable), client cart, authenticated checkout writing real Order entities, per-user order history, a shopping-concierge agent

Shared patterns (deliberate, consistent across all three)

  • Cacheability is the app's concern: public catalog-style pages set public, max-age/s-maxage so the platform's shared edge cache stores them; anything personalized sets private, no-store. Cached HTML never carries per-user content (auth state hydrates client-side).
  • Entities + RLS use the documented rls block ({"data.field": "{{user.email}}"}, user_condition, $or) — e.g. Estates' Inquiry denormalizes the property's agent_email server-side so RLS can scope reads without cross-entity joins.
  • Server-only SDK: createServerClient({ request, env }) runs in loaders/server functions/frontmatter only; verified the service token and server client never appear in the client bundles.
  • Agents are defined in base44/agents/*.jsonc with entity-scoped tool_configs; the CRM surfaces its agent as an in-app chat panel running under the logged-in user's RLS scope.
  • Each app builds green and emits the .wrangler/deploy/config.json contract the CLI deploys from.

Notes

  • fullstack-astro also fixes a real Astro 6 + @astrojs/cloudflare v13 breakage from the scaffold: Astro.locals.runtime.env was removed in Astro 6; env access now goes through import { env } from "cloudflare:workers" (centralized in src/lib/base44.ts).
  • Connectors were deliberately left out: their config format isn't documented yet, and shipping a guessed format would break the apps. Each README notes where a connector would slot in.
  • Root README table updated with the three apps.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9


Generated by Claude Code

… Start, Astro 6)

Real flagship examples for Base44 full-stack hosting (preview), each pinning
preview SDK/CLI builds via npm aliases:

- fullstack-react-router — Base44 Estates: real-estate agency site with
  edge-cached public SSR listings, RLS-protected inquiries/favorites, and an
  estate-assistant agent.
- fullstack-tanstack-start — Base44 CRM: private team sales CRM with
  owner-scoped RLS, pipeline kanban, SSR dashboards (all no-store), and a
  sales-copilot agent.
- fullstack-astro — Meridian: coffee-roaster storefront with an edge-cached
  catalog, dynamic product/category pages, authenticated checkout + orders,
  and a shopping-concierge agent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
@netanelgilad netanelgilad self-assigned this Jul 6, 2026
claude added 6 commits July 6, 2026 14:56
…examples

The platform dispatcher no longer reverse-proxies /login on app domains —
its surface is only /api/apps/* and /ws-user-apps/* — so apps must own
their login page. Google OAuth is also temporarily unavailable on new
base domains (gateway allowlist), so every example is now fully usable
with email/password alone, including new-user sign-up.

- fullstack-react-router (Estates): new /login route (sign-in, sign-up
  with OTP verification via SDK register/verifyOtp, Google OAuth).
  Header button and /favorites, /agent, /seed anonymous redirects now
  target the app-owned /login?from_url=… instead of the removed
  hosted-login paths (redirectToLogin / getLoginUrl).
- fullstack-tanstack-start (CRM): /login gains sign-up + OTP
  verification alongside the existing email/password + Google sign-in.
- fullstack-astro (Meridian): its sign-in links pointed at the platform
  login (wrong user pool, no round trip back) — added an app-owned
  /login page plus same-origin /api/auth/* routes that run the SDK
  server-side and set the session cookie, per the app's conventions.
- READMEs: document that apps own /login; hosted login is only used by
  the edge gate for fully-private apps; Google OAuth on new base
  domains pends gateway allowlist config.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
…ing, remove mock-data fallbacks

Three live fixes across the full-stack examples:

1. Estates /login error boundary (react-router): leaf-route meta() REPLACES
   the root's in RR7, so the base44:app-id/api-url tags only existed on the
   home page; getBrowserClient() then threw during hydration on every other
   route (login, listings, favorites, agent, property). The tags are now
   rendered directly in Layout <head> from the root loader data, guaranteed
   on every document.

2. CRM browser SDK hitting the wrong backend (tanstack-start): the browser
   client was created with createClient({ appId }) and no serverUrl, so the
   SDK defaulted to the production platform origin — kanban drag writes,
   deal/contact/activity forms and the Sales Copilot (whose failure message
   is the reported "base44 deploy" error) all failed. The session server fn
   now threads a runtime-resolved Base44Config { appId, apiUrl } (from the
   Worker env the deploy injects — never build-time env, which --prebuilt
   deploys don't have) through the root context to every browser SDK call.

3. No mock data in render paths (user requirement): removed the silent
   demo-catalog fallbacks from Estates loaders (seed-data now feeds ONLY the
   admin /seed route) and Meridian's store.ts (demo-data.ts deleted). Pages
   render real entity data with honest empty states; read errors surface via
   the error boundary / a thrown 500 instead of being masked. Missing-record
   404s still render not-found pages (Base44Error.status === 404).

All three apps rebuilt, redeployed and live-verified on b44apps.dev.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
…mples

The dispatcher reverse-proxies /api/apps/* (and the /ws-user-apps/*
websocket) on the app's own domain, so the browser SDK must never target
the platform origin directly — serverUrl: "" makes every call same-origin
with zero CORS.

- CRM (tanstack-start): getBrowserClient now hardcodes serverUrl: "";
  Base44Config threads only the runtime-resolved appId (apiUrl removed
  from the type, the session server fn, and the cache key).
- Estates (react-router): getBrowserClient uses serverUrl: "" and no
  longer reads the base44:api-url meta tag; root.tsx stops rendering it.
- Meridian (astro): no browser SDK — its client code only fetches its own
  same-origin /api/auth/* routes; verified clean, no changes.

Server-side createServerClient continues to read BASE44_API_URL from the
Worker env (server-to-platform, not subject to CORS). Verified: no
platform-origin URLs in any built client bundle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
… platform default

The CRM sales_copilot and Estates estate_assistant agents pinned
"model": "anthropic/claude-sonnet-4-20250514", a dated vendor snapshot the
platform's LLM provider no longer serves (backend ProviderError: 404
not_found_error). The platform's agent model allowlist only serves
claude-sonnet-4-6 / claude-sonnet-5 / claude-opus-4-6..4-8 style ids.

Dropping the field resets the stored config to the "automatic" platform
default on the next deploy (the agent-configs bulk PUT fully replaces the
config), matching the Meridian concierge which never pinned a model.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
Part 1 — hybrid rendering showcase:
- New prerendered pages: /about (brand story) and /brewing (five brew
  guides + cheat-sheet), both 'export const prerender = true', emitted as
  static HTML into dist/client and served by the asset layer before any
  Worker code runs. The 404 is now prerendered too (404.html, served with
  a real 404 status for unmatched routes).
- CacheBadge grew a third mode: static pages show 'Prerendered - built at
  <build time>' (frozen until redeploy) vs the SSR pages' 'server-rendered
  at' stamp; data-testid built-at/rendered-at for assertions.
- Layout accepts staticCategories (src/lib/static-nav.ts) since the build
  sandbox has no Base44 backend to fetch the live Category list from;
  header/footer gained Brew Guides + About links.
- build.format 'file' so /about serves 200 directly (about.html) instead
  of a trailing-slash redirect.

Part 2 — Astro 7:
- astro 6.4.8 -> 7.0.6, @astrojs/cloudflare 13.7.0 -> 14.1.1 (the Vite
  8-based major that pairs with Astro 7). Verified: no new Worker
  bindings in the generated wrangler.json (ASSETS only), nodejs_compat
  kept, sessionDrivers.memory() still supported, .wrangler/deploy/config
  emitted as before.
- compressHTML: true keeps v6 whitespace behavior (Astro 7's 'jsx'
  default strips spaces around inline elements on their own line).

README: new hybrid-rendering section (which pages are SSG vs SSR vs
edge-cached, and what the live response headers show), Astro 7 notes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DvhQfqxACcq25XAQRpoSh9
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