DioxusLabs/dioxus
View on GitHubdx build doesn't prepend <!DOCTYPE html> for server+fullstack+ssg builds
Open
#5,500 opened on Apr 21, 2026
bugenhancementgood first issuemanganis
Repository metrics
- Stars
- (36,038 stars)
- PR merge metrics
- (Avg merge 16d 13h) (9 merged PRs in 30d)
Description
Problem
on running dx build --verbose --trace --server --fullstack true --features fullstack --release --ssg I get this warning from my browser
This page is in Quirks Mode. Page layout may be impacted. For Standards Mode use “<!DOCTYPE html>”
Steps To Reproduce
Steps to reproduce the behavior:
- create a new dioxus workspace project (crates: app, pages)
- put your router inside pages crate and make it public
- add this to app/src/main.rs
use dioxus::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
#[cfg(feature = "server")]
#[tokio::main]
async fn main() {
rustls::crypto::ring::default_provider()
.install_default()
.expect("Failed to install ring crypto provider");
let certs_dir = std::env::var("CERTS_DIR").expect("CERTS_DIR must be set");
let rustls_config = axum_server::tls_rustls::RustlsConfig::from_pem_file(
format!("{}/server.crt", certs_dir),
format!("{}/server.key", certs_dir),
)
.await
.expect("Failed to load TLS config");
let address = std::net::SocketAddr::from(([0, 0, 0, 0], 8080));
let router = axum::Router::new().serve_dioxus_application(get_serve_config(), App);
axum_server::bind_rustls(address, rustls_config)
.serve(router.into_make_service())
.await
.unwrap();
}
#[cfg(target_arch = "wasm32")]
fn main() {
dioxus::logger::init(tracing::Level::DEBUG).expect("failed to init logger");
dioxus::LaunchBuilder::new()
.with_cfg(server_only! { get_serve_config() })
.launch(App);
}
#[cfg(feature = "fullstack")]
#[server(endpoint = "static_routes", output = server_fn::codec::Json)]
async fn static_routes() -> Result<Vec<String>, ServerFnError> {
Ok(pages::Route::static_routes()
.iter()
.map(ToString::to_string)
.collect())
}
#[cfg(feature = "server")]
fn get_serve_config() -> ServeConfig {
ServeConfig::builder()
.incremental(
dioxus::server::IncrementalRendererConfig::new()
.static_dir(static_dir())
.clear_cache(false),
)
.enable_out_of_order_streaming()
}
fn static_dir() -> std::path::PathBuf {
std::env::current_exe()
.unwrap()
.parent()
.unwrap()
.join("public")
}
#[component]
fn App() -> Element {
rsx! {
Router::<pages::Route> {}
}
}
- add this to app/Cargo.toml
[package]
name = "app"
version.workspace = true
edition.workspace = true
[dependencies]
pages = { path = "../pages" }
axum = { workspace = true, optional = true }
axum-server = { workspace = true, optional = true }
dioxus = { workspace = true, features = ["router"] }
rustls = { workspace = true, optional = true }
tokio = { workspace = true, optional = true }
tracing = { workspace = true }
[build-dependencies]
[features]
default = []
web = ["dioxus/web"]
desktop = ["dioxus/desktop"]
mobile = ["dioxus/mobile"]
server = ["dioxus/server", "dep:tokio", "dep:axum", "dep:axum-server", "dep:rustls"]
fullstack = ["dioxus/fullstack"]
- add this to ./Cargo.toml
[workspace]
resolver = "3"
members = [ "app", "pages"]
exclude = []
default-members = [ "app" ]
[workspace.package]
version = "0.1.0"
edition = "2024"
[workspace.dependencies]
axum = { version = "0.8" }
axum-server = { version = "0.8", features = ["tls-rustls"] }
dioxus = { version = "0.7.5" }
getrandom = { version = "0.4", features = ["wasm_js"] }
rustls = { version = "0.23", features = ["ring"] }
tokio = { version = "1", features = ["rt", "net"] }
tracing = { version = "0.1", features= ["release_max_level_off"] }
[workspace.lints.clippy]
redundant_clone = "warn"
[profile]
[profile.wasm-dev]
inherits = "dev"
opt-level = 1
[profile.server-dev]
inherits = "dev"
[profile.android-dev]
inherits = "dev"
- run
dx build --verbose --trace --server --fullstack true --features fullstack --release --ssg - run
./target/dx/app/release/web/server
Expected behavior
Dioxus should automatically prepend to all HTML output regardless of:
- Build type (development vs production)
- Renderer (web, server, native)
- Whether using custom templates or defaults
This would ensure consistent behavior and prevent the quirks mode warnings
Environment:
- Dioxus version: dioxus 0.7.5 (was built without git repository)
- Rust version: cargo 1.95.0 (f2d3ce0bd 2026-03-21)
- OS info: NixOS (nixpkgs unstable)
- App platform: web