Skip to main content

RSC Plugin Platform

Use this guide to scaffold, customize, run, secure, and verify independently compiled React Server Component plugins behind one public HttpNext listener.
API and package boundaries: @hile/rsc.
This is the canonical implementation guide for independently compiled React Server Component plugins behind one public Next.js listener and origin. Pages, assets, Server Functions, and development SSE use different paths on that same listener. It is intentionally domain-free and detailed enough for an AI agent with no repository history to scaffold, customize, run, and verify the topology. Also read RSC packages for package boundaries and API contracts. The supported quick start is scaffold-first: generate the maintained create-hile templates and customize them. The snippets below explain and extend those complete files; they are not a request to reimplement lifecycle plumbing from a blank directory.

Target Topology

The plugin has an internal Micro TCP listener because it is a microservice. It has no public HTTP listener. The Host is the only process that owns public HTTP. Registry presence plus an announcement accepted by the selected trust policy causes automatic installation and activation; there is no static plugin list or manual activation call.

Complete Example

The smallest complete composition has three parts:
This summary omits startup rollback, middleware mounting, provider wrapping, credentials, and shutdown. The generated template files supply those required pieces and the following sections explain their customization points; do not deploy the summary by itself.

AI Implementation Rules

Before writing code, preserve these invariants:
  1. Use HileRscPluginRuntime as the plugin lifecycle composition root.
  2. Use HileRscDiscoveryHost for automatic Host deployment.
  3. Use RscHostRuntime plus decodePluginFlight() inside a dynamic Next route.
  4. Use a module-level 'use server' file with defineRscServerFunction() and call scanned defineActionModel() definitions through its explicit API argument.
  5. Keep exact React/RSC versions identical across Host, plugin, and build config.
  6. Treat buildId and artifact directories as immutable. A changed artifact requires a new build ID or development revision.
  7. Choose discovery trust explicitly: bind each HMAC keyId to a plugin-ID allowlist, or use trusted-internal only when every internal Micro peer is trusted.
  8. Mount plugin assets, Server Functions, and optional development SSE on the same Host listener/origin.
  9. Pass the request abort signal into RscHostRuntime.render().
  10. Do not expose server bundles, artifact paths, namespaces, or internal message addresses to the browser.
  11. Configure bounded render timeouts/window and Registry snapshot concurrency for production.
  12. Keep loading/error renderer functions inside a Host Client Component.
  13. Choose remote or Host Suspense ownership explicitly; keep a Host-owned boundary stable across navigation when the product must retain the previous page until the delegated remote boundaries are ready.
Inside a create-hile template source, _env and _env.prod are generator placeholders. The generated project contains .env and .env.prod; do not create runtime files literally named _env. The fastest supported start is to scaffold twice and select the indicated template in the interactive prompt:
The generated projects already contain the lifecycle composition described below. Rename plugin identity, namespaces, ports, credentials, Host allowlist, and package names together before running them.

1. Install Exact Dependencies

Plugin runtime and compiler:
Host runtime:
The runtime versions above are the repository’s validated compatibility tuple. For @hile/* packages, use the mutually compatible versions already written by the generated templates; when copying commands outside this monorepo, do not combine an older RSC core with newer build/discovery adapters. Do not use ranges for React, React DOM, react-server-dom-webpack, or Next without running the complete compatibility suite. The Host does not directly install react-server-dom-webpack: @hile/rsc-next uses the compatible RSC implementation compiled into the pinned Next version. The plugin compiler/runtime pins the standalone package explicitly. Use these Host scripts from the generated template:
The templates also provide tsconfig.json, tsconfig.runtime.json, and next.config.ts. Keep runtime boot files in the runtime TypeScript build and Next app files in the Next build. Do not move the Hile boot service into the App Router compiler.

2. Configure The Immutable Plugin Build

Create hile-rsc.json:
pluginId is the stable logical plugin identity. It may be one lowercase identifier such as analytics or a lowercase namespaced identifier such as org.example.analytics. The omitted buildId is generated for each immutable build, while the omitted outdir defaults to .hile-rsc; set RSC_BUILD_ID when a deployment system must provide the identity. Explicit buildId and outdir remain supported. Optional styles entries are build-scoped CSS files: use an explicit relative path such as ./src/plugin/theme.css, an absolute path, or a package CSS export such as @example/ui/theme.css. The compiler content-hashes, deduplicates, copies, and integrity-declares them once per immutable build. These raw static inputs must be self-contained because relative url() dependencies and external @import files are not copied or rewritten. routes maps plugin-internal paths to exports from the server entry and may use named single-segment parameters such as /items/[itemId]. Captured values are supplied through RscRouteProps.params; exact routes win over parameterized routes, and ambiguous equal-specificity patterns are rejected during manifest validation. Optional metadata travels in the same immutable manifest; each navigation path must reference a declared static route because a parameter pattern is not a concrete destination. The Host URL prefix, authorization, visibility, localization, and final navigation components remain Host policy and are not configured here. For a shared or generated stylesheet that is not imported by the client graph, add the optional field to the same config:
With the example Host catch-all, this route is opened at /plugins/org.example.rsc-plugin/page. The later /plugins/demo.rsc.capabilities and /details URLs belong to the richer private test suite, whose build config declares those routes; they are not routes from this minimal config. Useful scripts:
The plugin process must use NODE_OPTIONS=--conditions=react-server so React resolves its server exports.

3. Write Server And Client Components

Server entry src/plugin/page.tsx:
The default is already a Server Component. Do not add 'use server' to mark it as one. rsc contains the exact selected { pluginId, buildId }, including development revision suffixes. Pass this identity into interactive boundaries instead of copying the base build ID from config. Client boundary src/plugin/interactive.tsx:
The custom directive graph recognizes the directive prologue, builds browser and SSR graphs with esbuild, externalizes the shared React runtime, emits imported CSS and lazy chunks, and records integrity in plugin.json. Minimal src/plugin/plugin.css for proving style delivery:

4. Add A Model And A Server Function

Create src/models/example/increment.model.ts:
Create src/plugin/actions.ts:
This follows the React/Next module-level Server Function shape: the client imports an async callable and useActionState supplies previous state and form data. defineRscServerFunction() keeps that public signature intact while its callback explicitly receives the request API first. Hile compiles a build-scoped reference instead of using Next’s application compiler. The request still enters the one public Host, is authorized there, acquires the exact build lease, runs in the plugin microservice, then invokes the Model. The Client Component does not manually append buildId to the Server Function arguments. The compiled Server Function reference and RscNextClientRuntime carry the exact plugin/build identity to the Host gateway. Passing rsc into the Client Boundary remains useful for display, cache keys, diagnostics, and any lower-level direct Action request; it must match the active deployment and must never be replaced with the base config build ID. Model rules:
  • RscPluginService.load(modelsDirectory) scans *.model.* through @hile/loader.
  • Only default-exported defineActionModel() definitions are externally callable.
  • defineModel() remains internal.
  • The action ID is the relative path without .model and extension.
  • Model pipelines and services remain supported because execution uses @hile/model.
  • Keep authentication/authorization in the Host policy and application layer; validate action input again in the Server Function or Model.
Supported Hile Server Function syntax is deliberately narrower than Next: use a plugin-owned module-level 'use server' file whose exports are created by defineRscServerFunction(). Ordinary unwrapped async exports, inline closure-capturing directives, re-exports, synchronous exports, mixed client/server directives, and dependency-owned directives fail during compilation.

5. Start The Plugin Microservice

The complete maintained implementation is packages/create-hile/templates/rsc-plugin/src/services/plugin.boot.ts. Its required sequence is:
  1. Resolve the production artifact or current development revision.
  2. Verify the entire artifact against HILE_RSC_RUNTIME.
  3. Create one internal Application namespace.
  4. Construct RscPluginService with the renderer and RscArtifactServerFunctionRuntime.
  5. Call service.load(modelsDirectory).
  6. Optionally bind model and artifact development state.
  7. Construct and start HileRscPluginRuntime.
  8. Register runtime.close() with the Hile shutdown callback.
Essential composition:
Do not duplicate attach/listen/publish/drain/rollback order in every plugin. The class owns that lifecycle. Validate required production values before constructing the runtime. In particular, reject a non-integer port outside 1..65535, an empty namespace, and a missing artifact directory. In HMAC mode, also reject an empty discovery key or secret. Plugin environment:
Every concurrently running plugin instance needs a unique internal namespace and port. Multiple builds may share a pluginId; priority and compatibility select the active candidate. Identity meanings:
  • pluginId: stable logical UI plugin identity and Host route key;
  • buildId: immutable artifact identity selected under that plugin ID;
  • MICRO_NAMESPACE / discovery namespace: routable internal service instance that serves the selected artifact; development configures a stable value, while production normally omits it and derives ${pluginId}.${buildId} so concurrent immutable builds cannot share a Micro route;
  • RSC_INSTANCE_ID: optional unique publisher identity; development configures a stable value for incremental updates, while production normally reuses the derived build-scoped namespace so rolling immutable deployments cannot share a discovery topic;
  • RSC_DISCOVERY_GENERATION: non-negative monotonic publication generation; increase it for newer immutable deployments at equal priority, while runtime updates increment it automatically;
  • hile-rsc-dev --namespace: the internal namespace recorded in development state; it must match the service namespace that will publish that revision.
When RSC_DEVELOPMENT_STATE is set, the plugin boot resolves and verifies the matching development record; otherwise it passes RSC_ARTIFACT_ROOT and optional RSC_BUILD_ID to resolveVerifiedRscPluginArtifact(), which selects and verifies once. Production must not set RSC_DEVELOPMENT_STATE. Use resolveHileRscPluginIdentity() from @hile/rsc-discovery-hile for the production/development identity policy rather than rebuilding namespace and instance rules in each plugin boot.

6. Compose The Single Public Host

The complete maintained implementation is packages/create-hile/templates/rsc-host/src/services/runtime.boot.ts. The Host must create:
  • InMemoryRscArtifactCatalog and InMemoryRscDeploymentCatalog;
  • an internal Host Application and catalog-backed plugin locator;
  • the remote client resolver and asset URLs;
  • HileRscDiscoveryHost with an explicit authorizer;
  • RscServerFunctionGateway with application authentication/authorization;
  • asset, Server Function, and optional development middleware;
  • exactly one HttpNext instance.
Use resolveRscStyleAssets(artifacts, pluginId, buildId, assetUrls) when the Host page must expose plugin CSS before rendering the remote boundary. Emit the returned integrity-declared stylesheet links, or equivalent framework preload metadata, in the HTML head before the decoded plugin tree. Use exactly the same { pluginId, buildId } passed to RscHostRuntime.render(); an unregistered build fails closed so CSS from one immutable revision cannot be paired with Flight from another. For a fully trusted internal Micro mesh, use the matching explicit policy and keep the trust assumption next to the code:
This mode needs no discovery secret, key ID, or plugin allowlist. It does not disable artifact digest verification, generation rollback protection, transfer bounds, or public request authorization. The mode is an exact fail-closed choice: a misspelling or a configuration that also contains keyId/secret is rejected before the plugin registers operations or publishes to Registry. For a live HMAC-to-trusted migration, upgrade every Host reader first; upgraded Hosts continue to accept old signed announcements, but old Hosts cannot read the new unsigned announcement shape. Plugin replicas can roll after the Host fleet is ready. When any internal publisher is outside that trust boundary, HMAC configuration must bind publisher identity to plugin ownership:
Never return a secret without a non-empty, explicit pluginIds allowlist. An arbitrary Registry client can announce a topic; signatures and ownership policy establish trust. Keep RSC_DISCOVERY_REQUIRE_GENERATION=false only during a rolling upgrade with legacy publishers, then switch it to true; otherwise an intermediary can strip both generation fields and downgrade to the still-valid legacy signature. The discovery manager rejects changed announcements at an accepted or lower generation and tombstones identities retired after the missing threshold. Supply a caller-owned generationHighWater map to HileRscDiscoveryHost so this state survives Host reconstruction. The map is exclusively owned by one live Host; close() the old Host successfully before constructing its replacement with that store. Treat Registry topic presence as trusted liveness evidence. Generation signatures reject modified and older deployments, but they cannot distinguish a healthy retained topic from an exact replay of the current signed payload. Protect Registry writes/deletes and its transport; use a separate signed freshness service if the Registry itself is in the adversary model. Set transfer bounds on HileRscDiscoveryHost when application quotas differ from the safe defaults:
Downloaded bytes first enter an isolated OS temporary directory. Verification and deployment staging create the Host-managed immutable copy; temporary download files are removed on success or failure. Retired artifacts are removed according to deployment drain and asset retention lifecycle. The byte limits are per artifact operation, not tenant storage quotas; add disk/quota monitoring at the Host deployment layer. Mount the Host adapters:
The application-supplied Server Function authorizer must authenticate the user, verify same-origin/CSRF policy, and authorize { pluginId, buildId, referenceId }. Do not trust a client-provided namespace or internal address. The default Server Function route is /_hile/rsc/server-functions. The generated development example composes createSameOriginCsrfAuthorizer() and passes request headers through context.requestContext. In a real application, construct the gateway with a policy that first authenticates the request context, then checks user access to the plugin/build/reference, and only then applies same-origin/CSRF verification:
authenticate() and canInvoke() are application ports, not @hile/rsc APIs. Apply equivalent authentication/authorization to the dynamic page GET before rendering a plugin. The example RSC_CSRF_TOKEN is deliberately only a local pairing value: it reaches browser JavaScript and is not a production secret or user/session authorization mechanism. HMAC Host environment (omit the discovery key fields in trusted-internal mode):
HMAC deployments should source discovery secrets from a secret manager. All deployments need real public authentication and normally use a less frequent discovery poll. The example token is not production security.

7. Render Through A Dynamic Next Route

Create src/app/plugins/[pluginId]/[[...path]]/page.tsx:
force-dynamic prevents a build-time snapshot of a runtime deployment. The active build is resolved first and the same exact ID is sent to the plugin. The lease remains valid until Flight decode finishes or is aborted. Never request a base config ID after development has activated a revision-suffixed ID. The total timeout bounds the complete internal Flight stream, the idle timeout resets after every valid chunk, and window bounds chunks in transit (1 through 64). The Host should reuse one verificationCache across requests and attach an observe callback for render outcome, duration, and byte metrics; observer failures do not affect rendering. For product loading and failure UI, wrap RscNextClientRuntime and RscClientRuntimeProvider in a Host-owned file with 'use client', then pass renderLoading and renderError(error, identity, retry) there. Do not define these function props in this Server Component: functions may not cross the RSC serialization boundary. The default suspensePolicy="remote" preserves this per-component fallback behavior, and the default error UI is safe but intentionally minimal. When navigation must keep the previously revealed route visible and replace it only after all remote Client Boundaries and their precedence styles are ready, move the runtime wrapper above changing route content so it remains mounted across navigations:
Render HostRscRuntime from a persistent Host layout, not from the changing plugin page, and pass the same assetMountPath used by the Host asset middleware. In host mode each remote lazy import propagates suspension instead of committing a local empty/loading fallback. Next navigation is transition-aware, so an already revealed stable boundary keeps the previous route until all delegated remote boundaries in that coordinated region are ready, then React commits that replacement together. Plugin-owned nested Suspense boundaries keep their own intentional reveal sequence. The Host fallback still defines cold-entry behavior when there is no previously revealed route. Do not pass renderLoading with suspensePolicy="host"; the provider rejects that contradictory configuration. Keep renderError when the product needs per-component retry and failure isolation. RscNextClientRuntime also installs the Host browser navigation adapter. A remote plugin uses the framework-neutral entry and never imports Next:
RscLink delegates eligible same-origin clicks to the Host router after hydration and otherwise remains a normal anchor. Client Components may use useRscNavigation() from the same entry for imperative push, replace, refresh, or prefetch; imperative destinations accept only HTTP(S), and cross-origin navigation remains a full browser navigation. Do not append _rsc, send Flight headers, or depend on next/link or next/navigation from a plugin; Next owns its private navigation request when the Host adapter calls the public router. @hile/rsc-next supports exactly Next 16.3.0 with React 19.2.8 and checks the installed package tuple before decoding through its isolated private Next modules. Do not widen the Next peer range without rerunning the full production SSR/hydration suite. Do not add cache(), unstable_cache, or route revalidation around tenant/user-specific plugin rendering by default. Cross-request caching is an application policy; it requires an explicit authorization-safe key and invalidation contract. The /plugins prefix is only this Host route’s policy. You may choose another catch-all route without changing the RSC core. The minimal route maps “no active deployment” to 404 and lets the Host error boundary handle unexpected runtime failures. A product Host should explicitly map authorization denial, deployment still downloading, incompatible build, drained/stale build, upstream unavailable, and request cancellation according to its HTTP/UI policy. Do not put those product decisions into @hile/rsc.

8. Keep The Outer Layout In The Host

The Host owns <html>, <body>, navigation, authentication shell, global theme, document metadata, and application-level error boundaries. The plugin tree is rendered inside that shell. Plugin builds may publish bounded presentation metadata through plugin.json. Read it from the current active deployment and artifact catalogs with listActiveRscPlugins(deployments, artifacts), then apply Host authorization and visibility policy before passing serializable navigation items to the shell. This is a derived view, not another plugin inventory, and it changes atomically with active buildId selection. Presentation metadata is data, not executable head code. The Host may map trusted fields such as displayName or description through Next metadata APIs, but arbitrary plugin code still cannot mutate the Host document head.
For Ant Design or another CSS-in-JS library:
  • place the Host library’s Next SSR registry/collector around children in the Host layout;
  • place plugin ConfigProvider, App, theme, and plugin-only providers inside the plugin client boundary;
  • bundle plugin-imported static CSS as plugin assets;
  • keep React external/shared so Host and plugin do not create incompatible contexts;
  • test raw HTML and hydrated behavior. A visually correct client-only render is not sufficient SSR evidence.
The validated Ant Design Host setup installs antd@6.6.0 and @ant-design/nextjs-registry@1.3.0, then composes:
The Host shell owns navigation and application-wide theme state:
The plugin owns a separate provider inside its remote Client Boundary. This module is compiled as part of the plugin browser/SSR graph and must not wrap <html> or replace the Host collector:
For a larger plugin, move the ThemeConfig into a plugin-owned module while keeping the provider at this boundary. Re-run raw-HTML, hydration, and compatibility tests whenever Ant Design or its Next registry version changes. Repository maintainers can compare the larger executable examples in packages/test-rsc-plugin-capabilities-v2 and packages/test-rsc-host. Published-doc readers do not need those private demo paths to implement the provider structure above.

9. Production Build And Startup

Start Registry in its own process:
Readiness is the registry started on port 9876 log plus a successful plugin/Host Registry connection; merely having a process with that PID is not readiness. In production, supervise Registry separately and bind it to the intended private interface. Then build both generated projects. These commands assume the two projects are siblings, not members of a pnpm workspace:
Keep Registry running. Start the foreground services in separate terminals:
Ordering between plugin and Host startup is flexible after Registry exists: discovery reconciles later arrivals. Readiness means the plugin internal listener is ready and its accepted announcement is visible; a process merely existing is not sufficient. On first reconciliation the Host:
  1. reads Registry candidates;
  2. authenticates publisher ownership;
  3. selects a compatible candidate;
  4. streams plugin.json and every declared artifact directly into isolated temporary files with credit/backpressure and hard limits;
  5. verifies paths, sizes, runtime tuple, and SHA-256 integrity;
  6. atomically installs and activates the deployment;
  7. keeps old builds available while existing leases drain.

10. Development Mode

Use hile-rsc-dev plus the plugin service. For deterministic cold startup, run pnpm dev:rsc, wait until .hile-rsc/development.json contains a revision for the configured namespace, then run pnpm dev:service in a second terminal. The current template scripts/dev.mjs is a convenience process owner that starts both children and propagates exit/signals; if a cold machine exposes a first-state race, use the deterministic two-terminal order or replace the supervisor with an explicit state-readiness gate. The development compiler consumes the same optional styles configuration as production and includes those files in every immutable revision. A relative style under the plugin cwd triggers the normal source watcher; after changing an absolute or package-export style outside cwd, invoke a rebuild or reload the config explicitly. Development binding belongs in the generated plugin boot: bindRscModelDevelopment() watches the models directory, while bindRscPluginDevelopmentState() activates a verified revision and calls the runtime-supplied publisher only after activation. The Host onEnabled observer publishes RscDevelopmentEvents, its middleware serves SSE, and the Host root layout renders RscDevelopmentReload only in development. Complete cold-start order for sibling generated projects:
After the first successful cold start, cd rsc-plugin && pnpm dev may be used as the two-child convenience command. Keep the Registry and Host terminals running. Development behavior:
  • server, browser, and SSR esbuild contexts persist across rebuilds;
  • server-only edits reuse browser/SSR outputs when client inputs and Server Function graph are unchanged;
  • Client Boundary, transitive client input, CSS, exported boundary, or Server Function graph changes rebuild affected client artifacts;
  • every successful revision is immutable and receives an exact revision build ID;
  • a failed build keeps the previous deployment serving and the watcher alive;
  • model changes atomically reload models without compiling RSC assets;
  • after the plugin activates and republishes, the Host downloads/verifies/enables it, then emits SSE and RscDevelopmentReload refreshes the page;
  • this is full-page refresh after safe activation, not cross-plugin React Fast Refresh state preservation.
Use at least two retained revisions. Size maxRevisions for the maximum build-download-activation overlap, and keep maxSessions bounded so stale sessions cannot grow indefinitely.

11. Upgrade, Removal, And Failure Semantics

  • A new build is downloaded and verified before activation.
  • New renders select the new build; in-flight renders keep their captured old lease.
  • The old runtime/artifact retires only after drain and retention policy allow it.
  • A failed candidate does not replace the working build.
  • A missing announcement is tolerated for missingReconciliations; after that grace, the deployment retires automatically.
  • Stopping or uninstalling a plugin therefore disables it without a manual Host activation API.
  • RscPluginService.activate() is an internal lifecycle primitive used by verified runtime/development orchestration. “No manual activation” means application users and Host routes do not call it as an install workflow.
  • Never mutate bytes under an already published build ID. It breaks cache and deployment identity.
  • At equal priority, publish newer immutable builds with a higher generation. HMAC mode signs that generation; announcements without generation remain valid legacy generation zero.

12. Verification

First verify the generated pair itself:
The response must contain the plugin’s server-rendered heading. In a browser, open the same URL, increment local client state, submit the Server Function form added in sections 3–4, and confirm the Model result appears without a page error. Inspect Network to confirm plugin JS/CSS and the Server Function POST use 127.0.0.1:3000; no browser request may target the plugin Micro port. Stop the plugin and wait past the configured missing-announcement grace to verify automatic removal, then restart it to verify automatic reinstallation. Edit a Server Component in the four-terminal development topology and verify a new immutable build ID appears only after a successful rebuild; introduce and repair a syntax error to verify last-good behavior. For a generated external project, record the browser’s successful Server Function request and use “Copy as cURL” to repeat it with a wrong Origin, missing/incorrect CSRF token, stale build ID, unknown reference ID, oversized body, and an aborted connection. Every altered request must fail without invoking the Model. For upgrade coverage, build a new immutable buildId, start it at higher priority, verify new requests select it while an already-started slow request finishes on the old build, then remove the old announcement. For isolation coverage, generate a second plugin with a distinct pluginId, namespace, and Micro port, and verify neither plugin’s assets or Server Function references resolve under the other identity. The following exhaustive architecture acceptance suite is available only to maintainers working in the Hile monorepo; it is not a command for scaffolded sibling projects:
Monorepo-only interactive reference:
Then open:
  • http://127.0.0.1:3200/ for discovery and deployment state;
  • http://127.0.0.1:3200/plugins/demo.rsc.capabilities?label=review&count=3 for Server/Client/CSS/lazy/action coverage;
  • http://127.0.0.1:3200/plugins/demo.rsc.capabilities/details?source=review for a server-only plugin route;
  • http://127.0.0.1:3200/plugins/demo.rsc.isolation?marker=review for independent plugin isolation.
An implementation is not complete until tests prove:
  • only the Host accepts public HTTP;
  • raw HTML contains plugin SSR output;
  • hydration, hooks, context, effects, CSS, library components, and lazy chunks work without console errors;
  • a module-level Server Function works through useActionState and executes the expected scanned Model in the plugin process;
  • wrong origin/token, unknown reference, stale build, invalid input, excessive body, and aborted requests fail safely;
  • server/SSR artifacts cannot be fetched from the public asset route;
  • discovery rejects values outside the selected trust mode; HMAC coverage includes wrong signatures and publisher/plugin ownership mismatches;
  • artifact transfer is streamed to disk with bounded size/count/path constraints;
  • upgrade preserves in-flight old-build requests and failed rebuilds preserve the last good revision.
  • stream window/timeout/idle-timeout, discovery generation ordering, bounded snapshot concurrency, and Host loading/error retry policies are covered.

Troubleshooting

Completion Checklist For AI Agents

  • I used the current templates or explained every deviation.
  • Plugin and Host runtime pins match the compatibility tuple supported by their installed RSC packages.
  • Plugin process uses --conditions=react-server and creates no HTTP server.
  • Models load before HileRscPluginRuntime.start().
  • New UI behavior uses module-level 'use server'defineRscServerFunction() → explicit API → defineActionModel().
  • Host and plugin select the same explicit discovery trust mode; HMAC mode binds keyId to explicit plugin IDs.
  • Host mounts assets, Server Functions, and development SSE on its one HTTP server.
  • Dynamic Next route resolves and passes the exact active build ID and abort signal.
  • Render timeout, idle timeout, stream window, observer, and shared verification cache are configured.
  • Discovery generation and snapshot concurrency are configured; HMAC mode signs generations.
  • Loading/error functions live in a Host Client Component and retry is tested.
  • Outer layout remains Host-owned; plugin providers/styles remain plugin-owned.
  • Development keeps the last good immutable revision and reloads after verified activation.
  • Contract, production E2E, and development E2E checks pass.

Lower-Level Extension Points

Use attachRscPluginService, registerHileRscPluginDiscovery, RscDiscoveryManager, custom locators, or custom artifact catalogs only when building an adapter or persistence implementation. They are not the default application integration path. Keep transport, trust, storage, lifecycle, Next decoding, and business behavior in separate modules.