defineGroup
Declares options in a +group.ts for an app/pages directory (named layout, its props and middleware) inherited by all its pages.
Se autoimporta en las aplicaciones del framework.
import { defineGroup } from "@meekojs/meeko/framework";defineGroup declares an app/pages directory's options in its +group.ts file: the named layout, its props and, since 1.6, named middleware. All pages in the directory and its subdirectories inherit them, so you do not have to repeat layout or middleware in each definePage.
It is auto-imported. Meeko reads the file without executing it, like render: its values must be literals. This makes it work the same in SSR, prerendering and static sites.
Usage#
// app/pages/(dashboard)/+group.ts
import { defineGroup } from "@meekojs/meeko/framework";
export default defineGroup({ layout: "dashboard", layoutProps: { showAlert: false }, middleware: ["auth"] });All pages in app/pages/(dashboard)/ render inside app/layouts/dashboard.meeko with showAlert: false and first run the "auth" middleware.
Type#
function defineGroup<const L extends LayoutName | false = string>(
definition: GroupDefinition<L>,
): GroupDefinition<L>interface GroupDefinition<L extends LayoutName | false = LayoutName> {
readonly layout?: L
readonly layoutProps?: Partial<LayoutProps<L>>
readonly middleware?: readonly RouteMiddlewareName[] | false
}Options#
| Option | Type | Default | Description |
|---|---|---|---|
layout |
layout name, or false |
outer group's layout, or default |
Named layout from app/layouts/<nombre>.meeko. false removes the named layout and keeps app/app.meeko and +layout.meeko files. Must be a literal. |
layoutProps |
layout Props |
none | Props for the layout, typed against the one selected by layout (or the inherited layout). A literal object of strings, numbers, booleans, null, arrays and objects. Merged by key with outer groups and the page, which takes precedence. |
middleware |
names from app/middleware, or false |
inherited middleware | Since 1.6. Named middleware added to those from outer groups without duplicates. false removes inherited middleware. Must be a literal array. |
Return value#
The same definition, unchanged at runtime. What matters is the file: Meeko analyzes it when discovering routes and stores the result in each page's manifest.
Examples#
A private area with its own layout#
app/layouts/dashboard.meeko
app/middleware/auth.server.ts ← defineServerRouteMiddleware(…, { global: false })
app/pages/(dashboard)/+group.ts ← defineGroup({ layout: "dashboard", middleware: ["auth"] })
app/pages/(dashboard)/reports.meeko
app/pages/(dashboard)/settings/index.meeko/reports and /settings use dashboard and require a session. The (dashboard) directory is a group: it is not part of the URL.
Nested groups#
+group.ts files apply from the outside in, followed by the page:
// app/pages/(dashboard)/admin/+group.ts
import { defineGroup } from "@meekojs/meeko/framework";
// Inherits layout "dashboard" and middleware ["auth"]; adds "admin" and changes a prop.
export default defineGroup({ layoutProps: { showAlert: true }, middleware: ["admin"] });A page in admin/ runs auth and then admin, and its layout receives showAlert: true.
A page that opts out of the group#
The page takes precedence over its groups. With layout: false and middleware: false, it has neither the layout nor inherited middleware:
<!-- app/pages/(dashboard)/login.meeko -->
<script server lang="ts">
export const route = definePage({ layout: false, middleware: false });
</script>
<template><h1>Sign in</h1></template>Common mistakes#
A layout that does not exist#
export default defineGroup({ layout: "dashboard" });Without app/layouts/dashboard.meeko, meeko check, meeko dev and meeko build stop with el layout "dashboard" no existe; crea app/layouts/dashboard.meeko (layouts disponibles: "default").
// with app/layouts/dashboard.meeko
export default defineGroup({ layout: "dashboard" });A computed value#
Meeko does not execute the file.
const name = process.env.ADMIN ? "admin" : "default";
export default defineGroup({ layout: name });layout debe ser un literal de texto (el nombre de un layout de app/layouts) o false para que Meeko pueda leerlo durante el build. The same applies to a spread or computed middleware.
export default defineGroup({ layout: "admin" });An option that does not exist#
export default defineGroup({ layout: "default", sidebar: true });opción de grupo desconocida "sidebar"; un +group.ts admite layout, layoutProps y middleware. Page options (render, load, head) belong in its definePage.
export default defineGroup({ layout: "default", layoutProps: { sidebar: true } });layoutProps not declared by the layout#
export default defineGroup({ layout: "default", layoutProps: { title: "Dashboard" } });If app/layouts/default.meeko does not declare title, meeko check reports TS2344: Type '"Las layoutProps de app/pages/(dash)/+group.ts no coinciden con las props del layout default"' does not satisfy the constraint 'true'.
// app/layouts/default.meeko declares defineProps<{ title?: string }>()
export default defineGroup({ layout: "default", layoutProps: { title: "Dashboard" } });A missing or global middleware#
export default defineGroup({ middleware: ["auth", "locale"] });el middleware "auth" no existe; crea app/middleware/auth.ts con defineRouteMiddleware(..., { global: false }) (middleware con nombre disponibles: ninguno), o app/middleware/auth.server.ts con defineServerRouteMiddleware para uno que sólo se ejecuta en el servidor. A global one, such as 10-locale.ts without options, reports el middleware "locale" (…) es global y ya se ejecuta en todas las rutas; quítalo de middleware o decláralo con defineRouteMiddleware(..., { global: false }).
// with app/middleware/auth.server.ts declared with { global: false }
export default defineGroup({ middleware: ["auth"] });Notes#
- Placement. Only in
+group.ts, in any directory underapp/pages(a(nombre)group or an ordinary directory). A+group.tsoutsideapp/pagesconfigures nothing andmeeko checkwarns withMEEK115. - Inheritance.
layoutis decided by the page or the innermost group that declares it. A group or page selecting another layout starts without inheritedlayoutProps, which belonged to the previous one. - Navigation. Pages sharing a layout keep it mounted when navigating between them, with its state and scroll position.
- Security. Middleware requested by a group protects pages, not
server/apior RPC: endpoints need their own guards. To check the session, use server middleware (*.server.ts). - Development. Creating, deleting or changing a
+group.tsmakesmeeko devrediscover routes.