Putnami
DocsGitHub

Licensed under FSL-1.1-MIT

Getting Started
Concepts
How To
Build A Web App
Build An Api Service
Share Code Between Projects
Configure Your App
Add Persistence
Add Authentication
Add Background Jobs
Develop With Ai
Structure Business Logic With Di
Upgrade Putnami
Principles
Tooling & Workspace
Workspace
Cli
Jobs & Caching
Extensions
Templates
Error Handling
Frameworks
Typescript
ExtensionOverviewWebReact RoutingForms And ActionsStatic FilesApiErrors And ResponsesConfigurationLoggingHttp And MiddlewareDependency InjectionPlugins And LifecycleSessionsAuthPersistenceEventsStorageCachingWebsocketsTestingHealth ChecksTelemetryProto GrpcSmart ClientSchema
Go
ExtensionOverviewHttpDependency InjectionPlugins And LifecycleConfigurationSecurityPersistenceErrorsEventsStorageCachingLoggingTelemetryGrpcService ClientsValidationOpenapiTesting
Python
Extension
Platform
Ci
  1. DocsSeparator
  2. How ToSeparator
  3. Build A Web App

Build a web app

You will create a React web app with Putnami, explore its structure, and add a new page with server-side data loading.

Steps

1) Create the app

putnami init --workspace my-workspace --project web
cd my-workspace

This scaffolds a full React SSR application from the typescript-web template, with file-based routing, a layout, pages, and a client-side counter component.

2) Run it

putnami serve web

Open http://localhost:3000. You see the welcome page with navigation to About and Guestbook pages.

3) Explore the project structure

The scaffolded project lives in packages/web/:

packages/web/
├── src/
│   ├── main.ts               # Application entrypoint
│   ├── serve.ts               # Server bootstrap
│   ├── app/
│   │   ├── layout.tsx         # Root layout (nav, theme toggle)
│   │   ├── page.tsx           # Home page
│   │   ├── about/page.tsx     # About page
│   │   ├── guestbook/
│   │   │   ├── page.tsx       # Guestbook page
│   │   │   ├── loader.ts      # Server-side data loader
│   │   │   └── action.ts      # Form action handler
│   │   ├── error.tsx          # Error boundary
│   │   └── not-found.tsx      # 404 page
│   └── components/
│       └── counter.tsx        # Client-side interactive component
└── test/
    └── app.test.ts

4) Add a new page

Create packages/web/src/app/hello/page.tsx:

import { page } from '@putnami/web';
import { Heading, Text } from '@putnami/ui';

export default page().render(function HelloPage() {
  return (
    <>
      <Heading level={1}>Hello</Heading>
      <Text as='p' color='secondary'>This is a new page.</Text>
    </>
  );
});

Navigate to http://localhost:3000/hello. File-based routing picks it up automatically.

5) Load data from the server

Create packages/web/src/app/hello/loader.ts:

import { loader } from '@putnami/web';

export default loader(async () => {
  return { message: 'Hello from the server', timestamp: new Date().toISOString() };
});

Update packages/web/src/app/hello/page.tsx to use the loaded data:

import { page, useLoaderData } from '@putnami/web';
import { Heading, Text } from '@putnami/ui';

export default page().render(function HelloPage() {
  const { message, timestamp } = useLoaderData<{ message: string; timestamp: string }>();

  return (
    <>
      <Heading level={1}>{message}</Heading>
      <Text as='p' color='secondary'>Loaded at {timestamp}</Text>
    </>
  );
});

The loader runs on the server before rendering. The data is typed and available via useLoaderData.

Result

You have a React SSR app with layout, file-based routing, and server-side data loading. The template gave you a working starting point — you extended it with a new page and a loader.

Next steps

  • Check the existing guestbook/ page for an example of form actions with action.ts
  • See the components/counter.tsx for a client-side interactive component
  • Add persistence for database-backed data
  • Add authentication to protect routes

Companion sample: typescript/samples/03-web — a runnable project covering pages, layouts, loaders, actions, and forms. Run putnami serve @example/web from the workspace root.

On this page

  • Build a web app
  • Steps
  • 1) Create the app
  • 2) Run it
  • 3) Explore the project structure
  • 4) Add a new page
  • 5) Load data from the server
  • Result
  • Next steps