{"section":"rendering","slug":"philosophy","featureTitle":"SSR Philosophy","summary":"Semitexa SSR is one continuous rendering architecture: page, slots, deferred regions, live refresh, and interactive components stay inside one server-owned story.","entryLine":"Semitexa SSR is not “render once on the server and then improvise”. It is a coherent rendering system that refuses both kinds of drift: backend HTML plus frontend survival code, and fake “data vs presentation” separation where templates quietly become data loaders.","highlights":["one rendering story","HtmlResponse","Presentation boundary","Deferred SSR","Framework-free enhancement"],"learnMoreLabel":"See the Semitexa SSR axioms →","deepDiveLabel":"What Semitexa SSR refuses to become →","documentBodyHtml":"<article class=\"sx-docs-fragment\" data-doc-id=\"rendering/philosophy\" data-doc-locale=\"en\">\n<h1>SSR Philosophy</h1>\n<p>Semitexa SSR is not &quot;render once on the server and then improvise&quot;. It is a coherent rendering system that refuses both kinds of drift: backend HTML plus frontend survival code, and fake &quot;data vs presentation&quot; separation where templates quietly become data loaders.</p>\n<h2>The problem</h2>\n<p>&quot;SSR&quot; usually means the first paint is server-rendered, but the moment the page becomes dynamic, teams quietly switch to a second frontend architecture. At the same time, templates start accumulating query logic, ad hoc reshaping, and service calls because nobody protected the presentation boundary structurally.</p>\n<p>Page regions become partials with hidden context, live widgets become little apps, and interaction drifts into custom fetch glue. Soon the page is &quot;SSR&quot; only in name, while React, Alpine, or bespoke client glue becomes the real owner of interaction and state interpretation.</p>\n<h2>The seven pillars</h2>\n<ul>\n<li><strong>Page Contract</strong> — Resource DTOs make the page response explicit before Twig sees a single field.</li>\n<li><strong>Presentation Boundary</strong> — Templates consume prepared data instead of querying storage, calling APIs, or inventing new view-side mapping rules.</li>\n<li><strong>Region Contract</strong> — Slots are real resources with their own pipeline, not fragment glue.</li>\n<li><strong>Late HTML</strong> — Deferred blocks stream SSR HTML later instead of handing control to a client renderer.</li>\n<li><strong>Live HTML</strong> — Reactive slots refresh from server truth without inventing a second state machine.</li>\n<li><strong>Interactive HTML</strong> — Components can now dispatch backend events while staying in the SSR component model.</li>\n<li><strong>Framework-Free JS</strong> — When JavaScript is needed, it stays as small component-owned enhancement rather than a mandatory UI framework layer.</li>\n</ul>\n<h2>The rules</h2>\n<ol>\n<li>The page response must be explicit before template rendering begins.</li>\n<li>Templates are presentation surfaces, not a place to fetch from databases, hit APIs, or smuggle handler logic into Twig.</li>\n<li>A region is a resource with a pipeline, not a partial with lucky context.</li>\n<li>Deferred does not mean &quot;replace SSR with client rendering later&quot;. It means late server HTML.</li>\n<li>Reactive does not mean &quot;invent a mini SPA for one widget&quot;. It means the server keeps re-rendering truth.</li>\n<li>Interactivity does not require escaping into bespoke API glue. Components can declare backend event contracts directly.</li>\n<li>JavaScript may enhance the page, but Semitexa refuses to require React, Alpine, Angular, or another client framework as the second rendering layer.</li>\n<li>Assets, scripts, and SEO stay inside the same rendering system instead of becoming a parallel deployment concern.</li>\n</ol>\n<h2>What Semitexa SSR refuses to become</h2>\n<table>\n<thead>\n<tr>\n<th>Anti-pattern</th>\n<th>Semitexa answer</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>&quot;SSR for the first paint, client app for everything real.&quot;</td>\n<td>Semitexa keeps deferred and reactive regions inside the same HTML pipeline.</td>\n</tr>\n<tr>\n<td>&quot;The template can just query what it needs.&quot;</td>\n<td>Semitexa treats that as presentation-boundary failure. Handlers and resource DTOs must shape data before Twig sees it.</td>\n</tr>\n<tr>\n<td>&quot;This region is just a partial, pass whatever data it seems to need.&quot;</td>\n<td>Semitexa promotes regions to slot resources with an explicit render contract.</td>\n</tr>\n<tr>\n<td>&quot;The widget is live, so we need a second state architecture.&quot;</td>\n<td>Semitexa refreshes the slot from server truth and swaps HTML in place.</td>\n</tr>\n<tr>\n<td>&quot;Once the page becomes interactive, we obviously need React or Alpine.&quot;</td>\n<td>Semitexa rejects that as a default assumption. Small component-owned scripts are enough when the server still owns rendering truth.</td>\n</tr>\n</tbody>\n</table>\n</article>","sectionLabel":"UI Rendering & SSR","navSections":[{"key":"get-started","label":"Start Here","sidebarLabel":"Get Started","summary":"The shortest path from fresh scaffold to a trustworthy local Semitexa runtime: install, boot, understand the module map, bind a real host, and reach the first tenant boundary.","icon":"GO","eyebrow":"Onboarding","starter":true,"prerequisites":[],"featureCount":7,"href":"/demo/get-started","features":[{"section":"get-started","slug":"module-structure","label":"Start Here","title":"Module Structure","summary":"The minimal Semitexa module is a typed HTTP spine of payload, handler, resource, and template.","opensInNewTab":false,"href":"/demo/get-started/module-structure"},{"section":"get-started","slug":"installation","label":"Start Here","title":"Installation","summary":"Create the project, review the baseline env contract, and bring up the Semitexa runtime the supported way.","opensInNewTab":false,"href":"/demo/get-started/installation"},{"section":"get-started","slug":"local-domain","label":"Start Here","title":"Local Domain","summary":"Register .test domains through the built-in local-domain helper instead of relying on ad hoc host setup.","opensInNewTab":false,"href":"/demo/get-started/local-domain"},{"section":"get-started","slug":"base-tenant","label":"Start Here","title":"Base Tenant","summary":"Establish one default tenant context early so tenant-aware behavior is visible before the rest of the application grows.","opensInNewTab":false,"href":"/demo/get-started/base-tenant"},{"section":"get-started","slug":"locale-setup","label":"Start Here","title":"Locale Setup","summary":"Configure the minimal Locale contract so translations and locale-aware rendering become explicit early.","opensInNewTab":false,"href":"/demo/get-started/locale-setup"},{"section":"get-started","slug":"ai-console","label":"Start Here","title":"AI Console","summary":"Use the Semitexa AI console as a command translation surface over real operator commands.","opensInNewTab":false,"href":"/demo/get-started/ai-console"},{"section":"get-started","slug":"beyond-controllers","label":"Start Here","title":"Beyond Controllers","summary":"Understand why Semitexa keeps transport, use case, and rendering as separate explicit responsibilities.","opensInNewTab":false,"href":"/demo/get-started/beyond-controllers"}],"groups":[{"key":"structure","label":"Module Structure","featureCount":1,"features":[{"section":"get-started","slug":"module-structure","label":"Start Here","title":"Module Structure","summary":"The minimal Semitexa module is a typed HTTP spine of payload, handler, resource, and template.","opensInNewTab":false,"href":"/demo/get-started/module-structure"}]},{"key":"onboarding","label":"Onboarding","featureCount":6,"features":[{"section":"get-started","slug":"installation","label":"Start Here","title":"Installation","summary":"Create the project, review the baseline env contract, and bring up the Semitexa runtime the supported way.","opensInNewTab":false,"href":"/demo/get-started/installation"},{"section":"get-started","slug":"local-domain","label":"Start Here","title":"Local Domain","summary":"Register .test domains through the built-in local-domain helper instead of relying on ad hoc host setup.","opensInNewTab":false,"href":"/demo/get-started/local-domain"},{"section":"get-started","slug":"base-tenant","label":"Start Here","title":"Base Tenant","summary":"Establish one default tenant context early so tenant-aware behavior is visible before the rest of the application grows.","opensInNewTab":false,"href":"/demo/get-started/base-tenant"},{"section":"get-started","slug":"locale-setup","label":"Start Here","title":"Locale Setup","summary":"Configure the minimal Locale contract so translations and locale-aware rendering become explicit early.","opensInNewTab":false,"href":"/demo/get-started/locale-setup"},{"section":"get-started","slug":"ai-console","label":"Start Here","title":"AI Console","summary":"Use the Semitexa AI console as a command translation surface over real operator commands.","opensInNewTab":false,"href":"/demo/get-started/ai-console"},{"section":"get-started","slug":"beyond-controllers","label":"Start Here","title":"Beyond Controllers","summary":"Understand why Semitexa keeps transport, use case, and rendering as separate explicit responsibilities.","opensInNewTab":false,"href":"/demo/get-started/beyond-controllers"}]}]},{"key":"routing","label":"Routing & Handlers","summary":"Attribute-driven routes, typed handlers, and content negotiation in one coherent request pipeline.","icon":"RT","eyebrow":"HTTP Layer","starter":true,"prerequisites":[],"featureCount":7,"href":"/demo/routing","features":[{"section":"routing","slug":"basic","label":"Routing & Handlers","title":"Basic Route","summary":"Define a route with one access attribute on the payload — no XML, no YAML, no config files.","opensInNewTab":false,"href":"/demo/routing/basic"},{"section":"routing","slug":"parameterized","label":"Routing & Handlers","title":"Parameterized Route","summary":"Path parameters with regex constraints and typed injection.","opensInNewTab":false,"href":"/demo/routing/parameterized/headphones"},{"section":"routing","slug":"env-route-override","label":"Routing & Handlers","title":"Env Route Override","summary":"Keep the payload as the route source of truth while allowing operations to remap the public URL through .env.","opensInNewTab":false,"href":"/demo/routing/env-route-override"},{"section":"routing","slug":"payload-shield","label":"Routing & Handlers","title":"Payload As A Shield","summary":"Hydration happens before the handler, and each setter owns the normalization and guard logic for its own field.","opensInNewTab":false,"href":"/demo/routing/payload-shield"},{"section":"routing","slug":"payload-parts","label":"Routing & Handlers","title":"Payload Parts","summary":"One module owns the route, another module can extend the same payload contract without forking or reopening the base class.","opensInNewTab":false,"href":"/demo/routing/payload-parts"},{"section":"routing","slug":"content-negotiation","label":"Routing & Handlers","title":"Content Negotiation","summary":"One endpoint, multiple response formats — automatically.","opensInNewTab":false,"href":"/demo/routing/content-negotiation"},{"section":"routing","slug":"public-endpoint","label":"Routing & Handlers","title":"Public Payload","summary":"Anonymous endpoints opt in explicitly with the public access attribute. Every other payload requires authentication.","opensInNewTab":false,"href":"/demo/routing/public-endpoint"}],"groups":[{"key":"foundations","label":"Foundations","featureCount":3,"features":[{"section":"routing","slug":"basic","label":"Routing & Handlers","title":"Basic Route","summary":"Define a route with one access attribute on the payload — no XML, no YAML, no config files.","opensInNewTab":false,"href":"/demo/routing/basic"},{"section":"routing","slug":"parameterized","label":"Routing & Handlers","title":"Parameterized Route","summary":"Path parameters with regex constraints and typed injection.","opensInNewTab":false,"href":"/demo/routing/parameterized/headphones"},{"section":"routing","slug":"env-route-override","label":"Routing & Handlers","title":"Env Route Override","summary":"Keep the payload as the route source of truth while allowing operations to remap the public URL through .env.","opensInNewTab":false,"href":"/demo/routing/env-route-override"}]},{"key":"request-model","label":"Request Model","featureCount":2,"features":[{"section":"routing","slug":"payload-shield","label":"Routing & Handlers","title":"Payload As A Shield","summary":"Hydration happens before the handler, and each setter owns the normalization and guard logic for its own field.","opensInNewTab":false,"href":"/demo/routing/payload-shield"},{"section":"routing","slug":"payload-parts","label":"Routing & Handlers","title":"Payload Parts","summary":"One module owns the route, another module can extend the same payload contract without forking or reopening the base class.","opensInNewTab":false,"href":"/demo/routing/payload-parts"}]},{"key":"delivery","label":"Delivery","featureCount":2,"features":[{"section":"routing","slug":"content-negotiation","label":"Routing & Handlers","title":"Content Negotiation","summary":"One endpoint, multiple response formats — automatically.","opensInNewTab":false,"href":"/demo/routing/content-negotiation"},{"section":"routing","slug":"public-endpoint","label":"Routing & Handlers","title":"Public Payload","summary":"Anonymous endpoints opt in explicitly with the public access attribute. Every other payload requires authentication.","opensInNewTab":false,"href":"/demo/routing/public-endpoint"}]}]},{"key":"di","label":"Dependency Injection","summary":"Single-path DI with explicit lifecycles, deterministic contracts, and stable boot behavior for long-running workers.","icon":"DI","eyebrow":"Container","starter":true,"prerequisites":[],"featureCount":5,"href":"/demo/di","features":[{"section":"di","slug":"overview","label":"Dependency Injection","title":"DI Canon","summary":"One canonical DI path for container-managed classes: explicit properties, explicit lifecycles, deterministic boot.","opensInNewTab":false,"href":"/demo/di/overview"},{"section":"di","slug":"readonly","label":"Dependency Injection","title":"Readonly Injection","summary":"One explicit DI path, one shared worker instance — fast at runtime and stable under reload.","opensInNewTab":false,"href":"/demo/di/readonly"},{"section":"di","slug":"mutable","label":"Dependency Injection","title":"Mutable Injection","summary":"Execution-scoped services get a fresh clone every run — safe state without contaminating the worker.","opensInNewTab":false,"href":"/demo/di/mutable"},{"section":"di","slug":"factory","label":"Dependency Injection","title":"Factory Injection","summary":"On-demand creation stays explicit — lazy instances without falling back to service locator habits.","opensInNewTab":false,"href":"/demo/di/factory"},{"section":"di","slug":"contracts","label":"Dependency Injection","title":"Service Contracts","summary":"Depend on contracts, but keep ownership explicit — deterministic substitution instead of runtime magic.","opensInNewTab":false,"href":"/demo/di/contracts"}],"groups":[{"key":"container-basics","label":"Container Basics","featureCount":5,"features":[{"section":"di","slug":"overview","label":"Dependency Injection","title":"DI Canon","summary":"One canonical DI path for container-managed classes: explicit properties, explicit lifecycles, deterministic boot.","opensInNewTab":false,"href":"/demo/di/overview"},{"section":"di","slug":"readonly","label":"Dependency Injection","title":"Readonly Injection","summary":"One explicit DI path, one shared worker instance — fast at runtime and stable under reload.","opensInNewTab":false,"href":"/demo/di/readonly"},{"section":"di","slug":"mutable","label":"Dependency Injection","title":"Mutable Injection","summary":"Execution-scoped services get a fresh clone every run — safe state without contaminating the worker.","opensInNewTab":false,"href":"/demo/di/mutable"},{"section":"di","slug":"factory","label":"Dependency Injection","title":"Factory Injection","summary":"On-demand creation stays explicit — lazy instances without falling back to service locator habits.","opensInNewTab":false,"href":"/demo/di/factory"},{"section":"di","slug":"contracts","label":"Dependency Injection","title":"Service Contracts","summary":"Depend on contracts, but keep ownership explicit — deterministic substitution instead of runtime magic.","opensInNewTab":false,"href":"/demo/di/contracts"}]}]},{"key":"data","label":"Persistence","summary":"Attribute-mapped resources, repositories, filtering, pagination, and relations with real demo data.","icon":"DB","eyebrow":"Persistence","starter":true,"prerequisites":[],"featureCount":9,"href":"/demo/data","features":[{"section":"data","slug":"domain-models","label":"Persistence","title":"Domain-Level Models","summary":"Semitexa separates persistence resources from business models. Resources map tables; domain models carry behavior and invariants.","opensInNewTab":false,"href":"/demo/data/domain-models"},{"section":"data","slug":"repository-workflow","label":"Persistence","title":"Repository Workflow","summary":"The canonical Semitexa path: handlers depend on repository contracts, repositories return domain models, and persistence resources stay behind the boundary.","opensInNewTab":false,"href":"/demo/data/repository-workflow"},{"section":"data","slug":"schema-sync","label":"Persistence","title":"Schema Sync, Not Migration Churn","summary":"Semitexa creates SQL only when the real schema changed, blocks destructive drops by default, and logs the exact DDL plan as SQL and JSON.","opensInNewTab":false,"href":"/demo/data/schema-sync"},{"section":"data","slug":"query","label":"Persistence","title":"Query Builder","summary":"Compose type-safe queries with a fluent API — no raw SQL, no magic strings.","opensInNewTab":false,"href":"/demo/data/query"},{"section":"data","slug":"filtering","label":"Persistence","title":"Filtering","summary":"Mark a property #[Filterable] and the ORM handles the rest — no manual WHERE clauses.","opensInNewTab":false,"href":"/demo/data/filtering"},{"section":"data","slug":"pagination","label":"Persistence","title":"Pagination","summary":"Offset and cursor pagination out of the box — switch modes with a single query parameter.","opensInNewTab":false,"href":"/demo/data/pagination"},{"section":"data","slug":"relations","label":"Persistence","title":"Relations","summary":"Declare parent and child links on the resource itself, then read typed relations from the handler.","opensInNewTab":false,"href":"/demo/data/relations"},{"section":"data","slug":"table-extension","label":"Persistence","title":"Shared Table Extension","summary":"Two modules can extend one table independently, and the ORM merges the schema without forcing either side to edit the other.","opensInNewTab":false,"href":"/demo/data/table-extension"},{"section":"data","slug":"n-plus-one","label":"Persistence","title":"N+1 Without Magic","summary":"Semitexa avoids N+1 by using resource slices for the exact columns and relations each screen needs, instead of hiding database traffic behind implicit relation loading.","opensInNewTab":false,"href":"/demo/data/n-plus-one"}],"groups":[{"key":"modeling","label":"Modeling & Workflow","featureCount":3,"features":[{"section":"data","slug":"domain-models","label":"Persistence","title":"Domain-Level Models","summary":"Semitexa separates persistence resources from business models. Resources map tables; domain models carry behavior and invariants.","opensInNewTab":false,"href":"/demo/data/domain-models"},{"section":"data","slug":"repository-workflow","label":"Persistence","title":"Repository Workflow","summary":"The canonical Semitexa path: handlers depend on repository contracts, repositories return domain models, and persistence resources stay behind the boundary.","opensInNewTab":false,"href":"/demo/data/repository-workflow"},{"section":"data","slug":"schema-sync","label":"Persistence","title":"Schema Sync, Not Migration Churn","summary":"Semitexa creates SQL only when the real schema changed, blocks destructive drops by default, and logs the exact DDL plan as SQL and JSON.","opensInNewTab":false,"href":"/demo/data/schema-sync"}]},{"key":"querying","label":"Querying","featureCount":6,"features":[{"section":"data","slug":"query","label":"Persistence","title":"Query Builder","summary":"Compose type-safe queries with a fluent API — no raw SQL, no magic strings.","opensInNewTab":false,"href":"/demo/data/query"},{"section":"data","slug":"filtering","label":"Persistence","title":"Filtering","summary":"Mark a property #[Filterable] and the ORM handles the rest — no manual WHERE clauses.","opensInNewTab":false,"href":"/demo/data/filtering"},{"section":"data","slug":"pagination","label":"Persistence","title":"Pagination","summary":"Offset and cursor pagination out of the box — switch modes with a single query parameter.","opensInNewTab":false,"href":"/demo/data/pagination"},{"section":"data","slug":"relations","label":"Persistence","title":"Relations","summary":"Declare parent and child links on the resource itself, then read typed relations from the handler.","opensInNewTab":false,"href":"/demo/data/relations"},{"section":"data","slug":"table-extension","label":"Persistence","title":"Shared Table Extension","summary":"Two modules can extend one table independently, and the ORM merges the schema without forcing either side to edit the other.","opensInNewTab":false,"href":"/demo/data/table-extension"},{"section":"data","slug":"n-plus-one","label":"Persistence","title":"N+1 Without Magic","summary":"Semitexa avoids N+1 by using resource slices for the exact columns and relations each screen needs, instead of hiding database traffic behind implicit relation loading.","opensInNewTab":false,"href":"/demo/data/n-plus-one"}]}]},{"key":"auth","label":"Security","summary":"Typed session payloads, machine credentials, RBAC, and route protection without string-key auth chaos.","icon":"AU","eyebrow":"Security","starter":false,"prerequisites":[],"featureCount":7,"href":"/demo/auth","features":[{"section":"auth","slug":"session","label":"Security","title":"Session Auth","summary":"Google signs the user in, then the session stores the selected demo role and re-hydrates it on every request.","opensInNewTab":false,"href":"/demo/auth/session"},{"section":"auth","slug":"session-payloads","label":"Security","title":"Session Payloads","summary":"Semitexa forbids string-key session chaos: session state lives in typed Session Payloads or it does not exist.","opensInNewTab":false,"href":"/demo/auth/session-payloads"},{"section":"auth","slug":"google","label":"Security","title":"Google Authorization","summary":"Authorization is required for demo SSE blocks that keep a long-lived backend connection open.","opensInNewTab":false,"href":"/demo/auth/google"},{"section":"auth","slug":"machine","label":"Security","title":"Machine Auth","summary":"Service-to-service authentication via Bearer tokens — scoped, revocable, and audited.","opensInNewTab":false,"href":"/demo/auth/machine"},{"section":"auth","slug":"protected","label":"Security","title":"Protected Route","summary":"Add one access attribute and one optional permission attribute and the framework enforces access — 401 for unauthenticated requests, 403 for unauthorized ones.","opensInNewTab":false,"href":"/demo/auth/protected"},{"section":"auth","slug":"requires-permission","label":"Security","title":"Requires Permission","summary":"Declare one permission slug on the payload and let the framework enforce it before your handler runs.","opensInNewTab":false,"href":"/demo/auth/requires-permission"},{"section":"auth","slug":"rbac","label":"Security","title":"RBAC","summary":"Hybrid RBAC with coarse-grained capabilities, exact permission slugs, and module-owned permission catalogs.","opensInNewTab":false,"href":"/demo/auth/rbac"}],"groups":[{"key":"identity","label":"Identity","featureCount":4,"features":[{"section":"auth","slug":"session","label":"Security","title":"Session Auth","summary":"Google signs the user in, then the session stores the selected demo role and re-hydrates it on every request.","opensInNewTab":false,"href":"/demo/auth/session"},{"section":"auth","slug":"session-payloads","label":"Security","title":"Session Payloads","summary":"Semitexa forbids string-key session chaos: session state lives in typed Session Payloads or it does not exist.","opensInNewTab":false,"href":"/demo/auth/session-payloads"},{"section":"auth","slug":"google","label":"Security","title":"Google Authorization","summary":"Authorization is required for demo SSE blocks that keep a long-lived backend connection open.","opensInNewTab":false,"href":"/demo/auth/google"},{"section":"auth","slug":"machine","label":"Security","title":"Machine Auth","summary":"Service-to-service authentication via Bearer tokens — scoped, revocable, and audited.","opensInNewTab":false,"href":"/demo/auth/machine"}]},{"key":"access-control","label":"Access Control","featureCount":3,"features":[{"section":"auth","slug":"protected","label":"Security","title":"Protected Route","summary":"Add one access attribute and one optional permission attribute and the framework enforces access — 401 for unauthenticated requests, 403 for unauthorized ones.","opensInNewTab":false,"href":"/demo/auth/protected"},{"section":"auth","slug":"requires-permission","label":"Security","title":"Requires Permission","summary":"Declare one permission slug on the payload and let the framework enforce it before your handler runs.","opensInNewTab":false,"href":"/demo/auth/requires-permission"},{"section":"auth","slug":"rbac","label":"Security","title":"RBAC","summary":"Hybrid RBAC with coarse-grained capabilities, exact permission slugs, and module-owned permission catalogs.","opensInNewTab":false,"href":"/demo/auth/rbac"}]}]},{"key":"events","label":"Async","summary":"Synchronous and deferred event flows, queues, and SSE-style interactions.","icon":"EV","eyebrow":"Async","starter":false,"prerequisites":[],"featureCount":5,"href":"/demo/events","features":[{"section":"events","slug":"arena","label":"Async","title":"Execution Arena","summary":"Launch the same backend intent in sync, Swoole async, and queued modes, then watch the proof arrive over SSE.","opensInNewTab":false,"href":"/demo/events/arena"},{"section":"events","slug":"sync","label":"Async","title":"Sync Events","summary":"Dispatch an event and all sync listeners run before the response is sent.","opensInNewTab":false,"href":"/demo/events/sync"},{"section":"events","slug":"deferred","label":"Async","title":"Deferred Handler","summary":"Heavy work runs after the response is sent — the user gets instant feedback.","opensInNewTab":false,"href":"/demo/events/deferred"},{"section":"events","slug":"queued","label":"Async","title":"Queued Handler","summary":"Events survive restarts and scale across workers — backed by a durable message queue.","opensInNewTab":false,"href":"/demo/events/queued"},{"section":"events","slug":"sse","label":"Async","title":"SSE Stream","summary":"Real-time server push without WebSockets — connect once and receive real backend events over plain HTTP.","opensInNewTab":false,"href":"/demo/events/sse"}],"groups":[{"key":"event-flow","label":"Event Flow","featureCount":5,"features":[{"section":"events","slug":"arena","label":"Async","title":"Execution Arena","summary":"Launch the same backend intent in sync, Swoole async, and queued modes, then watch the proof arrive over SSE.","opensInNewTab":false,"href":"/demo/events/arena"},{"section":"events","slug":"sync","label":"Async","title":"Sync Events","summary":"Dispatch an event and all sync listeners run before the response is sent.","opensInNewTab":false,"href":"/demo/events/sync"},{"section":"events","slug":"deferred","label":"Async","title":"Deferred Handler","summary":"Heavy work runs after the response is sent — the user gets instant feedback.","opensInNewTab":false,"href":"/demo/events/deferred"},{"section":"events","slug":"queued","label":"Async","title":"Queued Handler","summary":"Events survive restarts and scale across workers — backed by a durable message queue.","opensInNewTab":false,"href":"/demo/events/queued"},{"section":"events","slug":"sse","label":"Async","title":"SSE Stream","summary":"Real-time server push without WebSockets — connect once and receive real backend events over plain HTTP.","opensInNewTab":false,"href":"/demo/events/sse"}]}]},{"key":"rendering","label":"UI Rendering & SSR","summary":"One rendering story from handler to HTML: page data, page regions, and live updates stay in the same server-driven model instead of splitting into frontend and backend template logic.","icon":"UI","eyebrow":"Frontend","starter":false,"prerequisites":[],"featureCount":15,"href":"/demo/rendering","features":[{"section":"rendering","slug":"philosophy","label":"UI Rendering & SSR","title":"SSR Philosophy","summary":"Semitexa SSR is one continuous rendering architecture: page, slots, deferred regions, live refresh, and interactive components stay inside one server-owned story.","opensInNewTab":false,"href":"/demo/rendering/philosophy"},{"section":"rendering","slug":"resource-dtos","label":"UI Rendering & SSR","title":"Resource DTOs","summary":"A Resource DTO is the one typed source of presentation data: handlers shape it once, templates consume it everywhere, and no view has to dissect random arrays.","opensInNewTab":false,"href":"/demo/rendering/resource-dtos"},{"section":"rendering","slug":"slots","label":"UI Rendering & SSR","title":"Slot Resources","summary":"Each page region is its own resource pipeline with the same template system as the main page — no scattered partial glue, no mystery wiring.","opensInNewTab":false,"href":"/demo/rendering/slots"},{"section":"rendering","slug":"components","label":"UI Rendering & SSR","title":"Components","summary":"Reusable, attribute-registered UI components — discovered automatically from the classmap.","opensInNewTab":false,"href":"/demo/rendering/components"},{"section":"rendering","slug":"seo","label":"UI Rendering & SSR","title":"SEO","summary":"Set title, description, and Open Graph tags from your handler — no template hacks needed.","opensInNewTab":false,"href":"/demo/rendering/seo"},{"section":"rendering","slug":"assets","label":"UI Rendering & SSR","title":"Asset Pipeline","summary":"Declare assets with glob patterns in assets.json — served, versioned, and injected automatically.","opensInNewTab":false,"href":"/demo/rendering/assets"},{"section":"rendering","slug":"component-scripts","label":"UI Rendering & SSR","title":"Component Script Assets","summary":"A Semitexa SSR component can own its optional enhancement asset, so behavior travels with the component instead of leaking into page-level glue.","opensInNewTab":false,"href":"/demo/rendering/component-scripts"},{"section":"rendering","slug":"deferred-scripts","label":"UI Rendering & SSR","title":"Script Injection","summary":"Deferred blocks carry their own JS — injected once when the block arrives, never duplicated.","opensInNewTab":false,"href":"/demo/rendering/deferred-scripts"},{"section":"rendering","slug":"deferred","label":"UI Rendering & SSR","title":"Deferred Blocks","summary":"SSR renders the shell first, then expensive regions stream in as real HTML over SSE — no SPA handoff and no client-side page rebuild.","opensInNewTab":true,"href":"/demo/rendering/deferred"},{"section":"rendering","slug":"deferred-encapsulation","label":"UI Rendering & SSR","title":"Block Isolation","summary":"Two identical blocks on the same page run independently — scoped DOM, scoped JS, no conflicts.","opensInNewTab":false,"href":"/demo/rendering/deferred-encapsulation"},{"section":"rendering","slug":"deferred-live","label":"UI Rendering & SSR","title":"Live Widgets","summary":"A live slot can refresh itself on a timer while the page stays SSR-first — no SPA runtime and no handwritten polling layer.","opensInNewTab":false,"href":"/demo/rendering/deferred-live"},{"section":"rendering","slug":"reactive-report","label":"UI Rendering & SSR","title":"Reactive Report","summary":"Background work updates an SSR-first slot in place, so the UI feels live without falling back to SPA state orchestration.","opensInNewTab":false,"href":"/demo/rendering/reactive-report"},{"section":"rendering","slug":"reactive-import","label":"UI Rendering & SSR","title":"Reactive Import","summary":"Background batches keep moving, and the page reflects server progress as live HTML instead of a client-managed progress app.","opensInNewTab":false,"href":"/demo/rendering/reactive-import"},{"section":"rendering","slug":"reactive-analytics","label":"UI Rendering & SSR","title":"Reactive Analytics","summary":"Independent analytics jobs can light up one dashboard progressively, while the page stays server-rendered from the first byte.","opensInNewTab":false,"href":"/demo/rendering/reactive-analytics"},{"section":"rendering","slug":"reactive-ai","label":"UI Rendering & SSR","title":"Reactive AI Task","summary":"Submit a task and watch the AI pipeline stages reveal one by one as the cron job processes it.","opensInNewTab":false,"href":"/demo/rendering/reactive-ai"}],"groups":[{"key":"rendering-model","label":"SSR Foundation","featureCount":8,"features":[{"section":"rendering","slug":"philosophy","label":"UI Rendering & SSR","title":"SSR Philosophy","summary":"Semitexa SSR is one continuous rendering architecture: page, slots, deferred regions, live refresh, and interactive components stay inside one server-owned story.","opensInNewTab":false,"href":"/demo/rendering/philosophy"},{"section":"rendering","slug":"resource-dtos","label":"UI Rendering & SSR","title":"Resource DTOs","summary":"A Resource DTO is the one typed source of presentation data: handlers shape it once, templates consume it everywhere, and no view has to dissect random arrays.","opensInNewTab":false,"href":"/demo/rendering/resource-dtos"},{"section":"rendering","slug":"slots","label":"UI Rendering & SSR","title":"Slot Resources","summary":"Each page region is its own resource pipeline with the same template system as the main page — no scattered partial glue, no mystery wiring.","opensInNewTab":false,"href":"/demo/rendering/slots"},{"section":"rendering","slug":"components","label":"UI Rendering & SSR","title":"Components","summary":"Reusable, attribute-registered UI components — discovered automatically from the classmap.","opensInNewTab":false,"href":"/demo/rendering/components"},{"section":"rendering","slug":"seo","label":"UI Rendering & SSR","title":"SEO","summary":"Set title, description, and Open Graph tags from your handler — no template hacks needed.","opensInNewTab":false,"href":"/demo/rendering/seo"},{"section":"rendering","slug":"assets","label":"UI Rendering & SSR","title":"Asset Pipeline","summary":"Declare assets with glob patterns in assets.json — served, versioned, and injected automatically.","opensInNewTab":false,"href":"/demo/rendering/assets"},{"section":"rendering","slug":"component-scripts","label":"UI Rendering & SSR","title":"Component Script Assets","summary":"A Semitexa SSR component can own its optional enhancement asset, so behavior travels with the component instead of leaking into page-level glue.","opensInNewTab":false,"href":"/demo/rendering/component-scripts"},{"section":"rendering","slug":"deferred-scripts","label":"UI Rendering & SSR","title":"Script Injection","summary":"Deferred blocks carry their own JS — injected once when the block arrives, never duplicated.","opensInNewTab":false,"href":"/demo/rendering/deferred-scripts"}]},{"key":"deferred","label":"Deferred Delivery","featureCount":2,"features":[{"section":"rendering","slug":"deferred","label":"UI Rendering & SSR","title":"Deferred Blocks","summary":"SSR renders the shell first, then expensive regions stream in as real HTML over SSE — no SPA handoff and no client-side page rebuild.","opensInNewTab":true,"href":"/demo/rendering/deferred"},{"section":"rendering","slug":"deferred-encapsulation","label":"UI Rendering & SSR","title":"Block Isolation","summary":"Two identical blocks on the same page run independently — scoped DOM, scoped JS, no conflicts.","opensInNewTab":false,"href":"/demo/rendering/deferred-encapsulation"}]},{"key":"live","label":"Reactive UI","featureCount":5,"features":[{"section":"rendering","slug":"deferred-live","label":"UI Rendering & SSR","title":"Live Widgets","summary":"A live slot can refresh itself on a timer while the page stays SSR-first — no SPA runtime and no handwritten polling layer.","opensInNewTab":false,"href":"/demo/rendering/deferred-live"},{"section":"rendering","slug":"reactive-report","label":"UI Rendering & SSR","title":"Reactive Report","summary":"Background work updates an SSR-first slot in place, so the UI feels live without falling back to SPA state orchestration.","opensInNewTab":false,"href":"/demo/rendering/reactive-report"},{"section":"rendering","slug":"reactive-import","label":"UI Rendering & SSR","title":"Reactive Import","summary":"Background batches keep moving, and the page reflects server progress as live HTML instead of a client-managed progress app.","opensInNewTab":false,"href":"/demo/rendering/reactive-import"},{"section":"rendering","slug":"reactive-analytics","label":"UI Rendering & SSR","title":"Reactive Analytics","summary":"Independent analytics jobs can light up one dashboard progressively, while the page stays server-rendered from the first byte.","opensInNewTab":false,"href":"/demo/rendering/reactive-analytics"},{"section":"rendering","slug":"reactive-ai","label":"UI Rendering & SSR","title":"Reactive AI Task","summary":"Submit a task and watch the AI pipeline stages reveal one by one as the cron job processes it.","opensInNewTab":false,"href":"/demo/rendering/reactive-ai"}]}]},{"key":"platform","label":"Tenancy","summary":"Multi-tenant resolution, tenant-aware configuration, and strict isolation of data and background work.","icon":"TN","eyebrow":"Multi-Tenant","starter":false,"prerequisites":["data","rendering"],"featureCount":5,"href":"/demo/platform","features":[{"section":"platform","slug":"tenancy-resolution","label":"Tenancy","title":"Tenant Context Resolution","summary":"See how Semitexa resolves the active tenant from subdomain, header, path, or query input before the rest of the platform runs.","opensInNewTab":false,"href":"/demo/platform/tenancy-resolution"},{"section":"platform","slug":"tenancy-config","label":"Tenancy","title":"Per-Tenant Configuration","summary":"Three demo tenants with distinct branding -- switch tenant, everything changes without if/else.","opensInNewTab":false,"href":"/demo/platform/tenancy-config"},{"section":"platform","slug":"tenancy-layers","label":"Tenancy","title":"Multi-Layer Tenancy","summary":"Organization, Locale, Theme, Environment -- four independent layers compose into one TenantContext.","opensInNewTab":false,"href":"/demo/platform/tenancy-layers"},{"section":"platform","slug":"tenancy-isolation","label":"Tenancy","title":"Data Isolation","summary":"Product listing scoped by tenant -- switch tenant, list changes. Zero manual WHERE clauses.","opensInNewTab":false,"href":"/demo/platform/tenancy-isolation"},{"section":"platform","slug":"tenancy-queue","label":"Tenancy","title":"Queue Tenant Propagation","summary":"Tenant context travels with queued jobs -- _tenant key injected automatically, restored by worker.","opensInNewTab":false,"href":"/demo/platform/tenancy-queue"}],"groups":[{"key":"resolution","label":"Tenant Resolution","featureCount":1,"features":[{"section":"platform","slug":"tenancy-resolution","label":"Tenancy","title":"Tenant Context Resolution","summary":"See how Semitexa resolves the active tenant from subdomain, header, path, or query input before the rest of the platform runs.","opensInNewTab":false,"href":"/demo/platform/tenancy-resolution"}]},{"key":"configuration","label":"Tenant Configuration","featureCount":2,"features":[{"section":"platform","slug":"tenancy-config","label":"Tenancy","title":"Per-Tenant Configuration","summary":"Three demo tenants with distinct branding -- switch tenant, everything changes without if/else.","opensInNewTab":false,"href":"/demo/platform/tenancy-config"},{"section":"platform","slug":"tenancy-layers","label":"Tenancy","title":"Multi-Layer Tenancy","summary":"Organization, Locale, Theme, Environment -- four independent layers compose into one TenantContext.","opensInNewTab":false,"href":"/demo/platform/tenancy-layers"}]},{"key":"isolation","label":"Isolation & Work","featureCount":2,"features":[{"section":"platform","slug":"tenancy-isolation","label":"Tenancy","title":"Data Isolation","summary":"Product listing scoped by tenant -- switch tenant, list changes. Zero manual WHERE clauses.","opensInNewTab":false,"href":"/demo/platform/tenancy-isolation"},{"section":"platform","slug":"tenancy-queue","label":"Tenancy","title":"Queue Tenant Propagation","summary":"Tenant context travels with queued jobs -- _tenant key injected automatically, restored by worker.","opensInNewTab":false,"href":"/demo/platform/tenancy-queue"}]}]},{"key":"api","label":"API","summary":"External API endpoints, machine auth, versioning, and consumer-facing schema behavior.","icon":"API","eyebrow":"Machine","starter":false,"prerequisites":["routing","auth"],"featureCount":7,"href":"/demo/api","features":[{"section":"api","slug":"rest-api","label":"API","title":"REST API","summary":"Classic Semitexa REST endpoints with typed payloads, versioning, and consumer-friendly response shaping.","opensInNewTab":false,"href":"/demo/api/rest-api"},{"section":"api","slug":"structured-errors","label":"API","title":"Structured Errors","summary":"Throw domain exceptions and let semitexa-api map them into stable machine-readable error envelopes.","opensInNewTab":false,"href":"/demo/api/structured-errors"},{"section":"api","slug":"active-version","label":"API","title":"Active Version","summary":"The current collection endpoint with a clean X-Api-Version header and no deprecation noise.","opensInNewTab":false,"href":"/demo/api/active-version"},{"section":"api","slug":"sunset-version","label":"API","title":"Sunset Version","summary":"A deprecated product endpoint that emits both Deprecation and Sunset headers.","opensInNewTab":false,"href":"/demo/api/sunset-version"},{"section":"api","slug":"schema-discovery","label":"API","title":"Schema Discovery","summary":"A mini Swagger-style explorer for the live product API contract, schema endpoint, and response shapes.","opensInNewTab":false,"href":"/demo/api/schema-discovery"},{"section":"api","slug":"graphql","label":"API","title":"GraphQL API","summary":"GraphQL-first Semitexa contracts built with typed payloads and typed output DTOs instead of resolver sprawl.","opensInNewTab":false,"href":"/demo/api/graphql"},{"section":"api","slug":"rest-graphql","label":"API","title":"REST + GraphQL","summary":"One Semitexa use case can serve both REST and GraphQL without duplicating handler logic into separate resolver classes.","opensInNewTab":false,"href":"/demo/api/rest-graphql"}],"groups":[{"key":"public-api","label":"REST Surface","featureCount":4,"features":[{"section":"api","slug":"rest-api","label":"API","title":"REST API","summary":"Classic Semitexa REST endpoints with typed payloads, versioning, and consumer-friendly response shaping.","opensInNewTab":false,"href":"/demo/api/rest-api"},{"section":"api","slug":"structured-errors","label":"API","title":"Structured Errors","summary":"Throw domain exceptions and let semitexa-api map them into stable machine-readable error envelopes.","opensInNewTab":false,"href":"/demo/api/structured-errors"},{"section":"api","slug":"active-version","label":"API","title":"Active Version","summary":"The current collection endpoint with a clean X-Api-Version header and no deprecation noise.","opensInNewTab":false,"href":"/demo/api/active-version"},{"section":"api","slug":"sunset-version","label":"API","title":"Sunset Version","summary":"A deprecated product endpoint that emits both Deprecation and Sunset headers.","opensInNewTab":false,"href":"/demo/api/sunset-version"}]},{"key":"schema","label":"Schema Discovery","featureCount":3,"features":[{"section":"api","slug":"schema-discovery","label":"API","title":"Schema Discovery","summary":"A mini Swagger-style explorer for the live product API contract, schema endpoint, and response shapes.","opensInNewTab":false,"href":"/demo/api/schema-discovery"},{"section":"api","slug":"graphql","label":"API","title":"GraphQL API","summary":"GraphQL-first Semitexa contracts built with typed payloads and typed output DTOs instead of resolver sprawl.","opensInNewTab":false,"href":"/demo/api/graphql"},{"section":"api","slug":"rest-graphql","label":"API","title":"REST + GraphQL","summary":"One Semitexa use case can serve both REST and GraphQL without duplicating handler logic into separate resolver classes.","opensInNewTab":false,"href":"/demo/api/rest-graphql"}]}]},{"key":"cli","label":"CLI","summary":"Operational, introspection, and AI-oriented command surfaces that explain and drive the framework from the terminal.","icon":"CLI","eyebrow":"Operations","starter":false,"prerequisites":["routing"],"featureCount":6,"href":"/demo/cli","features":[{"section":"cli","slug":"describe-commands","label":"CLI","title":"Project Graph Introspection","summary":"Routes, modules, contracts, and handlers can be introspected directly from the CLI instead of reverse-engineering the framework graph by hand.","opensInNewTab":false,"href":"/demo/cli/describe-commands"},{"section":"cli","slug":"runtime-maintenance","label":"CLI","title":"Runtime Maintenance","summary":"Reload workers, clear stale cache, sync registries, lint architecture rules, and probe handler wiring without reaching for ad-hoc shell scripts.","opensInNewTab":false,"href":"/demo/cli/runtime-maintenance"},{"section":"cli","slug":"scaffolding-generators","label":"CLI","title":"Scaffolding Generators","summary":"Scaffold modules, pages, payloads, services, and contracts through commands that already understand Semitexa structure and AI-friendly output modes.","opensInNewTab":false,"href":"/demo/cli/scaffolding-generators"},{"section":"cli","slug":"workers-scheduling","label":"CLI","title":"Workers & Scheduling","summary":"Run queues, scheduler pools, mail delivery, webhooks, and tenant-scoped commands from a coherent operator surface instead of bespoke daemons.","opensInNewTab":false,"href":"/demo/cli/workers-scheduling"},{"section":"cli","slug":"ai-tooling","label":"CLI","title":"AI Tooling Surface","summary":"Semitexa exposes AI-facing commands as explicit CLI contracts: capabilities, skills, log access, and a local assistant entrypoint.","opensInNewTab":false,"href":"/demo/cli/ai-tooling"},{"section":"cli","slug":"orm-console","label":"CLI","title":"ORM Console Toolkit","summary":"The ORM ships with a practical CLI surface: status, diff, sync, and seed commands with dry-run safety and SQL plan export.","opensInNewTab":false,"href":"/demo/cli/orm-console"}],"groups":[{"key":"inspection","label":"Describe & Inspect","featureCount":2,"features":[{"section":"cli","slug":"describe-commands","label":"CLI","title":"Project Graph Introspection","summary":"Routes, modules, contracts, and handlers can be introspected directly from the CLI instead of reverse-engineering the framework graph by hand.","opensInNewTab":false,"href":"/demo/cli/describe-commands"},{"section":"cli","slug":"runtime-maintenance","label":"CLI","title":"Runtime Maintenance","summary":"Reload workers, clear stale cache, sync registries, lint architecture rules, and probe handler wiring without reaching for ad-hoc shell scripts.","opensInNewTab":false,"href":"/demo/cli/runtime-maintenance"}]},{"key":"automation","label":"Automation","featureCount":4,"features":[{"section":"cli","slug":"scaffolding-generators","label":"CLI","title":"Scaffolding Generators","summary":"Scaffold modules, pages, payloads, services, and contracts through commands that already understand Semitexa structure and AI-friendly output modes.","opensInNewTab":false,"href":"/demo/cli/scaffolding-generators"},{"section":"cli","slug":"workers-scheduling","label":"CLI","title":"Workers & Scheduling","summary":"Run queues, scheduler pools, mail delivery, webhooks, and tenant-scoped commands from a coherent operator surface instead of bespoke daemons.","opensInNewTab":false,"href":"/demo/cli/workers-scheduling"},{"section":"cli","slug":"ai-tooling","label":"CLI","title":"AI Tooling Surface","summary":"Semitexa exposes AI-facing commands as explicit CLI contracts: capabilities, skills, log access, and a local assistant entrypoint.","opensInNewTab":false,"href":"/demo/cli/ai-tooling"},{"section":"cli","slug":"orm-console","label":"CLI","title":"ORM Console Toolkit","summary":"The ORM ships with a practical CLI surface: status, diff, sync, and seed commands with dry-run safety and SQL plan export.","opensInNewTab":false,"href":"/demo/cli/orm-console"}]}]},{"key":"llm","label":"LLM Module","sidebarLabel":"LLM","summary":"The dedicated `semitexa/llm` module: AI assistant entrypoint, skill discovery, planner, executor, provider backends, and skill authoring rules.","icon":"AI","eyebrow":"semitexa/llm","starter":false,"prerequisites":["cli"],"featureCount":4,"href":"/demo/llm","features":[{"section":"llm","slug":"overview","label":"LLM Module","title":"LLM Module Overview","summary":"What `semitexa/llm` adds to the framework and how your project can expose its own CLI skills to the assistant.","opensInNewTab":false,"href":"/demo/llm/overview"},{"section":"llm","slug":"providers","label":"LLM Module","title":"Providers & Backends","summary":"Provider contracts, backend resolution, local vs remote Ollama, and the environment knobs that shape LLM runtime behavior.","opensInNewTab":false,"href":"/demo/llm/providers"},{"section":"llm","slug":"skills","label":"LLM Module","title":"Adding Skills","summary":"How a console command becomes AI-executable through `#[AsAiSkill]`, metadata policy, and registry discovery.","opensInNewTab":false,"href":"/demo/llm/skills"},{"section":"llm","slug":"execution-flow","label":"LLM Module","title":"Execution Flow","summary":"How a user request becomes a planner decision, a reviewed skill proposal, and finally a real console execution.","opensInNewTab":false,"href":"/demo/llm/execution-flow"}],"groups":[{"key":"assistant-basics","label":"Assistant Surface","featureCount":2,"features":[{"section":"llm","slug":"overview","label":"LLM Module","title":"LLM Module Overview","summary":"What `semitexa/llm` adds to the framework and how your project can expose its own CLI skills to the assistant.","opensInNewTab":false,"href":"/demo/llm/overview"},{"section":"llm","slug":"providers","label":"LLM Module","title":"Providers & Backends","summary":"Provider contracts, backend resolution, local vs remote Ollama, and the environment knobs that shape LLM runtime behavior.","opensInNewTab":false,"href":"/demo/llm/providers"}]},{"key":"skill-system","label":"Skill System","featureCount":2,"features":[{"section":"llm","slug":"skills","label":"LLM Module","title":"Adding Skills","summary":"How a console command becomes AI-executable through `#[AsAiSkill]`, metadata policy, and registry discovery.","opensInNewTab":false,"href":"/demo/llm/skills"},{"section":"llm","slug":"execution-flow","label":"LLM Module","title":"Execution Flow","summary":"How a user request becomes a planner decision, a reviewed skill proposal, and finally a real console execution.","opensInNewTab":false,"href":"/demo/llm/execution-flow"}]}]},{"key":"project-graph","label":"Project Graph","summary":"The `semitexa-project-graph` package: stored structural graph, intelligence layer, impact analysis, and task-scoped context for serious repository work.","icon":"PG","eyebrow":"AI Accelerator","starter":true,"prerequisites":["cli"],"featureCount":3,"href":"/demo/project-graph","features":[{"section":"project-graph","slug":"overview","label":"Project Graph","title":"Project Graph Overview","summary":"Understand what `semitexa-project-graph` adds: a stored structural map, an intelligence layer, and task-scoped context for large-codebase work.","opensInNewTab":false,"href":"/demo/project-graph/overview"},{"section":"project-graph","slug":"inspection","label":"Project Graph","title":"Inspecting the Graph","summary":"Use Project Graph queries and intelligence views to inspect modules, dependencies, flows, events, and hotspots without reconstructing the repository manually.","opensInNewTab":false,"href":"/demo/project-graph/inspection"},{"section":"project-graph","slug":"impact","label":"Project Graph","title":"Impact, Context, and Watch Mode","summary":"Use impact analysis, context packing, and watch mode to scope risky changes and keep graph-backed answers current during long work sessions.","opensInNewTab":false,"href":"/demo/project-graph/impact"}],"groups":[{"key":"launch","label":"Start Here","featureCount":1,"features":[{"section":"project-graph","slug":"overview","label":"Project Graph","title":"Project Graph Overview","summary":"Understand what `semitexa-project-graph` adds: a stored structural map, an intelligence layer, and task-scoped context for large-codebase work.","opensInNewTab":false,"href":"/demo/project-graph/overview"}]},{"key":"exploration","label":"Explore & Inspect","featureCount":1,"features":[{"section":"project-graph","slug":"inspection","label":"Project Graph","title":"Inspecting the Graph","summary":"Use Project Graph queries and intelligence views to inspect modules, dependencies, flows, events, and hotspots without reconstructing the repository manually.","opensInNewTab":false,"href":"/demo/project-graph/inspection"}]},{"key":"change-safety","label":"Impact & Context","featureCount":1,"features":[{"section":"project-graph","slug":"impact","label":"Project Graph","title":"Impact, Context, and Watch Mode","summary":"Use impact analysis, context packing, and watch mode to scope risky changes and keep graph-backed answers current during long work sessions.","opensInNewTab":false,"href":"/demo/project-graph/impact"}]}]},{"key":"testing","label":"Testing","summary":"Contract-level verification patterns for payloads and other framework boundaries.","icon":"QA","eyebrow":"Verification","starter":false,"prerequisites":["routing"],"featureCount":1,"href":"/demo/testing","features":[{"section":"testing","slug":"payload-contracts","label":"Testing","title":"Payload Contract Testing","summary":"Run one project-level contract suite through the canonical test runner and let strategy profiles verify payload boundaries without hand-writing repetitive negative cases.","opensInNewTab":false,"href":"/demo/testing/payload-contracts"}],"groups":[{"key":"contracts","label":"Contracts","featureCount":1,"features":[{"section":"testing","slug":"payload-contracts","label":"Testing","title":"Payload Contract Testing","summary":"Run one project-level contract suite through the canonical test runner and let strategy profiles verify payload boundaries without hand-writing repetitive negative cases.","opensInNewTab":false,"href":"/demo/testing/payload-contracts"}]}]}],"featureTree":[{"key":"start-here","label":"Start Here","eyebrow":"Guided path","summary":"The smallest reliable sequence that makes Semitexa feel like a system instead of a brochure.","type":"feature-links","href":"/#start-here","features":[{"section":"get-started","slug":"installation","label":"Start Here","title":"Installation","summary":"Create the project, review the baseline env contract, and bring up the Semitexa runtime the supported way.","opensInNewTab":false,"href":"/demo/get-started/installation"},{"section":"get-started","slug":"local-domain","label":"Start Here","title":"Local Domain","summary":"Register .test domains through the built-in local-domain helper instead of relying on ad hoc host setup.","opensInNewTab":false,"href":"/demo/get-started/local-domain"},{"section":"get-started","slug":"module-structure","label":"Start Here","title":"Module Structure","summary":"The minimal Semitexa module is a typed HTTP spine of payload, handler, resource, and template.","opensInNewTab":false,"href":"/demo/get-started/module-structure"},{"section":"get-started","slug":"base-tenant","label":"Start Here","title":"Base Tenant","summary":"Establish one default tenant context early so tenant-aware behavior is visible before the rest of the application grows.","opensInNewTab":false,"href":"/demo/get-started/base-tenant"},{"section":"get-started","slug":"locale-setup","label":"Start Here","title":"Locale Setup","summary":"Configure the minimal Locale contract so translations and locale-aware rendering become explicit early.","opensInNewTab":false,"href":"/demo/get-started/locale-setup"},{"section":"get-started","slug":"ai-console","label":"Start Here","title":"AI Console","summary":"Use the Semitexa AI console as a command translation surface over real operator commands.","opensInNewTab":false,"href":"/demo/get-started/ai-console"},{"section":"project-graph","slug":"overview","label":"Project Graph","title":"Project Graph Overview","summary":"Understand what `semitexa-project-graph` adds: a stored structural map, an intelligence layer, and task-scoped context for large-codebase work.","opensInNewTab":false,"href":"/demo/project-graph/overview"},{"section":"routing","slug":"basic","label":"Routing & Handlers","title":"Basic Route","summary":"Define a route with one access attribute on the payload — no XML, no YAML, no config files.","opensInNewTab":false,"href":"/demo/routing/basic"},{"section":"di","slug":"overview","label":"Dependency Injection","title":"DI Canon","summary":"One canonical DI path for container-managed classes: explicit properties, explicit lifecycles, deterministic boot.","opensInNewTab":false,"href":"/demo/di/overview"}],"featureCount":9},{"key":"full-catalog","label":"Full Catalog","eyebrow":"Route-first map","summary":"The exhaustive live map, still route-first, still real, and still one click away from every feature route.","type":"section-groups","href":"/#full-catalog","sectionKeys":["get-started","routing","di","data","auth","events","rendering","platform","api","cli","project-graph","llm","testing"],"featureCount":81,"sections":[{"key":"get-started","label":"Start Here","sidebarLabel":"Get Started","summary":"The shortest path from fresh scaffold to a trustworthy local Semitexa runtime: install, boot, understand the module map, bind a real host, and reach the first tenant boundary.","icon":"GO","eyebrow":"Onboarding","starter":true,"prerequisites":[],"featureCount":7,"href":"/demo/get-started","features":[{"section":"get-started","slug":"module-structure","label":"Start Here","title":"Module Structure","summary":"The minimal Semitexa module is a typed HTTP spine of payload, handler, resource, and template.","opensInNewTab":false,"href":"/demo/get-started/module-structure"},{"section":"get-started","slug":"installation","label":"Start Here","title":"Installation","summary":"Create the project, review the baseline env contract, and bring up the Semitexa runtime the supported way.","opensInNewTab":false,"href":"/demo/get-started/installation"},{"section":"get-started","slug":"local-domain","label":"Start Here","title":"Local Domain","summary":"Register .test domains through the built-in local-domain helper instead of relying on ad hoc host setup.","opensInNewTab":false,"href":"/demo/get-started/local-domain"},{"section":"get-started","slug":"base-tenant","label":"Start Here","title":"Base Tenant","summary":"Establish one default tenant context early so tenant-aware behavior is visible before the rest of the application grows.","opensInNewTab":false,"href":"/demo/get-started/base-tenant"},{"section":"get-started","slug":"locale-setup","label":"Start Here","title":"Locale Setup","summary":"Configure the minimal Locale contract so translations and locale-aware rendering become explicit early.","opensInNewTab":false,"href":"/demo/get-started/locale-setup"},{"section":"get-started","slug":"ai-console","label":"Start Here","title":"AI Console","summary":"Use the Semitexa AI console as a command translation surface over real operator commands.","opensInNewTab":false,"href":"/demo/get-started/ai-console"},{"section":"get-started","slug":"beyond-controllers","label":"Start Here","title":"Beyond Controllers","summary":"Understand why Semitexa keeps transport, use case, and rendering as separate explicit responsibilities.","opensInNewTab":false,"href":"/demo/get-started/beyond-controllers"}],"groups":[{"key":"structure","label":"Module Structure","featureCount":1,"features":[{"section":"get-started","slug":"module-structure","label":"Start Here","title":"Module Structure","summary":"The minimal Semitexa module is a typed HTTP spine of payload, handler, resource, and template.","opensInNewTab":false,"href":"/demo/get-started/module-structure"}]},{"key":"onboarding","label":"Onboarding","featureCount":6,"features":[{"section":"get-started","slug":"installation","label":"Start Here","title":"Installation","summary":"Create the project, review the baseline env contract, and bring up the Semitexa runtime the supported way.","opensInNewTab":false,"href":"/demo/get-started/installation"},{"section":"get-started","slug":"local-domain","label":"Start Here","title":"Local Domain","summary":"Register .test domains through the built-in local-domain helper instead of relying on ad hoc host setup.","opensInNewTab":false,"href":"/demo/get-started/local-domain"},{"section":"get-started","slug":"base-tenant","label":"Start Here","title":"Base Tenant","summary":"Establish one default tenant context early so tenant-aware behavior is visible before the rest of the application grows.","opensInNewTab":false,"href":"/demo/get-started/base-tenant"},{"section":"get-started","slug":"locale-setup","label":"Start Here","title":"Locale Setup","summary":"Configure the minimal Locale contract so translations and locale-aware rendering become explicit early.","opensInNewTab":false,"href":"/demo/get-started/locale-setup"},{"section":"get-started","slug":"ai-console","label":"Start Here","title":"AI Console","summary":"Use the Semitexa AI console as a command translation surface over real operator commands.","opensInNewTab":false,"href":"/demo/get-started/ai-console"},{"section":"get-started","slug":"beyond-controllers","label":"Start Here","title":"Beyond Controllers","summary":"Understand why Semitexa keeps transport, use case, and rendering as separate explicit responsibilities.","opensInNewTab":false,"href":"/demo/get-started/beyond-controllers"}]}]},{"key":"routing","label":"Routing & Handlers","summary":"Attribute-driven routes, typed handlers, and content negotiation in one coherent request pipeline.","icon":"RT","eyebrow":"HTTP Layer","starter":true,"prerequisites":[],"featureCount":7,"href":"/demo/routing","features":[{"section":"routing","slug":"basic","label":"Routing & Handlers","title":"Basic Route","summary":"Define a route with one access attribute on the payload — no XML, no YAML, no config files.","opensInNewTab":false,"href":"/demo/routing/basic"},{"section":"routing","slug":"parameterized","label":"Routing & Handlers","title":"Parameterized Route","summary":"Path parameters with regex constraints and typed injection.","opensInNewTab":false,"href":"/demo/routing/parameterized/headphones"},{"section":"routing","slug":"env-route-override","label":"Routing & Handlers","title":"Env Route Override","summary":"Keep the payload as the route source of truth while allowing operations to remap the public URL through .env.","opensInNewTab":false,"href":"/demo/routing/env-route-override"},{"section":"routing","slug":"payload-shield","label":"Routing & Handlers","title":"Payload As A Shield","summary":"Hydration happens before the handler, and each setter owns the normalization and guard logic for its own field.","opensInNewTab":false,"href":"/demo/routing/payload-shield"},{"section":"routing","slug":"payload-parts","label":"Routing & Handlers","title":"Payload Parts","summary":"One module owns the route, another module can extend the same payload contract without forking or reopening the base class.","opensInNewTab":false,"href":"/demo/routing/payload-parts"},{"section":"routing","slug":"content-negotiation","label":"Routing & Handlers","title":"Content Negotiation","summary":"One endpoint, multiple response formats — automatically.","opensInNewTab":false,"href":"/demo/routing/content-negotiation"},{"section":"routing","slug":"public-endpoint","label":"Routing & Handlers","title":"Public Payload","summary":"Anonymous endpoints opt in explicitly with the public access attribute. Every other payload requires authentication.","opensInNewTab":false,"href":"/demo/routing/public-endpoint"}],"groups":[{"key":"foundations","label":"Foundations","featureCount":3,"features":[{"section":"routing","slug":"basic","label":"Routing & Handlers","title":"Basic Route","summary":"Define a route with one access attribute on the payload — no XML, no YAML, no config files.","opensInNewTab":false,"href":"/demo/routing/basic"},{"section":"routing","slug":"parameterized","label":"Routing & Handlers","title":"Parameterized Route","summary":"Path parameters with regex constraints and typed injection.","opensInNewTab":false,"href":"/demo/routing/parameterized/headphones"},{"section":"routing","slug":"env-route-override","label":"Routing & Handlers","title":"Env Route Override","summary":"Keep the payload as the route source of truth while allowing operations to remap the public URL through .env.","opensInNewTab":false,"href":"/demo/routing/env-route-override"}]},{"key":"request-model","label":"Request Model","featureCount":2,"features":[{"section":"routing","slug":"payload-shield","label":"Routing & Handlers","title":"Payload As A Shield","summary":"Hydration happens before the handler, and each setter owns the normalization and guard logic for its own field.","opensInNewTab":false,"href":"/demo/routing/payload-shield"},{"section":"routing","slug":"payload-parts","label":"Routing & Handlers","title":"Payload Parts","summary":"One module owns the route, another module can extend the same payload contract without forking or reopening the base class.","opensInNewTab":false,"href":"/demo/routing/payload-parts"}]},{"key":"delivery","label":"Delivery","featureCount":2,"features":[{"section":"routing","slug":"content-negotiation","label":"Routing & Handlers","title":"Content Negotiation","summary":"One endpoint, multiple response formats — automatically.","opensInNewTab":false,"href":"/demo/routing/content-negotiation"},{"section":"routing","slug":"public-endpoint","label":"Routing & Handlers","title":"Public Payload","summary":"Anonymous endpoints opt in explicitly with the public access attribute. Every other payload requires authentication.","opensInNewTab":false,"href":"/demo/routing/public-endpoint"}]}]},{"key":"di","label":"Dependency Injection","summary":"Single-path DI with explicit lifecycles, deterministic contracts, and stable boot behavior for long-running workers.","icon":"DI","eyebrow":"Container","starter":true,"prerequisites":[],"featureCount":5,"href":"/demo/di","features":[{"section":"di","slug":"overview","label":"Dependency Injection","title":"DI Canon","summary":"One canonical DI path for container-managed classes: explicit properties, explicit lifecycles, deterministic boot.","opensInNewTab":false,"href":"/demo/di/overview"},{"section":"di","slug":"readonly","label":"Dependency Injection","title":"Readonly Injection","summary":"One explicit DI path, one shared worker instance — fast at runtime and stable under reload.","opensInNewTab":false,"href":"/demo/di/readonly"},{"section":"di","slug":"mutable","label":"Dependency Injection","title":"Mutable Injection","summary":"Execution-scoped services get a fresh clone every run — safe state without contaminating the worker.","opensInNewTab":false,"href":"/demo/di/mutable"},{"section":"di","slug":"factory","label":"Dependency Injection","title":"Factory Injection","summary":"On-demand creation stays explicit — lazy instances without falling back to service locator habits.","opensInNewTab":false,"href":"/demo/di/factory"},{"section":"di","slug":"contracts","label":"Dependency Injection","title":"Service Contracts","summary":"Depend on contracts, but keep ownership explicit — deterministic substitution instead of runtime magic.","opensInNewTab":false,"href":"/demo/di/contracts"}],"groups":[{"key":"container-basics","label":"Container Basics","featureCount":5,"features":[{"section":"di","slug":"overview","label":"Dependency Injection","title":"DI Canon","summary":"One canonical DI path for container-managed classes: explicit properties, explicit lifecycles, deterministic boot.","opensInNewTab":false,"href":"/demo/di/overview"},{"section":"di","slug":"readonly","label":"Dependency Injection","title":"Readonly Injection","summary":"One explicit DI path, one shared worker instance — fast at runtime and stable under reload.","opensInNewTab":false,"href":"/demo/di/readonly"},{"section":"di","slug":"mutable","label":"Dependency Injection","title":"Mutable Injection","summary":"Execution-scoped services get a fresh clone every run — safe state without contaminating the worker.","opensInNewTab":false,"href":"/demo/di/mutable"},{"section":"di","slug":"factory","label":"Dependency Injection","title":"Factory Injection","summary":"On-demand creation stays explicit — lazy instances without falling back to service locator habits.","opensInNewTab":false,"href":"/demo/di/factory"},{"section":"di","slug":"contracts","label":"Dependency Injection","title":"Service Contracts","summary":"Depend on contracts, but keep ownership explicit — deterministic substitution instead of runtime magic.","opensInNewTab":false,"href":"/demo/di/contracts"}]}]},{"key":"data","label":"Persistence","summary":"Attribute-mapped resources, repositories, filtering, pagination, and relations with real demo data.","icon":"DB","eyebrow":"Persistence","starter":true,"prerequisites":[],"featureCount":9,"href":"/demo/data","features":[{"section":"data","slug":"domain-models","label":"Persistence","title":"Domain-Level Models","summary":"Semitexa separates persistence resources from business models. Resources map tables; domain models carry behavior and invariants.","opensInNewTab":false,"href":"/demo/data/domain-models"},{"section":"data","slug":"repository-workflow","label":"Persistence","title":"Repository Workflow","summary":"The canonical Semitexa path: handlers depend on repository contracts, repositories return domain models, and persistence resources stay behind the boundary.","opensInNewTab":false,"href":"/demo/data/repository-workflow"},{"section":"data","slug":"schema-sync","label":"Persistence","title":"Schema Sync, Not Migration Churn","summary":"Semitexa creates SQL only when the real schema changed, blocks destructive drops by default, and logs the exact DDL plan as SQL and JSON.","opensInNewTab":false,"href":"/demo/data/schema-sync"},{"section":"data","slug":"query","label":"Persistence","title":"Query Builder","summary":"Compose type-safe queries with a fluent API — no raw SQL, no magic strings.","opensInNewTab":false,"href":"/demo/data/query"},{"section":"data","slug":"filtering","label":"Persistence","title":"Filtering","summary":"Mark a property #[Filterable] and the ORM handles the rest — no manual WHERE clauses.","opensInNewTab":false,"href":"/demo/data/filtering"},{"section":"data","slug":"pagination","label":"Persistence","title":"Pagination","summary":"Offset and cursor pagination out of the box — switch modes with a single query parameter.","opensInNewTab":false,"href":"/demo/data/pagination"},{"section":"data","slug":"relations","label":"Persistence","title":"Relations","summary":"Declare parent and child links on the resource itself, then read typed relations from the handler.","opensInNewTab":false,"href":"/demo/data/relations"},{"section":"data","slug":"table-extension","label":"Persistence","title":"Shared Table Extension","summary":"Two modules can extend one table independently, and the ORM merges the schema without forcing either side to edit the other.","opensInNewTab":false,"href":"/demo/data/table-extension"},{"section":"data","slug":"n-plus-one","label":"Persistence","title":"N+1 Without Magic","summary":"Semitexa avoids N+1 by using resource slices for the exact columns and relations each screen needs, instead of hiding database traffic behind implicit relation loading.","opensInNewTab":false,"href":"/demo/data/n-plus-one"}],"groups":[{"key":"modeling","label":"Modeling & Workflow","featureCount":3,"features":[{"section":"data","slug":"domain-models","label":"Persistence","title":"Domain-Level Models","summary":"Semitexa separates persistence resources from business models. Resources map tables; domain models carry behavior and invariants.","opensInNewTab":false,"href":"/demo/data/domain-models"},{"section":"data","slug":"repository-workflow","label":"Persistence","title":"Repository Workflow","summary":"The canonical Semitexa path: handlers depend on repository contracts, repositories return domain models, and persistence resources stay behind the boundary.","opensInNewTab":false,"href":"/demo/data/repository-workflow"},{"section":"data","slug":"schema-sync","label":"Persistence","title":"Schema Sync, Not Migration Churn","summary":"Semitexa creates SQL only when the real schema changed, blocks destructive drops by default, and logs the exact DDL plan as SQL and JSON.","opensInNewTab":false,"href":"/demo/data/schema-sync"}]},{"key":"querying","label":"Querying","featureCount":6,"features":[{"section":"data","slug":"query","label":"Persistence","title":"Query Builder","summary":"Compose type-safe queries with a fluent API — no raw SQL, no magic strings.","opensInNewTab":false,"href":"/demo/data/query"},{"section":"data","slug":"filtering","label":"Persistence","title":"Filtering","summary":"Mark a property #[Filterable] and the ORM handles the rest — no manual WHERE clauses.","opensInNewTab":false,"href":"/demo/data/filtering"},{"section":"data","slug":"pagination","label":"Persistence","title":"Pagination","summary":"Offset and cursor pagination out of the box — switch modes with a single query parameter.","opensInNewTab":false,"href":"/demo/data/pagination"},{"section":"data","slug":"relations","label":"Persistence","title":"Relations","summary":"Declare parent and child links on the resource itself, then read typed relations from the handler.","opensInNewTab":false,"href":"/demo/data/relations"},{"section":"data","slug":"table-extension","label":"Persistence","title":"Shared Table Extension","summary":"Two modules can extend one table independently, and the ORM merges the schema without forcing either side to edit the other.","opensInNewTab":false,"href":"/demo/data/table-extension"},{"section":"data","slug":"n-plus-one","label":"Persistence","title":"N+1 Without Magic","summary":"Semitexa avoids N+1 by using resource slices for the exact columns and relations each screen needs, instead of hiding database traffic behind implicit relation loading.","opensInNewTab":false,"href":"/demo/data/n-plus-one"}]}]},{"key":"auth","label":"Security","summary":"Typed session payloads, machine credentials, RBAC, and route protection without string-key auth chaos.","icon":"AU","eyebrow":"Security","starter":false,"prerequisites":[],"featureCount":7,"href":"/demo/auth","features":[{"section":"auth","slug":"session","label":"Security","title":"Session Auth","summary":"Google signs the user in, then the session stores the selected demo role and re-hydrates it on every request.","opensInNewTab":false,"href":"/demo/auth/session"},{"section":"auth","slug":"session-payloads","label":"Security","title":"Session Payloads","summary":"Semitexa forbids string-key session chaos: session state lives in typed Session Payloads or it does not exist.","opensInNewTab":false,"href":"/demo/auth/session-payloads"},{"section":"auth","slug":"google","label":"Security","title":"Google Authorization","summary":"Authorization is required for demo SSE blocks that keep a long-lived backend connection open.","opensInNewTab":false,"href":"/demo/auth/google"},{"section":"auth","slug":"machine","label":"Security","title":"Machine Auth","summary":"Service-to-service authentication via Bearer tokens — scoped, revocable, and audited.","opensInNewTab":false,"href":"/demo/auth/machine"},{"section":"auth","slug":"protected","label":"Security","title":"Protected Route","summary":"Add one access attribute and one optional permission attribute and the framework enforces access — 401 for unauthenticated requests, 403 for unauthorized ones.","opensInNewTab":false,"href":"/demo/auth/protected"},{"section":"auth","slug":"requires-permission","label":"Security","title":"Requires Permission","summary":"Declare one permission slug on the payload and let the framework enforce it before your handler runs.","opensInNewTab":false,"href":"/demo/auth/requires-permission"},{"section":"auth","slug":"rbac","label":"Security","title":"RBAC","summary":"Hybrid RBAC with coarse-grained capabilities, exact permission slugs, and module-owned permission catalogs.","opensInNewTab":false,"href":"/demo/auth/rbac"}],"groups":[{"key":"identity","label":"Identity","featureCount":4,"features":[{"section":"auth","slug":"session","label":"Security","title":"Session Auth","summary":"Google signs the user in, then the session stores the selected demo role and re-hydrates it on every request.","opensInNewTab":false,"href":"/demo/auth/session"},{"section":"auth","slug":"session-payloads","label":"Security","title":"Session Payloads","summary":"Semitexa forbids string-key session chaos: session state lives in typed Session Payloads or it does not exist.","opensInNewTab":false,"href":"/demo/auth/session-payloads"},{"section":"auth","slug":"google","label":"Security","title":"Google Authorization","summary":"Authorization is required for demo SSE blocks that keep a long-lived backend connection open.","opensInNewTab":false,"href":"/demo/auth/google"},{"section":"auth","slug":"machine","label":"Security","title":"Machine Auth","summary":"Service-to-service authentication via Bearer tokens — scoped, revocable, and audited.","opensInNewTab":false,"href":"/demo/auth/machine"}]},{"key":"access-control","label":"Access Control","featureCount":3,"features":[{"section":"auth","slug":"protected","label":"Security","title":"Protected Route","summary":"Add one access attribute and one optional permission attribute and the framework enforces access — 401 for unauthenticated requests, 403 for unauthorized ones.","opensInNewTab":false,"href":"/demo/auth/protected"},{"section":"auth","slug":"requires-permission","label":"Security","title":"Requires Permission","summary":"Declare one permission slug on the payload and let the framework enforce it before your handler runs.","opensInNewTab":false,"href":"/demo/auth/requires-permission"},{"section":"auth","slug":"rbac","label":"Security","title":"RBAC","summary":"Hybrid RBAC with coarse-grained capabilities, exact permission slugs, and module-owned permission catalogs.","opensInNewTab":false,"href":"/demo/auth/rbac"}]}]},{"key":"events","label":"Async","summary":"Synchronous and deferred event flows, queues, and SSE-style interactions.","icon":"EV","eyebrow":"Async","starter":false,"prerequisites":[],"featureCount":5,"href":"/demo/events","features":[{"section":"events","slug":"arena","label":"Async","title":"Execution Arena","summary":"Launch the same backend intent in sync, Swoole async, and queued modes, then watch the proof arrive over SSE.","opensInNewTab":false,"href":"/demo/events/arena"},{"section":"events","slug":"sync","label":"Async","title":"Sync Events","summary":"Dispatch an event and all sync listeners run before the response is sent.","opensInNewTab":false,"href":"/demo/events/sync"},{"section":"events","slug":"deferred","label":"Async","title":"Deferred Handler","summary":"Heavy work runs after the response is sent — the user gets instant feedback.","opensInNewTab":false,"href":"/demo/events/deferred"},{"section":"events","slug":"queued","label":"Async","title":"Queued Handler","summary":"Events survive restarts and scale across workers — backed by a durable message queue.","opensInNewTab":false,"href":"/demo/events/queued"},{"section":"events","slug":"sse","label":"Async","title":"SSE Stream","summary":"Real-time server push without WebSockets — connect once and receive real backend events over plain HTTP.","opensInNewTab":false,"href":"/demo/events/sse"}],"groups":[{"key":"event-flow","label":"Event Flow","featureCount":5,"features":[{"section":"events","slug":"arena","label":"Async","title":"Execution Arena","summary":"Launch the same backend intent in sync, Swoole async, and queued modes, then watch the proof arrive over SSE.","opensInNewTab":false,"href":"/demo/events/arena"},{"section":"events","slug":"sync","label":"Async","title":"Sync Events","summary":"Dispatch an event and all sync listeners run before the response is sent.","opensInNewTab":false,"href":"/demo/events/sync"},{"section":"events","slug":"deferred","label":"Async","title":"Deferred Handler","summary":"Heavy work runs after the response is sent — the user gets instant feedback.","opensInNewTab":false,"href":"/demo/events/deferred"},{"section":"events","slug":"queued","label":"Async","title":"Queued Handler","summary":"Events survive restarts and scale across workers — backed by a durable message queue.","opensInNewTab":false,"href":"/demo/events/queued"},{"section":"events","slug":"sse","label":"Async","title":"SSE Stream","summary":"Real-time server push without WebSockets — connect once and receive real backend events over plain HTTP.","opensInNewTab":false,"href":"/demo/events/sse"}]}]},{"key":"rendering","label":"UI Rendering & SSR","summary":"One rendering story from handler to HTML: page data, page regions, and live updates stay in the same server-driven model instead of splitting into frontend and backend template logic.","icon":"UI","eyebrow":"Frontend","starter":false,"prerequisites":[],"featureCount":15,"href":"/demo/rendering","features":[{"section":"rendering","slug":"philosophy","label":"UI Rendering & SSR","title":"SSR Philosophy","summary":"Semitexa SSR is one continuous rendering architecture: page, slots, deferred regions, live refresh, and interactive components stay inside one server-owned story.","opensInNewTab":false,"href":"/demo/rendering/philosophy"},{"section":"rendering","slug":"resource-dtos","label":"UI Rendering & SSR","title":"Resource DTOs","summary":"A Resource DTO is the one typed source of presentation data: handlers shape it once, templates consume it everywhere, and no view has to dissect random arrays.","opensInNewTab":false,"href":"/demo/rendering/resource-dtos"},{"section":"rendering","slug":"slots","label":"UI Rendering & SSR","title":"Slot Resources","summary":"Each page region is its own resource pipeline with the same template system as the main page — no scattered partial glue, no mystery wiring.","opensInNewTab":false,"href":"/demo/rendering/slots"},{"section":"rendering","slug":"components","label":"UI Rendering & SSR","title":"Components","summary":"Reusable, attribute-registered UI components — discovered automatically from the classmap.","opensInNewTab":false,"href":"/demo/rendering/components"},{"section":"rendering","slug":"seo","label":"UI Rendering & SSR","title":"SEO","summary":"Set title, description, and Open Graph tags from your handler — no template hacks needed.","opensInNewTab":false,"href":"/demo/rendering/seo"},{"section":"rendering","slug":"assets","label":"UI Rendering & SSR","title":"Asset Pipeline","summary":"Declare assets with glob patterns in assets.json — served, versioned, and injected automatically.","opensInNewTab":false,"href":"/demo/rendering/assets"},{"section":"rendering","slug":"component-scripts","label":"UI Rendering & SSR","title":"Component Script Assets","summary":"A Semitexa SSR component can own its optional enhancement asset, so behavior travels with the component instead of leaking into page-level glue.","opensInNewTab":false,"href":"/demo/rendering/component-scripts"},{"section":"rendering","slug":"deferred-scripts","label":"UI Rendering & SSR","title":"Script Injection","summary":"Deferred blocks carry their own JS — injected once when the block arrives, never duplicated.","opensInNewTab":false,"href":"/demo/rendering/deferred-scripts"},{"section":"rendering","slug":"deferred","label":"UI Rendering & SSR","title":"Deferred Blocks","summary":"SSR renders the shell first, then expensive regions stream in as real HTML over SSE — no SPA handoff and no client-side page rebuild.","opensInNewTab":true,"href":"/demo/rendering/deferred"},{"section":"rendering","slug":"deferred-encapsulation","label":"UI Rendering & SSR","title":"Block Isolation","summary":"Two identical blocks on the same page run independently — scoped DOM, scoped JS, no conflicts.","opensInNewTab":false,"href":"/demo/rendering/deferred-encapsulation"},{"section":"rendering","slug":"deferred-live","label":"UI Rendering & SSR","title":"Live Widgets","summary":"A live slot can refresh itself on a timer while the page stays SSR-first — no SPA runtime and no handwritten polling layer.","opensInNewTab":false,"href":"/demo/rendering/deferred-live"},{"section":"rendering","slug":"reactive-report","label":"UI Rendering & SSR","title":"Reactive Report","summary":"Background work updates an SSR-first slot in place, so the UI feels live without falling back to SPA state orchestration.","opensInNewTab":false,"href":"/demo/rendering/reactive-report"},{"section":"rendering","slug":"reactive-import","label":"UI Rendering & SSR","title":"Reactive Import","summary":"Background batches keep moving, and the page reflects server progress as live HTML instead of a client-managed progress app.","opensInNewTab":false,"href":"/demo/rendering/reactive-import"},{"section":"rendering","slug":"reactive-analytics","label":"UI Rendering & SSR","title":"Reactive Analytics","summary":"Independent analytics jobs can light up one dashboard progressively, while the page stays server-rendered from the first byte.","opensInNewTab":false,"href":"/demo/rendering/reactive-analytics"},{"section":"rendering","slug":"reactive-ai","label":"UI Rendering & SSR","title":"Reactive AI Task","summary":"Submit a task and watch the AI pipeline stages reveal one by one as the cron job processes it.","opensInNewTab":false,"href":"/demo/rendering/reactive-ai"}],"groups":[{"key":"rendering-model","label":"SSR Foundation","featureCount":8,"features":[{"section":"rendering","slug":"philosophy","label":"UI Rendering & SSR","title":"SSR Philosophy","summary":"Semitexa SSR is one continuous rendering architecture: page, slots, deferred regions, live refresh, and interactive components stay inside one server-owned story.","opensInNewTab":false,"href":"/demo/rendering/philosophy"},{"section":"rendering","slug":"resource-dtos","label":"UI Rendering & SSR","title":"Resource DTOs","summary":"A Resource DTO is the one typed source of presentation data: handlers shape it once, templates consume it everywhere, and no view has to dissect random arrays.","opensInNewTab":false,"href":"/demo/rendering/resource-dtos"},{"section":"rendering","slug":"slots","label":"UI Rendering & SSR","title":"Slot Resources","summary":"Each page region is its own resource pipeline with the same template system as the main page — no scattered partial glue, no mystery wiring.","opensInNewTab":false,"href":"/demo/rendering/slots"},{"section":"rendering","slug":"components","label":"UI Rendering & SSR","title":"Components","summary":"Reusable, attribute-registered UI components — discovered automatically from the classmap.","opensInNewTab":false,"href":"/demo/rendering/components"},{"section":"rendering","slug":"seo","label":"UI Rendering & SSR","title":"SEO","summary":"Set title, description, and Open Graph tags from your handler — no template hacks needed.","opensInNewTab":false,"href":"/demo/rendering/seo"},{"section":"rendering","slug":"assets","label":"UI Rendering & SSR","title":"Asset Pipeline","summary":"Declare assets with glob patterns in assets.json — served, versioned, and injected automatically.","opensInNewTab":false,"href":"/demo/rendering/assets"},{"section":"rendering","slug":"component-scripts","label":"UI Rendering & SSR","title":"Component Script Assets","summary":"A Semitexa SSR component can own its optional enhancement asset, so behavior travels with the component instead of leaking into page-level glue.","opensInNewTab":false,"href":"/demo/rendering/component-scripts"},{"section":"rendering","slug":"deferred-scripts","label":"UI Rendering & SSR","title":"Script Injection","summary":"Deferred blocks carry their own JS — injected once when the block arrives, never duplicated.","opensInNewTab":false,"href":"/demo/rendering/deferred-scripts"}]},{"key":"deferred","label":"Deferred Delivery","featureCount":2,"features":[{"section":"rendering","slug":"deferred","label":"UI Rendering & SSR","title":"Deferred Blocks","summary":"SSR renders the shell first, then expensive regions stream in as real HTML over SSE — no SPA handoff and no client-side page rebuild.","opensInNewTab":true,"href":"/demo/rendering/deferred"},{"section":"rendering","slug":"deferred-encapsulation","label":"UI Rendering & SSR","title":"Block Isolation","summary":"Two identical blocks on the same page run independently — scoped DOM, scoped JS, no conflicts.","opensInNewTab":false,"href":"/demo/rendering/deferred-encapsulation"}]},{"key":"live","label":"Reactive UI","featureCount":5,"features":[{"section":"rendering","slug":"deferred-live","label":"UI Rendering & SSR","title":"Live Widgets","summary":"A live slot can refresh itself on a timer while the page stays SSR-first — no SPA runtime and no handwritten polling layer.","opensInNewTab":false,"href":"/demo/rendering/deferred-live"},{"section":"rendering","slug":"reactive-report","label":"UI Rendering & SSR","title":"Reactive Report","summary":"Background work updates an SSR-first slot in place, so the UI feels live without falling back to SPA state orchestration.","opensInNewTab":false,"href":"/demo/rendering/reactive-report"},{"section":"rendering","slug":"reactive-import","label":"UI Rendering & SSR","title":"Reactive Import","summary":"Background batches keep moving, and the page reflects server progress as live HTML instead of a client-managed progress app.","opensInNewTab":false,"href":"/demo/rendering/reactive-import"},{"section":"rendering","slug":"reactive-analytics","label":"UI Rendering & SSR","title":"Reactive Analytics","summary":"Independent analytics jobs can light up one dashboard progressively, while the page stays server-rendered from the first byte.","opensInNewTab":false,"href":"/demo/rendering/reactive-analytics"},{"section":"rendering","slug":"reactive-ai","label":"UI Rendering & SSR","title":"Reactive AI Task","summary":"Submit a task and watch the AI pipeline stages reveal one by one as the cron job processes it.","opensInNewTab":false,"href":"/demo/rendering/reactive-ai"}]}]},{"key":"platform","label":"Tenancy","summary":"Multi-tenant resolution, tenant-aware configuration, and strict isolation of data and background work.","icon":"TN","eyebrow":"Multi-Tenant","starter":false,"prerequisites":["data","rendering"],"featureCount":5,"href":"/demo/platform","features":[{"section":"platform","slug":"tenancy-resolution","label":"Tenancy","title":"Tenant Context Resolution","summary":"See how Semitexa resolves the active tenant from subdomain, header, path, or query input before the rest of the platform runs.","opensInNewTab":false,"href":"/demo/platform/tenancy-resolution"},{"section":"platform","slug":"tenancy-config","label":"Tenancy","title":"Per-Tenant Configuration","summary":"Three demo tenants with distinct branding -- switch tenant, everything changes without if/else.","opensInNewTab":false,"href":"/demo/platform/tenancy-config"},{"section":"platform","slug":"tenancy-layers","label":"Tenancy","title":"Multi-Layer Tenancy","summary":"Organization, Locale, Theme, Environment -- four independent layers compose into one TenantContext.","opensInNewTab":false,"href":"/demo/platform/tenancy-layers"},{"section":"platform","slug":"tenancy-isolation","label":"Tenancy","title":"Data Isolation","summary":"Product listing scoped by tenant -- switch tenant, list changes. Zero manual WHERE clauses.","opensInNewTab":false,"href":"/demo/platform/tenancy-isolation"},{"section":"platform","slug":"tenancy-queue","label":"Tenancy","title":"Queue Tenant Propagation","summary":"Tenant context travels with queued jobs -- _tenant key injected automatically, restored by worker.","opensInNewTab":false,"href":"/demo/platform/tenancy-queue"}],"groups":[{"key":"resolution","label":"Tenant Resolution","featureCount":1,"features":[{"section":"platform","slug":"tenancy-resolution","label":"Tenancy","title":"Tenant Context Resolution","summary":"See how Semitexa resolves the active tenant from subdomain, header, path, or query input before the rest of the platform runs.","opensInNewTab":false,"href":"/demo/platform/tenancy-resolution"}]},{"key":"configuration","label":"Tenant Configuration","featureCount":2,"features":[{"section":"platform","slug":"tenancy-config","label":"Tenancy","title":"Per-Tenant Configuration","summary":"Three demo tenants with distinct branding -- switch tenant, everything changes without if/else.","opensInNewTab":false,"href":"/demo/platform/tenancy-config"},{"section":"platform","slug":"tenancy-layers","label":"Tenancy","title":"Multi-Layer Tenancy","summary":"Organization, Locale, Theme, Environment -- four independent layers compose into one TenantContext.","opensInNewTab":false,"href":"/demo/platform/tenancy-layers"}]},{"key":"isolation","label":"Isolation & Work","featureCount":2,"features":[{"section":"platform","slug":"tenancy-isolation","label":"Tenancy","title":"Data Isolation","summary":"Product listing scoped by tenant -- switch tenant, list changes. Zero manual WHERE clauses.","opensInNewTab":false,"href":"/demo/platform/tenancy-isolation"},{"section":"platform","slug":"tenancy-queue","label":"Tenancy","title":"Queue Tenant Propagation","summary":"Tenant context travels with queued jobs -- _tenant key injected automatically, restored by worker.","opensInNewTab":false,"href":"/demo/platform/tenancy-queue"}]}]},{"key":"api","label":"API","summary":"External API endpoints, machine auth, versioning, and consumer-facing schema behavior.","icon":"API","eyebrow":"Machine","starter":false,"prerequisites":["routing","auth"],"featureCount":7,"href":"/demo/api","features":[{"section":"api","slug":"rest-api","label":"API","title":"REST API","summary":"Classic Semitexa REST endpoints with typed payloads, versioning, and consumer-friendly response shaping.","opensInNewTab":false,"href":"/demo/api/rest-api"},{"section":"api","slug":"structured-errors","label":"API","title":"Structured Errors","summary":"Throw domain exceptions and let semitexa-api map them into stable machine-readable error envelopes.","opensInNewTab":false,"href":"/demo/api/structured-errors"},{"section":"api","slug":"active-version","label":"API","title":"Active Version","summary":"The current collection endpoint with a clean X-Api-Version header and no deprecation noise.","opensInNewTab":false,"href":"/demo/api/active-version"},{"section":"api","slug":"sunset-version","label":"API","title":"Sunset Version","summary":"A deprecated product endpoint that emits both Deprecation and Sunset headers.","opensInNewTab":false,"href":"/demo/api/sunset-version"},{"section":"api","slug":"schema-discovery","label":"API","title":"Schema Discovery","summary":"A mini Swagger-style explorer for the live product API contract, schema endpoint, and response shapes.","opensInNewTab":false,"href":"/demo/api/schema-discovery"},{"section":"api","slug":"graphql","label":"API","title":"GraphQL API","summary":"GraphQL-first Semitexa contracts built with typed payloads and typed output DTOs instead of resolver sprawl.","opensInNewTab":false,"href":"/demo/api/graphql"},{"section":"api","slug":"rest-graphql","label":"API","title":"REST + GraphQL","summary":"One Semitexa use case can serve both REST and GraphQL without duplicating handler logic into separate resolver classes.","opensInNewTab":false,"href":"/demo/api/rest-graphql"}],"groups":[{"key":"public-api","label":"REST Surface","featureCount":4,"features":[{"section":"api","slug":"rest-api","label":"API","title":"REST API","summary":"Classic Semitexa REST endpoints with typed payloads, versioning, and consumer-friendly response shaping.","opensInNewTab":false,"href":"/demo/api/rest-api"},{"section":"api","slug":"structured-errors","label":"API","title":"Structured Errors","summary":"Throw domain exceptions and let semitexa-api map them into stable machine-readable error envelopes.","opensInNewTab":false,"href":"/demo/api/structured-errors"},{"section":"api","slug":"active-version","label":"API","title":"Active Version","summary":"The current collection endpoint with a clean X-Api-Version header and no deprecation noise.","opensInNewTab":false,"href":"/demo/api/active-version"},{"section":"api","slug":"sunset-version","label":"API","title":"Sunset Version","summary":"A deprecated product endpoint that emits both Deprecation and Sunset headers.","opensInNewTab":false,"href":"/demo/api/sunset-version"}]},{"key":"schema","label":"Schema Discovery","featureCount":3,"features":[{"section":"api","slug":"schema-discovery","label":"API","title":"Schema Discovery","summary":"A mini Swagger-style explorer for the live product API contract, schema endpoint, and response shapes.","opensInNewTab":false,"href":"/demo/api/schema-discovery"},{"section":"api","slug":"graphql","label":"API","title":"GraphQL API","summary":"GraphQL-first Semitexa contracts built with typed payloads and typed output DTOs instead of resolver sprawl.","opensInNewTab":false,"href":"/demo/api/graphql"},{"section":"api","slug":"rest-graphql","label":"API","title":"REST + GraphQL","summary":"One Semitexa use case can serve both REST and GraphQL without duplicating handler logic into separate resolver classes.","opensInNewTab":false,"href":"/demo/api/rest-graphql"}]}]},{"key":"cli","label":"CLI","summary":"Operational, introspection, and AI-oriented command surfaces that explain and drive the framework from the terminal.","icon":"CLI","eyebrow":"Operations","starter":false,"prerequisites":["routing"],"featureCount":6,"href":"/demo/cli","features":[{"section":"cli","slug":"describe-commands","label":"CLI","title":"Project Graph Introspection","summary":"Routes, modules, contracts, and handlers can be introspected directly from the CLI instead of reverse-engineering the framework graph by hand.","opensInNewTab":false,"href":"/demo/cli/describe-commands"},{"section":"cli","slug":"runtime-maintenance","label":"CLI","title":"Runtime Maintenance","summary":"Reload workers, clear stale cache, sync registries, lint architecture rules, and probe handler wiring without reaching for ad-hoc shell scripts.","opensInNewTab":false,"href":"/demo/cli/runtime-maintenance"},{"section":"cli","slug":"scaffolding-generators","label":"CLI","title":"Scaffolding Generators","summary":"Scaffold modules, pages, payloads, services, and contracts through commands that already understand Semitexa structure and AI-friendly output modes.","opensInNewTab":false,"href":"/demo/cli/scaffolding-generators"},{"section":"cli","slug":"workers-scheduling","label":"CLI","title":"Workers & Scheduling","summary":"Run queues, scheduler pools, mail delivery, webhooks, and tenant-scoped commands from a coherent operator surface instead of bespoke daemons.","opensInNewTab":false,"href":"/demo/cli/workers-scheduling"},{"section":"cli","slug":"ai-tooling","label":"CLI","title":"AI Tooling Surface","summary":"Semitexa exposes AI-facing commands as explicit CLI contracts: capabilities, skills, log access, and a local assistant entrypoint.","opensInNewTab":false,"href":"/demo/cli/ai-tooling"},{"section":"cli","slug":"orm-console","label":"CLI","title":"ORM Console Toolkit","summary":"The ORM ships with a practical CLI surface: status, diff, sync, and seed commands with dry-run safety and SQL plan export.","opensInNewTab":false,"href":"/demo/cli/orm-console"}],"groups":[{"key":"inspection","label":"Describe & Inspect","featureCount":2,"features":[{"section":"cli","slug":"describe-commands","label":"CLI","title":"Project Graph Introspection","summary":"Routes, modules, contracts, and handlers can be introspected directly from the CLI instead of reverse-engineering the framework graph by hand.","opensInNewTab":false,"href":"/demo/cli/describe-commands"},{"section":"cli","slug":"runtime-maintenance","label":"CLI","title":"Runtime Maintenance","summary":"Reload workers, clear stale cache, sync registries, lint architecture rules, and probe handler wiring without reaching for ad-hoc shell scripts.","opensInNewTab":false,"href":"/demo/cli/runtime-maintenance"}]},{"key":"automation","label":"Automation","featureCount":4,"features":[{"section":"cli","slug":"scaffolding-generators","label":"CLI","title":"Scaffolding Generators","summary":"Scaffold modules, pages, payloads, services, and contracts through commands that already understand Semitexa structure and AI-friendly output modes.","opensInNewTab":false,"href":"/demo/cli/scaffolding-generators"},{"section":"cli","slug":"workers-scheduling","label":"CLI","title":"Workers & Scheduling","summary":"Run queues, scheduler pools, mail delivery, webhooks, and tenant-scoped commands from a coherent operator surface instead of bespoke daemons.","opensInNewTab":false,"href":"/demo/cli/workers-scheduling"},{"section":"cli","slug":"ai-tooling","label":"CLI","title":"AI Tooling Surface","summary":"Semitexa exposes AI-facing commands as explicit CLI contracts: capabilities, skills, log access, and a local assistant entrypoint.","opensInNewTab":false,"href":"/demo/cli/ai-tooling"},{"section":"cli","slug":"orm-console","label":"CLI","title":"ORM Console Toolkit","summary":"The ORM ships with a practical CLI surface: status, diff, sync, and seed commands with dry-run safety and SQL plan export.","opensInNewTab":false,"href":"/demo/cli/orm-console"}]}]},{"key":"project-graph","label":"Project Graph","summary":"The `semitexa-project-graph` package: stored structural graph, intelligence layer, impact analysis, and task-scoped context for serious repository work.","icon":"PG","eyebrow":"AI Accelerator","starter":true,"prerequisites":["cli"],"featureCount":3,"href":"/demo/project-graph","features":[{"section":"project-graph","slug":"overview","label":"Project Graph","title":"Project Graph Overview","summary":"Understand what `semitexa-project-graph` adds: a stored structural map, an intelligence layer, and task-scoped context for large-codebase work.","opensInNewTab":false,"href":"/demo/project-graph/overview"},{"section":"project-graph","slug":"inspection","label":"Project Graph","title":"Inspecting the Graph","summary":"Use Project Graph queries and intelligence views to inspect modules, dependencies, flows, events, and hotspots without reconstructing the repository manually.","opensInNewTab":false,"href":"/demo/project-graph/inspection"},{"section":"project-graph","slug":"impact","label":"Project Graph","title":"Impact, Context, and Watch Mode","summary":"Use impact analysis, context packing, and watch mode to scope risky changes and keep graph-backed answers current during long work sessions.","opensInNewTab":false,"href":"/demo/project-graph/impact"}],"groups":[{"key":"launch","label":"Start Here","featureCount":1,"features":[{"section":"project-graph","slug":"overview","label":"Project Graph","title":"Project Graph Overview","summary":"Understand what `semitexa-project-graph` adds: a stored structural map, an intelligence layer, and task-scoped context for large-codebase work.","opensInNewTab":false,"href":"/demo/project-graph/overview"}]},{"key":"exploration","label":"Explore & Inspect","featureCount":1,"features":[{"section":"project-graph","slug":"inspection","label":"Project Graph","title":"Inspecting the Graph","summary":"Use Project Graph queries and intelligence views to inspect modules, dependencies, flows, events, and hotspots without reconstructing the repository manually.","opensInNewTab":false,"href":"/demo/project-graph/inspection"}]},{"key":"change-safety","label":"Impact & Context","featureCount":1,"features":[{"section":"project-graph","slug":"impact","label":"Project Graph","title":"Impact, Context, and Watch Mode","summary":"Use impact analysis, context packing, and watch mode to scope risky changes and keep graph-backed answers current during long work sessions.","opensInNewTab":false,"href":"/demo/project-graph/impact"}]}]},{"key":"llm","label":"LLM Module","sidebarLabel":"LLM","summary":"The dedicated `semitexa/llm` module: AI assistant entrypoint, skill discovery, planner, executor, provider backends, and skill authoring rules.","icon":"AI","eyebrow":"semitexa/llm","starter":false,"prerequisites":["cli"],"featureCount":4,"href":"/demo/llm","features":[{"section":"llm","slug":"overview","label":"LLM Module","title":"LLM Module Overview","summary":"What `semitexa/llm` adds to the framework and how your project can expose its own CLI skills to the assistant.","opensInNewTab":false,"href":"/demo/llm/overview"},{"section":"llm","slug":"providers","label":"LLM Module","title":"Providers & Backends","summary":"Provider contracts, backend resolution, local vs remote Ollama, and the environment knobs that shape LLM runtime behavior.","opensInNewTab":false,"href":"/demo/llm/providers"},{"section":"llm","slug":"skills","label":"LLM Module","title":"Adding Skills","summary":"How a console command becomes AI-executable through `#[AsAiSkill]`, metadata policy, and registry discovery.","opensInNewTab":false,"href":"/demo/llm/skills"},{"section":"llm","slug":"execution-flow","label":"LLM Module","title":"Execution Flow","summary":"How a user request becomes a planner decision, a reviewed skill proposal, and finally a real console execution.","opensInNewTab":false,"href":"/demo/llm/execution-flow"}],"groups":[{"key":"assistant-basics","label":"Assistant Surface","featureCount":2,"features":[{"section":"llm","slug":"overview","label":"LLM Module","title":"LLM Module Overview","summary":"What `semitexa/llm` adds to the framework and how your project can expose its own CLI skills to the assistant.","opensInNewTab":false,"href":"/demo/llm/overview"},{"section":"llm","slug":"providers","label":"LLM Module","title":"Providers & Backends","summary":"Provider contracts, backend resolution, local vs remote Ollama, and the environment knobs that shape LLM runtime behavior.","opensInNewTab":false,"href":"/demo/llm/providers"}]},{"key":"skill-system","label":"Skill System","featureCount":2,"features":[{"section":"llm","slug":"skills","label":"LLM Module","title":"Adding Skills","summary":"How a console command becomes AI-executable through `#[AsAiSkill]`, metadata policy, and registry discovery.","opensInNewTab":false,"href":"/demo/llm/skills"},{"section":"llm","slug":"execution-flow","label":"LLM Module","title":"Execution Flow","summary":"How a user request becomes a planner decision, a reviewed skill proposal, and finally a real console execution.","opensInNewTab":false,"href":"/demo/llm/execution-flow"}]}]},{"key":"testing","label":"Testing","summary":"Contract-level verification patterns for payloads and other framework boundaries.","icon":"QA","eyebrow":"Verification","starter":false,"prerequisites":["routing"],"featureCount":1,"href":"/demo/testing","features":[{"section":"testing","slug":"payload-contracts","label":"Testing","title":"Payload Contract Testing","summary":"Run one project-level contract suite through the canonical test runner and let strategy profiles verify payload boundaries without hand-writing repetitive negative cases.","opensInNewTab":false,"href":"/demo/testing/payload-contracts"}],"groups":[{"key":"contracts","label":"Contracts","featureCount":1,"features":[{"section":"testing","slug":"payload-contracts","label":"Testing","title":"Payload Contract Testing","summary":"Run one project-level contract suite through the canonical test runner and let strategy profiles verify payload boundaries without hand-writing repetitive negative cases.","opensInNewTab":false,"href":"/demo/testing/payload-contracts"}]}]}]}],"currentSection":"rendering","currentSlug":"philosophy","infoWhat":"Semitexa SSR is not a thin “server pre-render” layer. It is a rendering architecture where the page contract, page regions, deferred delivery, live refresh, and component interaction all stay inside one coherent server-owned model.","infoHow":"Resource DTOs define the page boundary before Twig renders a single field, slot resources give regions their own response pipeline, deferred blocks stream later HTML instead of triggering client takeover, reactive slots keep re-rendering server truth, and interactive components stay scoped through tiny component-owned JavaScript instead of a page-level UI framework dependency.","infoWhy":"Most stacks keep the phrase SSR but abandon the idea the moment the page becomes dynamic. Templates start reshaping data, partials start guessing context, and eventually view files begin pulling from storage or external APIs directly. Semitexa treats that drift as a framework problem, not a code review suggestion. It is opinionated because it is trying to preserve one rendering story, one presentation boundary, and one source of truth even when the page becomes late, live, or interactive.","infoKeywords":[{"term":"one rendering story","definition":"The same conceptual model survives first paint, deferred delivery, live refresh, and component interaction."},{"term":"server-owned truth","definition":"The browser displays HTML, but the authoritative rendering contract and state interpretation stay on the server side."},{"term":"presentation boundary","definition":"Templates consume already-shaped response data instead of fetching, reshaping, or interpreting domain data on their own."},{"term":"late HTML","definition":"Deferred content arrives after the shell, but it still arrives as server-rendered HTML rather than a client-side redraw."},{"term":"reactive SSR","definition":"A live region can keep refreshing from server truth while remaining part of the SSR page model."},{"term":"interactive SSR component","definition":"A server-rendered component can declare backend event contracts without turning into a mini SPA island."},{"term":"framework-free enhancement","definition":"Client behavior may exist, but it remains small, scoped, and component-owned instead of becoming a second UI framework layer."}],"navMode":"catalog","activeLayerKey":"full-catalog","authUi":{"isAuthenticated":false,"label":"Google user","shortLabel":"Google","email":null,"startUrl":"/demo/auth/google/start?return_to=%2Fdemo","authPageUrl":"/demo/auth/google?return_to=%2Fdemo","accountUrl":"/demo/auth/google?return_to=%2Fdemo","logoutUrl":"/demo/auth/google/logout?return_to=%2Fdemo","actionLabel":"Sign in with Google","signInTitle":"Sign in with Google to unlock advanced demos","signedInLabel":"Authorized as"},"explanation":{"what":"Semitexa SSR is not a thin “server pre-render” layer. It is a rendering architecture where the page contract, page regions, deferred delivery, live refresh, and component interaction all stay inside one coherent server-owned model.","how":"Resource DTOs define the page boundary before Twig renders a single field, slot resources give regions their own response pipeline, deferred blocks stream later HTML instead of triggering client takeover, reactive slots keep re-rendering server truth, and interactive components stay scoped through tiny component-owned JavaScript instead of a page-level UI framework dependency.","why":"Most stacks keep the phrase SSR but abandon the idea the moment the page becomes dynamic. Templates start reshaping data, partials start guessing context, and eventually view files begin pulling from storage or external APIs directly. Semitexa treats that drift as a framework problem, not a code review suggestion. It is opinionated because it is trying to preserve one rendering story, one presentation boundary, and one source of truth even when the page becomes late, live, or interactive.","keywords":[{"term":"one rendering story","definition":"The same conceptual model survives first paint, deferred delivery, live refresh, and component interaction."},{"term":"server-owned truth","definition":"The browser displays HTML, but the authoritative rendering contract and state interpretation stay on the server side."},{"term":"presentation boundary","definition":"Templates consume already-shaped response data instead of fetching, reshaping, or interpreting domain data on their own."},{"term":"late HTML","definition":"Deferred content arrives after the shell, but it still arrives as server-rendered HTML rather than a client-side redraw."},{"term":"reactive SSR","definition":"A live region can keep refreshing from server truth while remaining part of the SSR page model."},{"term":"interactive SSR component","definition":"A server-rendered component can declare backend event contracts without turning into a mini SPA island."},{"term":"framework-free enhancement","definition":"Client behavior may exist, but it remains small, scoped, and component-owned instead of becoming a second UI framework layer."}]},"sourceCode":{"Page Resource":"<?php\n\ndeclare(strict_types=1);\n\nuse App\\Domain\\Catalog\\CatalogInterface;\nuse App\\Domain\\Product;\nuse Semitexa\\Core\\Attribute\\AsPublicPayload;\nuse Semitexa\\Core\\Attribute\\AsPayloadHandler;\nuse Semitexa\\Core\\Attribute\\InjectAsReadonly;\nuse Semitexa\\Core\\Attribute\\AsResource;\nuse Semitexa\\Core\\Contract\\TypedHandlerInterface;\nuse Semitexa\\Core\\Exception\\NotFoundException;\nuse Semitexa\\Core\\Exception\\ValidationException;\nuse Semitexa\\Ssr\\Application\\Service\\Http\\Response\\HtmlResponse;\n\n#[AsPublicPayload(\n    path: '/products/{slug}',\n    methods: ['GET'],\n    responseWith: ProductPageResource::class,\n    requirements: ['slug' => '[a-z0-9-]+'],\n)]\nfinal class ProductPagePayload\n{\n    protected string $slug = '';\n\n    public function getSlug(): string\n    {\n        return $this->slug;\n    }\n\n    public function setSlug(string $slug): void\n    {\n        $slug = strtolower(trim($slug));\n\n        if ($slug === '') {\n            throw new ValidationException(['slug' => ['Product slug is required.']]);\n        }\n\n        if (preg_match('/^[a-z0-9-]+$/', $slug) !== 1) {\n            throw new ValidationException(['slug' => ['Product slug may only contain lowercase letters, numbers, and dashes.']]);\n        }\n\n        $this->slug = $slug;\n    }\n}\n\n#[AsPayloadHandler(payload: ProductPagePayload::class, resource: ProductPageResource::class)]\nfinal class ProductPageHandler implements TypedHandlerInterface\n{\n    #[InjectAsReadonly]\n    private CatalogInterface $catalog;\n\n    public function handle(ProductPagePayload $payload, ProductPageResource $resource): ProductPageResource\n    {\n        $product = $this->catalog->getBySlug($payload->getSlug());\n        if ($product === null) {\n            throw new NotFoundException('Product', $payload->getSlug());\n        }\n\n        return $resource\n            ->withProduct($product)\n            ->withHeroActions(['buy', 'bookmark'])\n            ->withInventoryState($product->inventoryState());\n    }\n}\n\n#[AsResource(handle: 'product_page', template: '@shop/pages/product.html.twig')]\nfinal class ProductPageResource extends HtmlResponse\n{\n    public function withProduct(Product $product): self\n    {\n        return $this->with('product', $product);\n    }\n\n    public function withInventoryState(string $state): self\n    {\n        return $this->with('inventoryState', $state);\n    }\n\n    public function withHeroActions(array $actions): self\n    {\n        return $this->with('heroActions', $actions);\n    }\n}\n","Slot Resource":"<?php\n\ndeclare(strict_types=1);\n\nuse Examples\\Rendering\\Philosophy\\Support\\RecommendationService;\nuse Semitexa\\Core\\Attribute\\InjectAsReadonly;\nuse Semitexa\\Ssr\\Attribute\\AsSlotHandler;\nuse Semitexa\\Ssr\\Attribute\\AsSlotResource;\nuse Semitexa\\Ssr\\Application\\Service\\Http\\Response\\HtmlSlotResponse;\n\n#[AsSlotResource(handle: 'product_page', slot: 'sidebar')]\nfinal class ProductSidebarSlot extends HtmlSlotResponse\n{\n    public function withRecommendations(array $products): self\n    {\n        return $this->with('recommendations', $products);\n    }\n}\n\n#[AsSlotHandler(slot: ProductSidebarSlot::class)]\nfinal class ProductSidebarSlotHandler\n{\n    #[InjectAsReadonly]\n    protected RecommendationService $recommendations;\n\n    public function handle(ProductSidebarSlot $slot): ProductSidebarSlot\n    {\n        return $slot->withRecommendations(\n            $this->recommendations->topForCurrentUser(),\n        );\n    }\n}\n\n/*\nlayout.twig\n\n<aside class=\"page-sidebar\">\n  {{ layout_slot('sidebar') }}\n</aside>\n*/\n","Deferred Slot":"<?php\n\ndeclare(strict_types=1);\n\nuse Examples\\Rendering\\Philosophy\\Support\\AnalyticsService;\nuse Semitexa\\Core\\Attribute\\InjectAsReadonly;\nuse Semitexa\\Ssr\\Attribute\\AsSlotHandler;\nuse Semitexa\\Ssr\\Attribute\\AsSlotResource;\nuse Semitexa\\Ssr\\Application\\Service\\Http\\Response\\HtmlSlotResponse;\n\n#[AsSlotResource(\n    handle: 'product_page',\n    slot: 'analytics_panel',\n    deferred: true,\n    skeletonTemplate: '@shop/skeletons/analytics-panel.html.twig',\n)]\nfinal class ProductAnalyticsSlot extends HtmlSlotResponse\n{\n    public function withMetrics(array $metrics): self\n    {\n        return $this->with('metrics', $metrics);\n    }\n}\n\n#[AsSlotHandler(slot: ProductAnalyticsSlot::class)]\nfinal class ProductAnalyticsSlotHandler\n{\n    #[InjectAsReadonly]\n    protected AnalyticsService $analytics;\n\n    public function handle(ProductAnalyticsSlot $slot): ProductAnalyticsSlot\n    {\n        return $slot->withMetrics(\n            $this->analytics->buildProductSnapshot(),\n        );\n    }\n}\n\n// The shell renders immediately. The slow region arrives later as HTML over SSE.\n","Reactive Slot":"<?php\n\ndeclare(strict_types=1);\n\nuse Examples\\Rendering\\Philosophy\\Support\\JobService;\nuse Semitexa\\Core\\Attribute\\InjectAsReadonly;\nuse Semitexa\\Ssr\\Attribute\\AsSlotHandler;\nuse Semitexa\\Ssr\\Attribute\\AsSlotResource;\nuse Semitexa\\Ssr\\Application\\Service\\Http\\Response\\HtmlSlotResponse;\n\n#[AsSlotResource(\n    handle: 'imports_dashboard',\n    slot: 'job_status',\n    deferred: true,\n    refreshInterval: 3,\n)]\nfinal class ImportJobStatusSlot extends HtmlSlotResponse\n{\n    public function withStatus(string $status): self\n    {\n        return $this->with('status', $status);\n    }\n\n    public function withProgress(int $progress): self\n    {\n        return $this->with('progress', $progress);\n    }\n}\n\n#[AsSlotHandler(slot: ImportJobStatusSlot::class)]\nfinal class ImportJobStatusSlotHandler\n{\n    #[InjectAsReadonly]\n    protected JobService $jobs;\n\n    public function handle(ImportJobStatusSlot $slot): ImportJobStatusSlot\n    {\n        $run = $this->jobs->latestImportRun();\n\n        return $slot\n            ->withStatus($run->status())\n            ->withProgress($run->progressPercent());\n    }\n}\n\n// The slot keeps re-rendering server truth. No second client-side state machine is required.\n","Interactive Component":"<?php\n\ndeclare(strict_types=1);\n\nuse App\\Events\\DemoDisclosureExpanded;\nuse Semitexa\\Ssr\\Attribute\\AsComponent;\n\n#[AsComponent(\n    name: 'disclosure-prompt',\n    template: '@shop/components/disclosure-prompt.html.twig',\n    event: DemoDisclosureExpanded::class,\n    triggers: ['click'],\n)]\nfinal class DisclosurePromptComponent\n{\n    public function __construct(\n        public readonly string $label,\n        public readonly string $target,\n    ) {}\n}\n\n/*\ndisclosure-prompt.html.twig\n\n<button\n  type=\"button\"\n  data-disclosure-trigger=\"{{ target }}\"\n  {{ component_event_attrs('click', {\n    targetId: target,\n    source: 'product-page',\n  }) }}\n>\n  {{ label }}\n</button>\n*/\n\n// The component still behaves like SSR UI, but click can now dispatch a declared backend event contract.\n"},"resultPreviewTemplate":"@project-layouts-semitexa-demo/components/previews/ssr-manifesto.html.twig","resultPreviewData":{"painPoints":["“SSR” usually means the first paint is server-rendered, but the moment the page becomes dynamic, teams quietly switch to a second frontend architecture.","At the same time, templates start accumulating query logic, ad hoc reshaping, and service calls because nobody protected the presentation boundary structurally.","Page regions become partials with hidden context, live widgets become little apps, and interaction drifts into custom fetch glue.","Soon the page is “SSR” only in name, while React, Alpine, or bespoke client glue becomes the real owner of interaction and state interpretation.","The result works, but the architecture has already split into two competing truths: server render for the shell, client orchestration for everything interesting."],"signals":[{"value":"1","label":"rendering story from first byte to live update"},{"value":"1","label":"presentation boundary before Twig sees data"},{"value":"0","label":"client-side page takeover points"},{"value":"0","label":"required UI framework layers to make the page interactive"},{"value":"0","label":"template-level database or API fetching as an accepted pattern"},{"value":"6","label":"core Semitexa SSR primitives composing one model"}],"compare":[{"variant":"warning","eyebrow":"Typical Split SSR","title":"Server-render the shell, then smuggle in a client framework","summary":"The page starts on the server, but regions, refresh loops, and interactions slowly migrate into React, Alpine, or ad hoc client orchestration.","note":"You keep the phrase SSR, but the browser quietly becomes the second rendering authority."},{"variant":"active","eyebrow":"Semitexa SSR","title":"One rendering architecture, end to end","summary":"Page resource, slot resources, deferred delivery, reactive refresh, component event bridging, and tiny component-owned scripts all remain part of the same server-owned rendering model.","note":"The UI can become late, live, or interactive without making a client framework the hidden second half of the system."}],"pillars":[{"title":"Page Contract","detail":"Resource DTOs make the page response explicit before Twig sees a single field."},{"title":"Presentation Boundary","detail":"Templates consume prepared data instead of querying storage, calling APIs, or inventing new view-side mapping rules."},{"title":"Region Contract","detail":"Slots are real resources with their own pipeline, not fragment glue."},{"title":"Late HTML","detail":"Deferred blocks stream SSR HTML later instead of handing control to a client renderer."},{"title":"Live HTML","detail":"Reactive slots refresh from server truth without inventing a second state machine."},{"title":"Interactive HTML","detail":"Components can now dispatch backend events while staying in the SSR component model."},{"title":"Framework-Free JS","detail":"When JavaScript is needed, it stays as small component-owned enhancement rather than a mandatory UI framework layer."}]},"l2ContentTemplate":"@project-layouts-semitexa-demo/components/previews/ssr-manifesto-rules.html.twig","l2ContentData":{"rules":["The page response must be explicit before template rendering begins.","Templates are presentation surfaces, not a place to fetch from databases, hit APIs, or smuggle handler logic into Twig.","A region is a resource with a pipeline, not a partial with lucky context.","Deferred does not mean “replace SSR with client rendering later”. It means late server HTML.","Reactive does not mean “invent a mini SPA for one widget”. It means the server keeps re-rendering truth.","Interactivity does not require escaping into bespoke API glue. Components can declare backend event contracts directly.","JavaScript may enhance the page, but Semitexa refuses to require React, Alpine, Angular, or another client framework as the second rendering layer.","Assets, scripts, and SEO stay inside the same rendering system instead of becoming a parallel deployment concern."],"checks":[{"label":"HtmlResponse","detail":"Page-level response object accumulates the render contract before Twig."},{"label":"Resource DTOs","detail":"Handlers shape presentation data before it reaches the template, which blocks template-side data drift at the architectural boundary."},{"label":"Slot Resources","detail":"Page regions use the same response discipline as the page itself."},{"label":"Deferred Blocks","detail":"Slow regions arrive later as HTML over SSE, not as client-owned redraw logic."},{"label":"Reactive Slots","detail":"Live UI keeps re-rendering server truth instead of mirroring it in a frontend state graph."},{"label":"Component Event Bridge","detail":"Interactive components can trigger backend events without abandoning the SSR component contract."},{"label":"Component Script Assets","detail":"Small component-owned JavaScript is allowed, but only as scoped enhancement rather than as a framework takeover."}]},"l3ContentTemplate":"@project-layouts-semitexa-demo/components/previews/ssr-manifesto-antipatterns.html.twig","l3ContentData":{"mapping":[{"anti":"“SSR for the first paint, client app for everything real.”","answer":"Semitexa keeps deferred and reactive regions inside the same HTML pipeline."},{"anti":"“The template can just query what it needs, call an API, or reshape the data inline.”","answer":"Semitexa treats that as presentation-boundary failure. Handlers and resource DTOs must shape data before Twig sees it."},{"anti":"“This region is just a partial, pass whatever data it seems to need.”","answer":"Semitexa promotes regions to slot resources with an explicit render contract."},{"anti":"“The widget is live, so we need a second state architecture.”","answer":"Semitexa refreshes the slot from server truth and swaps HTML in place."},{"anti":"“This interaction needs fetch glue, custom endpoints, and manual wiring.”","answer":"Semitexa components can now declare backend event contracts and dispatch through one generic bridge."},{"anti":"“Once the page becomes interactive, we obviously need React, Alpine, or another client UI framework.”","answer":"Semitexa rejects that as a default assumption. Small component-owned scripts are enough when the server still owns rendering truth."},{"anti":"“SEO, assets, scripts, templates, and live behavior all belong to different systems.”","answer":"Semitexa treats them as one rendering surface owned by one framework model."}]},"__page_document_html_iri":"/demo/rendering/philosophy","__page_document_json_iri":"/demo/rendering/philosophy?_format=json","__page_alternates":[{"type":"application/json","href":"/demo/rendering/philosophy?_format=json"}]}