Engine Architecture & Custom Module Development
DioxusPress avoids speculative plugin loaders and single-implementation trait factories. Every domain module is an ordinary Rust crate wired cleanly through explicit data contracts at the crates/app composition root.
Layering & Dependency Rules
flowchart BT Core["crates/core: SiteConfig / i18n / Auth / ModuleEngine / DB Pool"] Widgets["crates/widgets: Markdown & MDX / SEO Meta / ReadingLayout / Browser APIs"] Modules["crates/modules/*: docs / blog / cases / forum / course / search ..."] App["crates/app: Route Enum / 3 Shell Layouts / Cross-Module Slot Composition"] Core --> Widgets Widgets --> Modules Modules --> App
- Zero Sibling Coupling: Crates under
crates/modules/*never depend on one another. For example,module-docsknows nothing aboutmodule-forum(discussions) ormodule-course(annotations); instead it accepts afooter: Elementslot assembled bycrates/appaccording to active Cargo features.
Adding a Domain Module in Four Steps
- Create the Crate: Under
crates/modules/<your-mod>/, separate#[cfg(feature = "server")]data loaders from isomorphic Dioxus#[component]views. - Register a
ModuleSpec: Add the module ID, route prefixes, and optionalstatic_pathtobuiltin_module_specs()incrates/core/src/engines/module.rs— wiringsite.json::modules.<id>.enabledand/sitemap.xmlautomatically. - Mount Routes Behind
ModuleGate: Add variants toRouteincrates/app/src/routes/mod.rswrapped inModuleGate { id: "<your-mod>", ... }so runtime-disabled modules cleanly return404. - (Optional) Index into Tantivy: Add a collector in
crates/modules/search/src/indexer.rsto surface entries inside the⌘Ksearch dialog.

