§10 - one menu everywhere (buildPluginChrome) + shell on every page; instructional starter dashboard; Kratos-native email docs
Collapse the three nav builders into buildPluginChrome: chrome.bestHref does longest-prefix matching so deep admin routes mark their leaf. Delete adminNav; buildConfirmModel and the admin model builders take the resolved nav. The same role-filtered sidebar now renders signed in or out, collapsing to a burger on narrow screens. shell.ejs gains menu (default true; menu:false -> single-column .app-bare), docTitle (separate <title> from the topbar, so the body keeps the single <h1>), and hideSignIn (suppress the footer Sign-in on auth pages to avoid a login loop). auth/home/landing now render inside the shell. Dashboard is a replaceable instructional starter (definePlugin snippet, no mock data). Email stays delegated to Kratos: documented its built-in courier.template_override_path instead of adding web-side SMTP.
This commit is contained in:
+19
-41
@@ -1,43 +1,21 @@
|
||||
<%#
|
||||
Public landing page (todo §10): the ungated "/", what an anonymous visitor sees. A brief intro to
|
||||
the product and prominent paths to sign in / register — or to the app dashboard when already signed
|
||||
in. Standalone (no app shell — the sidebar/menu belong to the signed-in app). A plugin may replace
|
||||
this via its `home` handler. Auto theme follows the OS (styles.css). Data: brand, user (or null).
|
||||
Public landing page (todo §10): the ungated "/", rendered inside the unified app shell so the menu
|
||||
shows (role-filtered — anonymous ⇒ public items + Sign in). A brief intro + a prominent way in, or a
|
||||
dashboard link when already signed in. A plugin may replace this via its `home` handler.
|
||||
Data: chrome (PageChrome), user (or null).
|
||||
%><%
|
||||
const brand = locals.brand || "Plainpages";
|
||||
%><!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title><%= brand %></title>
|
||||
<link rel="stylesheet" href="/public/css/styles.css" />
|
||||
<link rel="stylesheet" href="/public/css/auth.css" />
|
||||
<link rel="icon" href="/public/favicon.svg" />
|
||||
</head>
|
||||
<body>
|
||||
<%- include("partials/icons") %>
|
||||
<main class="auth-stage">
|
||||
<div class="landing">
|
||||
<div class="auth-brand">
|
||||
<span class="brand-mark"><svg class="ico ico-sm"><use href="#i-box" /></svg></span>
|
||||
<span class="brand-name"><%= brand %></span>
|
||||
</div>
|
||||
<h1 class="landing-title">Operational web apps, without the boilerplate.</h1>
|
||||
<p class="landing-lead">
|
||||
<%= brand %> is a self-hostable foundation for admin and operational UIs — sign-in,
|
||||
a config-driven menu, and a server-rendered, zero-JS design system. You add the
|
||||
domain-specific screens by dropping in plugin folders.
|
||||
</p>
|
||||
<div class="landing-actions">
|
||||
<% if (locals.user) { %>
|
||||
<a class="btn btn-primary" href="/dashboard">Go to your dashboard</a>
|
||||
<% } else { %>
|
||||
<a class="btn btn-primary" href="/login">Log in</a>
|
||||
<a class="btn" href="/registration">Create account</a>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
const nav = include("partials/nav-tree", { nodes: chrome.nav });
|
||||
const body = include("partials/landing-body", { brand: chrome.brand.name, signedIn: !!locals.user });
|
||||
-%>
|
||||
<%- include("partials/shell", {
|
||||
body,
|
||||
brand: chrome.brand,
|
||||
csrfToken: chrome.csrfToken,
|
||||
docTitle: chrome.brand.name,
|
||||
nav,
|
||||
signInHref: chrome.signInHref,
|
||||
styles: ["/public/css/auth.css"],
|
||||
theme: chrome.theme,
|
||||
title: "",
|
||||
user: chrome.user,
|
||||
}) %>
|
||||
|
||||
Reference in New Issue
Block a user