Contenido
Convenciones
Carats resuelve por convención unas cuantas rutas y nombres de archivo. Desviarse de ellas funciona hasta que deja de funcionar, así que conviene atenerse a ellas.
Carpetas de página
Cada ruta vive en su propia carpeta bajo src/client/pages, y la carpeta exporta un componente por defecto desde index.tsx junto a una hoja de estilos del mismo nombre. Las carpetas que empiezan por guion bajo no son rutas; son bloques de construcción compartidos a los que se refieren las rutas que los necesitan.
src/client/pages/
├── _layout/ # shared building block, not a route
│ ├── index.tsx
│ └── _layout.sass
├── _error/ # suspense.error
│ └── index.tsx
├── _not_found/ # suspense.notFound
│ └── index.tsx
├── home/ # '/'
│ ├── index.tsx
│ └── home.sass
├── market/ # '/market'
│ ├── index.tsx
│ └── market.sass
├── profile/ # '/profile'
│ ├── index.tsx
│ └── profile.sass
└── trade/ # '/trade/:symbol'
├── index.tsx
└── trade.sass
El guion bajo inicial es lo que marca una carpeta como bloque de construcción y no como página. Mantiene los componentes compartidos fuera de en medio en el árbol de archivos y señala que no están destinados a ser enrutados.
Diseño compartido
No hay un diseño por convención de archivos como en Next.js. Un componente _layout lo importan las páginas que lo necesitan, lo que hace explícita la composición y permite que una página se quede fuera. La plantilla de referencia envuelve cada página en el mismo diseño para compartir la cabecera, el pie y el menú móvil.
// src/client/pages/profile/index.tsx
import { Burnish } from '@carats/render';
import Layout from '../_layout';
import './profile.sass';
export default Burnish(function (user: User) {
this.head = <>
<title>Profile for {user.name}</title>
</>;
return (
<Layout>
<h1>{user.name}</h1>
</Layout>
);
});
El diseño renderiza props.children donde corresponde al contenido de la página, y ese es el único mecanismo de composición. No hay árbol de rutas anidadas ni envoltura automática, así que la dependencia se ve en el import.
Páginas de error y de no encontrado
Los componentes de suspensión error y notFound son componentes corrientes. El de error recibe el Error lanzado, así que puede leer message y stack; el de notFound no recibe nada. Vale la pena envolver ambos en el diseño compartido para que un fallo siga mostrando el armazón del sitio.
DTO globales
Las interfaces colocadas en src/dto son globales, porque typeRoots apunta a esa carpeta. Eso es lo que permite escribir un culet como culet
// src/dto/user.d.ts
interface User {
id: string
name: string
username: string
email: string
phone: string
website: string
}
La interfaz no lleva export, y eso es lo que la hace global. Con typeRoots apuntando a src/dto, culet
Hojas de estilos
Una página o componente importa su propia hoja SASS, y esa hoja importa base.sass con @use ... as *. La extensión es opcional en la ruta. Mantén los resets globales y los tokens en base.sass y nada más allí.
// src/client/pages/trade/trade.sass
@use '../../base' as *
#trade
.trade-header
display: flex
La extensión en la ruta de @use es opcional, y la ruta es relativa a la hoja de estilos, no al componente. base.sass es el único archivo que define tokens; todos los demás los consumen.
Nombres
Las carpetas de ruta se nombran según el segmento de la ruta, y el nombre del parámetro dinámico debe ser idéntico en la faceta y en el culet. Los archivos de culet se nombran según la acción que realizan y exportan el culet por defecto, que luego se sienta en el punto de entrada del servidor.