Point0by 1gr14
  • Меню
    • GitHub
    • Блог
  • Introduction
    • Overview
    • Getting Started
    • Full Overview
    • Benchmarks
    • Points
  • Points
    • Page
    • Layout
    • Component
    • Provider
    • Mountable
    • Query
    • Infinite Query
    • Mutation
    • Action
    • Root
    • Base
    • Plugin
  • Methods
    • Validation
    • Loader
    • Context
    • Middleware
    • Loading & error
    • .with
    • Mapper
    • Transformer
    • Stage Methods
  • Core
    • Navigation
    • SSR
    • RSC
    • Request
    • Response
    • Error handling
    • Env
    • Head
    • MDX
    • Assets
    • File upload
    • OpenAPI
    • Query client
    • Events
    • Infer
  • Engine
    • Engine Config
    • Engine Runtime
    • CLI
    • Dev
    • Build
    • Compiler
    • Generator
    • Project MCP
    • Docs MCP
    • Importer
    • Public dir
    • Testing
    • Deploy
    • Bun or Vite
  • Extra
    • SsrStore
    • CookieStore
    • Basic Auth
    • CORS
    • Cache-Control
    • Compress
  • Examples
    • Basic
    • Vite
    • Better Auth
    • Capacitor
    • Expo
  • 1gr14
    • Главная
    • Start0
    • Поддержать
    • Обучение
    • Группа
    • Блог
    • Автор
  • Сообщество
    • Discord
    • Telegram
  • Опенсорс
    • Point0
    • Route0
    • Error0
    • Flat
  • Аккаунт
    • Войти
    • Регистрация
Point0by 1gr14
Создаю опенсорс во славу Господа Иисуса Христа ☦️
С любовью ко всем разработчикам на свете ❤️
Условия использованияПолитика конфиденциальностиСергей Дмитриев 2026 😎

Points

  • Раздел: Introduction

On this page

  1. The point types
  2. The short .lets notation
  3. The full .lets(type, name, …) form
  4. Static vs instance .lets
  5. The same word opens and closes
  6. Everything lands in one collection
  7. Reference
  8. Point types at a glance
  9. Notation at a glance

A point is the one building block in Point0. A page is a point; so is a query, a mutation, a layout, the root itself. They're all instances of a single Point0 class, composed with the same builder — you open a point, configure it, and close it. The word points is the umbrella term: pages, layouts, queries, mutations, and the rest are points.

export const ideaQuery = root.lets
  .query() //                        open a query point
  .input(z.object({ id: z.number() }))
  .loader(async ({ input }) => ({ idea: await getIdea(input.id) }))
  .query() //                        close it into a ready query

export const ideaPage = root.lets
  .page('/ideas/:id') //             open a page point
  .with(ideaQuery, ({ params }) => ({ id: Number(params.id) }))
  .page(({ data: { idea } }) => <h1>{idea.title}</h1>) // close it

The rest of this page lists every point type and explains the two ways to write .lets.

The point types

There are eleven. They split into three groups by what they do.

Mountables — they render UI.

  • page — a route and a component, with data, loading, error, and SSR handled up the chain.
  • layout — a shared shell around pages, with its own route, data, loading, and error that pages inherit.
  • component — composes queries and UI but has no route: a reusable mountable, not a page.
  • provider — loads or computes a value once and hands it to every child; read it with .useValue() or .getValue().

Page, layout, component, and provider share one method-injection model — see mountable for what they have in common.

Data and endpoints — they move data, often over HTTP.

  • query — an input schema plus a server loader: a real HTTP endpoint and a TanStack Query in one.
  • infinite-query — a query that loads in pages (cursor or offset), with the full TanStack infinite cache.
  • mutation — an input schema plus a loader: a real HTTP POST endpoint and a TanStack Mutation in one.
  • action — a server endpoint where you control the HTTP method and path, and may return a raw Response.

Structure — they hold defaults and shape the tree.

  • root — the point you build everything from: the server entry point and the holder of defaults for every point beneath it.
  • base — shared settings for a subset of points (a route prefix, defaults, gating) that its children inherit.
  • plugin — a bundle of methods you define once and inject into any point's chain with .use().

A point is not always an HTTP endpoint. A query, mutation, or action always is (its own path, in the OpenAPI spec). A page or component is an endpoint only when it has a server loader (or SSR is on) — otherwise it's a pure mountable. Each point's own page says exactly when.

The short .lets notation

Every example in these docs opens a point with the short form — root.lets.page('/ideas'), root.lets.query(), root.lets.mutation(). The point's type is the method name; its name is read from the variable:

export const ideaPage = root.lets.page('/ideas/:id').page(/* ... */)
//                 ▲                ▲
//          name → 'idea'      type → 'page'

The variable is ideaPage; the compiler strips the type suffix and the point's name becomes idea. Same rule everywhere — ideaQuery → idea, saveAction → save, mainRoot → main. A variable with no matching suffix is kept as-is (ideaX stays ideaX). If the variable name strips to nothing, or you use a default export, the name falls back to the file path — the filename, or the directory name for an index file.

The short notation needs the compiler. It's a compile-time rewrite, not a runtime feature: without the compiler, root.lets.page(...) throws

lets[type] notation can not work without compiler, please use compiler

The full .lets(type, name, …) form

The short form is sugar. The compiler rewrites every .lets.<type>(...) into one explicit .lets(...) call — type first, name second, then whatever arguments the short form took:

root.lets.page('/ideas') // → root.lets('page', 'idea', '/ideas')
root.lets.query() // → root.lets('query', 'idea')
root.lets.action('POST', '/save') // → root.lets('action', 'save', 'POST', '/save')

The full form runs at runtime unchanged — no compiler required. Use it when you need to pin a name yourself (the variable name isn't a good source) or when the compiler isn't in play:

export const generalLayout = root.lets('layout', 'general').layout(/* ... */)

Both forms are valid and identically typed. The example apps use the full form in a few places where a name is pinned explicitly — most of all the expo example, which doesn't run generate.

Static vs instance .lets

Most points grow off another point's instance — root.lets.page(...), generalLayout.lets.page(...), root.lets.query(...). Two types are different: root and plugin are created from the Point0 class itself, with the static Point0.lets:

import { Point0 } from '@point0/core'

export const root = Point0.lets.root().serverUrl(/* ... */).root()
export const mePlugin = Point0.lets.plugin().with(/* ... */).plugin()

Point0.lets accepts only 'root' and 'plugin'; every other type comes from an instance. From there, the chain flows down: a root spawns layouts, queries, and mutations; a layout spawns pages; a base or plugin contributes shared settings.

The same word opens and closes

A point is opened with .lets.<type>(...) and closed with .<type>(...) — the same word at both ends:

root.lets.query(/* ... */).input(/* ... */).loader(/* ... */).query()
//        ▲ open                                              ▲ close

The opener holds what comes before the point (a query's nothing, a page's route, an action's method and path); the closer holds what comes at the end (a mutation's react-query options, a page's component). Between them you add the point's methods. The closing call must match the type you opened — a page closes with .page(...), a mutation with .mutation(...). (An action is the exception: it can close as .action(), .query(), or .mutation(), depending on how you want to call it.)

The two ends have names the rest of the docs rely on. Everything from the opener up to (and including) the closing call is a stage-method — the chain methods you call while the point is still being built (.input, .loader, .with, the closing .page(...), …). What you get after the close is a ready-method — the surface on the finished point (useQuery, fetchMutation, .route, .id, .useValue, …). The two states have their own types in the code: a point under construction is a StagePoint, a closed one is a ReadyPoint.

const ideaQuery = root.lets
  .query() //                          ┐
  .input(z.object({ id: z.number() })) // stage-methods (building the point)
  .loader(/* ... */) //                ┘
  .query() //                          close → from here on, ready-methods

ideaQuery.useQuery({ id: 1 }) //       ready-method on the finished query

Everything lands in one collection

Because all eleven types are the same class, the compiler collects them into one array — the points collection the engine loads:

// generated points file (shape)
export default [root, ideaScreenComponent, createIdeaMutation, ideaQuery] // PointsDefinition

Each point carries a stable id of the form scope:type:name (e.g. root:query:idea). The engine wires this collection in; you never assemble it by hand. See generator for how it's produced and engine-config for how it's loaded.

Reference

Point types at a glance

TypeGroupOpens offPage
pagemountableroot / base / layoutpage
layoutmountableroot / base / layoutlayout
componentmountableroot / basecomponent
providermountableroot / baseprovider
querydata/endpointroot / basequery
infiniteQuerydata/endpointroot / baseinfinite-query
mutationdata/endpointroot / basemutation
actiondata/endpointroot / baseaction
rootstructurePoint0 (static) / rootroot
basestructureroot / basebase
pluginstructurePoint0 (static)plugin

query, mutation, and action are always HTTP endpoints; page, layout, component, and provider are endpoints only with a server loader or SSR; root, base, and plugin are never endpoints.

Notation at a glance

Short (.lets.page)Full (.lets('page', …))
Needs the compileryesno
Point nameread from the variablepassed explicitly
Runs at runtime as-isno — rewrittenyes
Used in these docsyes (default)only where a name is pinned
НазадBenchmarksДалееPage

Enjoying Point0?

Give it a star on GitHub, ask questions, and follow what's new

Star Point0

A star on GitHub helps more developers find Point0
Star on GitHub

Start0

Point0 integrated into the Start0 SaaS boilerplate — the best way to use it
Explore Start0

YouTube

Tutorials, walkthroughs, and updates
YouTube

Discord

Questions and chat in English
Join Discord

Telegram

News channel and chat in Russian
ChannelChat

Twitter

Posts and updates
Twitter