Frontend Overview

Table of Contents

What Vext Frontend Is

Vext Frontend is the built-in full-stack React 19 experience for Vext projects. The URL still belongs to src/routes/**; the route handler prepares server data and calls res.render() to render a page from src/frontend/pages/**.

Use it when one app needs APIs, server-rendered pages, and browser interaction. A page request follows this path:

Browser GET / → server route → prepare props → res.render("index", props)
              → React server HTML → browser hydration (when enabled)

Page components also run during SSR, so reading browser globals such as window while rendering can fail. Keep database and upstream calls in routes/services. Props are exposed to the browser and should contain only data the page needs.

Use --template api --frontend none when the project is API-only.

Create a Full-stack Project

npx vextjs create my-app
cd my-app
npm run dev

Install a Node.js and npm version satisfying the current Vext package; see the general quick start. The default command generates a TypeScript full-stack React app and runs npm install automatically. If installation fails or --skip-install is used, run npm install in the project before starting. Open the address printed by the terminal, normally http://localhost:3000/. For an API-only app:

npx vextjs create my-api --template api --frontend none

Project Structure

These are the main files in the default TypeScript full-stack starter; see Project Structure for configuration, types, and generated output.

src/
  config/
    default.ts
  routes/
    index.ts
  services/
    example.ts
  frontend/
    pages/
      index.tsx
      layout.tsx
      _document.html
      error/
        default.tsx
    components/
      AppShell.tsx
    styles/
      index.css
    locales/
      en-US.ts
public/
  vext-mark.svg
  favicon.svg

The important boundary is physical:

  • src/routes/** and src/services/** run on the server.
  • src/frontend/pages/** and src/frontend/components/** are UI sources used by SSR and browser builds according to render mode; a page file alone does not register a URL.
  • Do not import services, database clients, secrets, or Node-only modules from frontend files.
  • public/** holds fixed-path files copied into the frontend build and recorded in the deploy manifest; recording them does not upload them to a CDN.
  • Add src/frontend/assets/**, other languages, and business pages as needed; they are not already in the default starter.

First Page

In a newly created full-stack app, replace both the home page and its route with the complete examples below. Replacing the whole original route removes its starter API handlers; retain them if needed. No additional business service is required.

// src/frontend/pages/index.tsx
export default function HomePage(props: { greeting: string }) {
  return <main>{props.greeting}</main>;
}

Render it from a route:

// src/routes/index.ts
import { defineRoutes } from "vextjs";

export default defineRoutes((app) => {
  app.get("/", {}, (_req, res) => {
    res.render("index", { greeting: "Hello from Vext" });
  });
});

Visit / and expect Hello from Vext in the HTML. If the response is HTML without that text, inspect terminal errors, frontend enablement, and the page ID. See Getting Started for a complete walkthrough.

res.render(page, props?, options?) has three arguments:

ArgumentMeaning
pagePage id under src/frontend/pages/**, without extension. admin/dashboard.tsx becomes "admin/dashboard".
propsJSON-safe page data, written into the document and reused by the browser in normal hydration mode; do not pass database connections, functions, or private config.
optionsPer-render options such as status, head, ssr, layout, layoutData, messages, and nonce; see focused pages for route-level freshness and hydration declarations.

Current Capabilities

These features have separate conditions. React 19 or the default starter alone does not imply that every feature is enabled:

CapabilityMain condition or boundary
SSR, hydration, layouts, error pagesEnable frontend and bind an explicit render route; page files do not create URLs.
Streaming SSRGlobal default is buffered; the full-stack starter explicitly sets streaming: "auto". No-hydration mode has separate limits.
Frontend i18nEnable frontend i18n and provide dictionaries. The starter has only en-US and does not translate content automatically.
Fast Refresh and Render RefreshDevelopment-only, with separate settings and trigger scopes.
Splitting, styles, assets, budgetsThe frontend build produces resources and reports; budgets need explicit thresholds.
CDN upload and hydration validationRequire a deployment target or an accessible running site; project creation does not perform them.
Same-route navigation and static generationRequire the matching page protocol, route declarations, and output; they do not imply RSC or Server Actions.

See Boundaries and Roadmap for details. Browser assets and server output must come from matching builds. Deploying static files does not replace the Vext server process.

Reading Paths

Use the left navigation as the main map. It is intentionally split into concept, task, and reference layers.

NeedStart here
First successful pageGetting Started
Understand URL and page ownershipRouting and Pages
Choose SSR, hydration, or CSRRendering Modes
Pass service data to pagesData Flow
Build nested shellsLayouts and Components
Debug SSR outputSSR
Style a component with variants or CSS variablesVext JSCSS
Debug browser attach/mismatchHydration
Build a client-router sub-appCSR and SPA Fallback
Cache render dataRender Data and Cache
Tune development feedbackFast Refresh and Render Refresh
Ship frontend assetsBuild and Deploy and Static Assets and CDN
Keep JS smallCode Splitting and Performance Budgets
Validate production hydrationHydration Validation
Find config fieldsConfiguration
Check current boundariesBoundaries and Roadmap

The Frontend integration page connects the backend guide to this section and retains older links.