SSR websites¶
A website of API Maker is a folder of files : pages written in TSX, the components and the code they share, files sent as they are, and its settings. The server renders the pages next to your data and sends HTML : the browser shows a page as it reads it, and nothing runs in it unless you add a script.
A website answers at /ssr/<apiPath>/<name>/ of the server : the path of its account, as the addresses of its APIs have it, then its name, unique in the account. A reverse proxy shows it at the root of a domain of its own : see deployment.
| Where | Dashboard → SSR Websites : a website from a template, its files, the editor, the preview, its UI libraries, its routes, its settings. The panel. |
| Pages | pages/ : index.tsx is /, blog/[slug].tsx is /blog/:slug, a .ts file is an endpoint. Routing. |
| Data | A loader reads on the server ; ctx.db reaches the tables the website lists, with the rows each visitor may reach. Data. |
| Visitors | Sign-in with the auth providers of the account, access on a page or a layout, groups. Authentication. |
| Forms | An action takes a form ; every form carries a CSRF token by itself. Forms. |
| Speed | Templates compiled when a file is saved, engines kept per website, pages kept by the server. Cache. |
| Browser | Bootstrap, Tailwind, Chart.js, htmx… from a catalog with their hashes. UI libraries. |
| Git | src/ssr/<name>/ of the repository of the account : commit, pull, revert. Git. |
Your first website¶
- Dashboard → SSR Websites → New website.
- Choose Starter : a page for every feature, each with comments which say why it is written so.
- Name it
demo. Its address is/ssr/<apiPath>/demo/:/ssr/acme/demo/for the account of the pathacme. - Open
pages/index.tsx, change a word, save with Ctrl+S : the preview reloads by itself.
A page :
pages/products/index.tsx
import { formatCurrency } from 'am-ssr';
import type { PageConfig, PageContext, PageProps } from 'am-ssr';
export const config: PageConfig = {
title: 'Products',
// One page for every anonymous visitor, kept a minute.
cache: { maxAge: 60, scope: 'public' },
};
// Runs on the server before the page renders : what it returns is `data`.
export async function loader(ctx: PageContext) {
return {
products: await ctx.db.query({ instance: 'mongodb', database: 'shop', table: 'products', limit: 20 }),
};
}
export default function Products({ data }: PageProps<typeof loader>) {
return (
<ul>
{data.products.map((product) => (
<li>
<a href={`/products/${product.slug}`}>{product.name}</a> {formatCurrency(product.price, 'USD')}
</li>
))}
</ul>
);
}
And its website lists the table it reads, in site.config.ts : a website reaches no table it does not name.
site.config.ts
import { defineSite } from 'am-ssr';
export default defineSite({
title: 'My shop',
titleTemplate: '%s · My shop',
data: { read: ['mongodb/shop/products'] },
});
The files of a website¶
site.config.ts the settings : tables ctx.db reaches, auth providers, CSP, cache, SEO, redirects
libraries.json the UI libraries the pages load in the browser
pages/
_layout.tsx the HTML around every page
_middleware.ts code which runs before every page and endpoint
_404.tsx _error.tsx what a path no page answers shows, and what a page which failed shows
index.tsx /
about.tsx /about
blog/[slug].tsx /blog/:slug
docs/[...path].tsx /docs/a/b/c
(shop)/cart.tsx /cart, with the layout of (shop)/
api/items.ts an endpoint : GET, POST, PUT, PATCH, DELETE
components/ components the pages share : import Card from '@/components/Card'
lib/ code the pages share
data/ JSON the pages import : import posts from '@/data/posts.json'
public/ files sent as they are : public/logo.png is /logo.png
What happens to a request¶
- The server finds the website of
/ssr/<apiPath>/<name>, built for its version : its files were compiled when they were saved. - Redirects of the settings, files of
public/,/robots.txtand/sitemap.xmlanswer first. - The route of the path, and who may open it : the
accessof its layouts and of the page, read from their code when they were saved. A visitor who may not is refused before any code of the page runs. - A form of an unsafe method needs the CSRF token of its visitor.
- A page kept by the cache is sent as it was kept.
- The render, in an engine of the website : the middlewares, the
actionfor a form, the loaders of the layouts and of the page at once, the page, then each layout around it. - The server writes the head (title, description, Open Graph, the UI libraries), the CSRF token and the nonce of the CSP into the page, and sends it.
Safe by default¶
- Every value is escaped where it is written. HTML which is not is asked for by name (
raw()). ctx.dbreaches the tablessite.config.tslists, with the row rules it gives each :{ customer_id: '$user._id' }keeps every query to the rows of the visitor.- Sessions are cookies sealed with AES-256-GCM,
HttpOnly,SameSite=Lax,Secureover HTTPS. - Every form has a CSRF token ; every
<script>of a page has the nonce of the CSP ;javascript:addresses are refused. - Each website runs in engines of its own, with a limit of memory and of time.
See security for all of it.
Read on¶
| Page | What it says |
|---|---|
| The panel | The files of a website (new files and folders, rename, drag and drop, uploads), the keys of the editor, the preview at the size of a device. |
| Pages and routing | Files and paths, layouts, middlewares, 404 and error pages, endpoints, public files. |
| Data | Loaders, ctx.db, ctx.api, ctx.sys, ctx.fetch, ctx.cache, JSON files. |
| Forms | Actions, checks, messages, the redirect after a post, uploads. |
| Authentication | Sign-in, sign-up, sign-out, access, groups, row rules. |
| Caching | Pages kept by the server, tags, what is never kept. |
| UI libraries | The catalog, npm packages, self-hosting, the CSP. |
| SEO | Title, description, Open Graph, canonical, sitemap, robots, JSON-LD. |
| Settings | Every setting of site.config.ts. |
| Security | What the server does for you, and what is left to you. |
| Deployment | Domains, reverse proxies, the settings of the server. |
| Git | The websites in the repository : commit, pull, revert, editors. |
| Templates | The websites and the files a new one starts from. |
| Examples | Recipes for what websites do most. |
| Reference | The module am-ssr, ctx, PageConfig. |
| Guide for AI | What an assistant needs to write a page right the first time. |