soul v4.2.0

@jun/soul/static

Static

Paginas prerenderizadas que se sirven sin invocar el Worker.

Que resuelve#

Una landing o una pagina de precios cambian poco y reciben mucho trafico. Servirlas desde el Worker gasta una request por visita sin ganar nada. Este modulo las prerenderiza en tiempo de build y las deja como assets de Cloudflare: 0 requests de Worker, 0 D1.

Como funciona#

El proyecto declara sus paginas estaticas en src/static.ts. Cada una es una funcion pura: recibe nada y devuelve HTML.

TypeScript
import { defineStatic } from "@jun/soul/static";
import { shell } from "./core";

export const staticPages = defineStatic([
  {
    path: "/",
    render: () => shell({ title: "Mi SaaS", body: landing() }),
  },
  {
    path: "/precios",
    render: () => shell({ title: "Precios", body: precios() }),
  },
]);

Construir#

Terminal
npx soul build          # prerenderiza a public/<path>/index.html y copia ./assets

path: "/" se escribe en public/index.html; /precios en public/precios/index.html. El template ya llama a soul build dentro de deploy:production.

Servirlas#

Hace falta el binding de assets en wrangler.jsonc:

TypeScript
{
  "assets": { "directory": "./public" },
  "env": {
    "production": {
      "name": "mi-saas",
      "assets": { "directory": "./public" }   // los envs NO heredan: repetir
    }
  }
}

Generarlas con el CLI#

Terminal
npx soul g page landing --static     # nombre index/home/landing => path "/"
npx soul g page precios --static

A diferencia de las otras paginas, --static no toca src/index.ts: no hay ruta que registrar.

El problema evidente de una landing estatica: no sabe si el visitante tiene sesion, asi que no puede elegir entre "Entrar" e "Ir al panel". La solucion es una cookie pista:

TypeScript
export const auth = createAuth({ errorPage, sessionHintCookie: "mi_hint" });

Junto al JWT HttpOnly, soul emite una cookie sin HttpOnly con valor "1" (y la limpia al salir). La landing la lee desde JavaScript y decide que boton mostrar.

Cuando NO usarla#

  • Si la pagina depende de datos de D1 que cambian seguido.
  • Si es por-usuario o por-organizacion (eso es portal).
  • Si publicar un cambio no puede esperar a un despliegue.