Skip to content
Docs Try Aspire
Docs Try

Vite React + FastAPI

Aspire sample
TypeScript AppHost

Clone, run, and explore this sample

Todo app with React frontend and Python FastAPI backend using YARP for unified routing.

DockerJavaScriptNode.jsPythonTypeScript
AppHost

The entry point that composes every resource and dependency in this sample's distributed application.

View on GitHub
apphost.mts
import { createBuilder } from "./.aspire/modules/aspire.mjs";
const builder = await createBuilder();
const executionContext = await builder.executionContext();
const dc = await builder.addDockerComposeEnvironment("dc");
const api = await builder.addUvicornApp("api", "./api", "main:app")
.withHttpHealthCheck({ path: "/health" })
.withComputeEnvironment(dc);
const frontend = await builder.addViteApp("frontend", "./frontend")
.withReference(api);
await builder.addYarp("app")
.withConfiguration(async (yarp) =>
{
const apiCluster = await (await yarp.addClusterWithDestination("api", "https://api"))
.withHttpClientConfig({ dangerousAcceptAnyServerCertificate: true });
await (await yarp.addRoute("api/{**catch-all}", apiCluster))
.withTransformPathRemovePrefix("/api");
if (await executionContext.isRunMode())
{
const frontendCluster = await yarp.addClusterFromResource(frontend);
await yarp.addRoute("{**catch-all}", frontendCluster);
}
})
.withReference(api)
.withExternalHttpEndpoints()
.withBrowserLogs()
.publishWithStaticFiles(frontend)
.withComputeEnvironment(dc)
.withExplicitStart();
await builder.build().run();

Todo app with React frontend and Python FastAPI backend using YARP for unified routing.

Run Mode:

flowchart LR
    Browser --> YARP
    YARP -->|/api/*| FastAPI[FastAPI Backend]
    YARP --> Vite[Vite Dev Server<br/>HMR enabled]

Publish Mode:

flowchart LR
    Browser --> YARP[YARP serving<br/>Vite build output<br/>'npm run build']
    YARP -->|/api/*| FastAPI[FastAPI Backend]
  • addUvicornApp: Python FastAPI backend with uv package manager
  • addViteApp: React + TypeScript frontend with Vite
  • addYarp: Single endpoint with path-based routing
  • withTransformPathRemovePrefix: Strip /api prefix before forwarding
  • publishWithStaticFiles: Frontend embedded in YARP for publish mode
  • Dual-Mode Operation: Vite HMR in run mode, Vite build output in publish mode
  • Polyglot Fullstack: JavaScript + Python working together
Terminal window
aspire run
Terminal window
aspire run # Run locally
aspire deploy # Deploy to Docker Compose
aspire do docker-compose-down-dc # Teardown deployment

YARP with Path Transform - Strip /api prefix before forwarding to FastAPI:

const api = await builder.addUvicornApp("api", "./api", "main:app")
.withHttpHealthCheck({ path: "/health" });
const frontend = await builder.addViteApp("frontend", "./frontend")
.withReference(api);
await builder.addYarp("app")
.withConfiguration(async (yarp) =>
{
const apiCluster = await yarp.addClusterFromResource(api);
await (await yarp.addRoute("api/{**catch-all}", apiCluster))
.withTransformPathRemovePrefix("/api");
if (await executionContext.isRunMode.get())
{
const frontendCluster = await yarp.addClusterFromResource(frontend);
await yarp.addRoute("{**catch-all}", frontendCluster);
}
})
.publishWithStaticFiles(frontend);

Path Transform Example:

  • Client: GET /api/todos
  • YARP receives: /api/todos
  • Transform strips: /api
  • FastAPI receives: GET /todos

This sample intentionally keeps the FastAPI todo endpoints public and unauthenticated for instructional use. The /api/todos endpoints are demo endpoints, not a production API security model.

  • Todo data is stored in process memory and is lost when the API restarts. The API caps the in-memory list at 100 todos, limits todo titles to 200 characters, requires non-empty titles, and bounds list responses with skip and limit query parameters.
  • The sample does not include authentication, authorization, CSRF protection, or rate limiting.
  • For production, add an appropriate identity provider and authorization checks, persistent storage, CSRF protections if browser credentials are used, rate limiting/quotas, request logging/monitoring, and deployment-specific network protections.

Relevant references:

Preview

Sample screenshots

Select the image to zoom in.

Screenshot of the Todo App UI for the Vite React + FastAPI sample
Screenshot of the Todo App UI for the Vite React + FastAPI sample