Audience: Developer
LokAkrt discriminates page vs app templates solely by a valid template.app contribution (menu.label required; settings may be []). Catalog type (page | project) remains a page-count filter and must not be overloaded as app|page.
Optional pack-loaded REST under /api/app/:projectId/* is a capability of a bound project whose Install copied platform pack JS into shared/project/{id}/js/{version}/ and registered a project_plugin row — not a second discriminator.
Page template (app absent) |
App template (app present) |
|
|---|---|---|
| Role | LokAkrt design/content starter | Domain package owning the project app surface |
| Pages | 1..N | 1..N |
| Data / media | Allowed | Allowed |
| Bind | Never | Install → project.properties.app (written last) |
| Entry | Add one page, or scaffold all (no bind) | Install App only |
| Project theme | Never written by create/scaffold | replaceTheme on Install |
| Settings sidebar | None | app.menu + settings values; declared app.menuItems (e.g. Payments / payment-config) freeze at Install but the current CMS side menu only renders type: settings — use Plugins for payment credentials |
| Custom REST | Never | Only when pack JS is installed + runtime loaded |
Seeds: Fashion Store is authored at plugin/template/e-commerce/fashion (local) or Admin-imported into shared/catalog/template/ (prod) — not under migration/.../template. Chat Social is a page template under migration seeds (multipage scaffold / Add Page; no Install).
lkt-starter-empty is a developer skeleton for pack authors — not a Store-installable operator app. Do not treat it as an end-user install guide.
pack.manifest.json: assert requiredDataSources, copy server/ (and packed node_modules/ when present) → shared JS tree, insert project_plugin, load routes, then write the bind snapshot (menuItems included when declared).Page templates with more than one page may still scaffold all pages without bind and without writing project theme. App templates are hidden from Add Page and hard-gated on materialize paths.
Unload runtime → delete plugin rows → delete shared/project/{id}/ → clear properties.app. Pages, theme, and data remain. /api/app/... for that project fails closed. Reinstall needs an empty page set (or a new project). UI should say so in the confirm dialog.
Only pack-persisted assets live under shared/project/{id}/ (typed subpaths).
Policy via bind settings (guest.enabled, guest.tokenExpiresIn). Storage is the template datastore guest-sessions (not platform guest tables). Mint: POST /api/app/:projectId/guest/session. Preview and hosted clients send _dv and keep a separate guest JWT (isGuestAuth()).
project_guest_session tables / properties.guestthemeTarget, project_configtype as app|page