Repository navigation
Description
Problem
Framework features should be consumable through the same function-based Stackpress plugin mechanism used by application and third-party plugins. Today the framework crates are reusable libraries, but host integration is uneven: application code assembles page registration, settings handlers, generated operations and generation tooling through different APIs.
The requested outcome is a coherent plugin-facing integration layer over those libraries. This does not require one plugin per crate, a plugin trait, or a new plugin loader.
Current behavior and source evidence
Review baseline: remote trial/3 at 74319ac366f3397b684ee5fa8007651c19e54292. The cited integration sources match the inspected local checkout; unrelated later admin edits are outside this issue.
- Project direction says plugins contribute services, events, routes, policy and generation, and the framework follows the same conventions. A registration function is the essential contract.
- ServerBuilder::plugin / plugin_with already accept registration functions and support explicit dependency/order checks.
- framework-view offers
ServerBuilderViewExt::page, rather than a uniform feature plugin entry point. - Profile UI application wiring assembles backend selection, pages and a fixed API route in example-owned code.
- framework-sql supplies generated-operation registration support; framework-admin generation emits explicit native operation/route registration.
- framework-preferences exports provide helpers and persistence/state contracts; the application wires their host handlers.
Existing registration shape:
// Existing host API; "register" is an ordinary function pointer.
pub fn plugin(
&mut self,
id: &str,
register: fn(&mut ServerBuilder) -> stackpress_lib::Result<()>,
) -> stackpress_lib::Result<&mut Self>;Current composition excerpt from the Profile UI application:
backend::register(app)?;
register_pages_with_module(app, base.clone(), module)?;
app.post(
routes::search_api(&base).map_err(Error::from_source)?.as_str(),
search_api,
)?;Requested behavior
Allow consumers to select framework features through ordinary app.plugin(...) / app.plugin_with(...) registration while retaining direct use of the underlying libraries.
Illustrative consumer experience — proposed names, not existing APIs:
use stackpress_lib::Result;
use stackpress_server::ServerBuilder;
fn presentation(app: &mut ServerBuilder) -> Result<()> {
stackpress_framework_preferences::plugin::register(app)?;
stackpress_framework_view::plugin::register(app)?;
// Application-specific pages, renderers and policies remain explicit.
Ok(())
}
async fn application() -> stackpress_server::BuildResult<stackpress_server::Server> {
let mut app = ServerBuilder::new();
app.plugin("presentation", presentation)?;
app.build().await
}The issue concerns developer integration. It does not request a visual redesign or changed search/CRUD behavior.
Scope and boundaries
Assess all seven current framework crates: view, UI, language, preferences, schema, SQL and admin. Decide which own runtime registration, which contribute to a composite feature, and which remain support libraries or build-time facilities. Avoid empty registration functions added solely for naming consistency.
Preserve compile-time selection, ordinary lifecycle/dispatch semantics, explicit application policy and separate web/native adapters. Importing/enabling a library must not expose routes automatically. Plugin startup must not implicitly install/migrate/seed databases or start network listeners.
Keep Idea/code-generation registration in the build tool; do not pull generators into the final application or native services into browser builds. Runtime registration and build-time participation need separate documented entry points where applicable.
Acceptance criteria
- Record a reviewed capability-to-crate/plugin map for all seven crates, including registration responsibilities, required configuration/services, dependency order, supported targets and deliberate exclusions.
- Provide documented function-based entry points for the selected host-integrated features, compatible with existing
ServerBuilderplugin APIs; preserve directly usable libraries. - Publish a responsibility list for each entry point: configuration, startup callbacks, services, operations, routes and optional build-tool hooks. Application-owned policies and route/model selections remain explicit.
- Demonstrate both a directly selected framework plugin and application composition/customization without changing core handlers or introducing a second dispatcher.
- Update at least one existing presentation example to use the integration and preserve its public responses, locale/theme behavior, route mounts and lifecycle behavior.
- Prove meaningful negative behavior: missing/wrong-order dependencies, duplicate/conflicting registrations, invalid configuration and denied protected actions fail through the existing contracts before inappropriate effects.
- Verify disabled integrations register nothing and preserve appropriate default/browser/native dependency graphs. Build SSR, hydration and CSR separately.
- Document the migration from existing application wiring, direct-library usage, feature selection and runtime-versus-generation integration. Run relevant tests, doctests, target checks and the repository's three substantive review/refactoring rounds; report coverage and platform limitations under the existing quality policy.
Non-goals
Dynamic loading/hot enablement, a universal plugin trait, mandatory directory layouts, implementing missing authentication/synchronization systems, dependency/toolchain upgrades, publication or deployment. This issue records work to design and implement; the snippets do not freeze the final API.
Activity
cblanquera commentedon Oct 27, 2026
Suggested implementation approach
These are proposals for the design checkpoint. All new symbols in the snippets below are sketches, not compile-verified APIs.
1. Map features before adding entry points
Keep the current pure libraries and choose plugin boundaries by behavior:
Prefer an optional
pluginmodule behind the crate's existingserverfeature where appropriate. If that creates an awkward dependency graph, justify a separate integration crate instead. Do not make every pure helper depend onstackpress-server.2. Reuse the existing registration contract
For independently identified features, use
PluginSpecrather than inventing a registry or loader. The IDs, dependencies and entry-point names here are illustrative and require the responsibility map first:Only declare a dependency if the feature actually requires that selected plugin. Keep the caller's ordering and existing missing/cycle/order failures.
For a composite feature, call contribution helpers inside one selected function. Do not call
app.plugin(...)from a registration callback: the current builder seals plugin selection before callbacks run. Helpers executed under a composite retain that composite's identity; use separate selections when distinct provenance/order requirements matter.3. Keep selection at compile time and configuration typed
A possible native consumer manifest:
Keep the frontend as a separate hydrate/CSR consumer with host features disabled. Use typed configuration sections and startup callbacks to validate options and construct services. Register application settings before
build(); do not depend on ambient globals or runtime strings loading compiled-out code. The existing function-pointer API needs no closure capture: configuration, application wrapper functions and contribution helpers cover the ordinary cases.4. Share operations, keep transport policy in adapters
Presentation integration should not silently expose arbitrary event names over HTTP/IPC. A settings plugin needs explicit routes/command mapping, origin/CSRF/authorization policy where applicable, cookie scope or native storage policy, and safe public projection.
Reuse
ServerBuilderViewExt::page,PageSpec, the Leptos renderer and generated operation handlers. Keep normal plugin startup separate from database installation/migration/seed commands and explicit network-host startup.5. Separate build-tool participation
A feature may provide both runtime integration and a generator, but use them in different binaries/build graphs:
Do not force the transform registry to implement
ServerBuilderregistration or conflate generation with runtime startup.6. Deliver a bounded pilot, then extend
Start with a presentation/preferences vertical and one existing example. Freeze its responsibility/configuration contract, prove parity and negative cases, then apply the convention to SQL/admin where the map identifies useful integration.
Suggested behavior-focused checks:
Complete the repository's complexity, responsibility/abstraction and consistency/Rustdoc review rounds with meaningful tests. Keep direct-library examples alongside the plugin example so the added integration does not become mandatory.
cblanquera commentedon Oct 27, 2026
Coordination update: independent Leptos library and view plugin
See #17, requested after this issue was filed: extract the reusable part of
framework-uiintocrates/leptos(intended packagestackpress-leptos) and makeframework-viewconsume it through optional integration.This refines the capability-to-crate/plugin map above:
stackpress-leptosis an ordinary reusable library. It must not require a Stackpress host/plugin, page protocol or preference persistence merely to use components.framework-viewowns the Stackpress-facing page/route/render adapters and plugin registration.Proposed usage examples, not APIs available today:
Update the proposed registration map and old
framework-ui-*facade/feature examples in light of #17. Do not add a UI plugin that exists only to import components. Preserve direct library use, compile-time selection and explicit runtime registration. Break the current UI → view dependency before adding view → reusable Leptos integration; a reverse-edge feature would still create a cycle.Coordinate the final entry points with #15/#17, and use #16's server-family paths when those changes land. Earlier code sketches remain historical proposals, not additional APIs to implement in parallel.
Add framework-view preferences and flash plugin registrations (issue #15
Add issue #14 design checkpoint (framework plugin entry points)
Record G42: issue #14 keeps current route semantics; ui-preferences p…
Add framework-view's presentation plugin and migrate ui-preferences t…
Record issue #14 part 1 as verified and merged; paused before part 2
Resume issue #14 at M2
Fast-build workflow: isolate disposable consumer targets; trim increm…
Issue #14 M2: SQL plugin registration, generated admin page host plug…
Record issue #14 M2 coordinator verification; correct the nextest rec…
Issue #14 M3: review rounds, plugin docs, cancellation test, isolated…
Record issue #14 M3 coordinator verification; issue #14 implementatio…