Documentation
Mount the bundled assets and wire verified solverforge-ui primitives into an Axum app.
Getting Started with solverforge-ui
This guide covers the verified integration path:
- add the crate
- mount
/sf/*assets with.merge(solverforge_ui::routes()) - include the bundled CSS and JS
- instantiate components plus the retained-job backend and solver helpers
Add the Dependency
[dependencies]
axum = "0.8.9"
solverforge-ui = { version = "0.6.5" }
# Pin a specific GitHub release tag when you need exact reproducibility.
# solverforge-ui = { git = "https://github.com/SolverForge/solverforge-ui", tag = "v0.6.5" }
Use the Git tag form when you need exact source-tag reproducibility instead of the crates.io package.
Use Rust 1.95+ for the current crate line.
Mount /sf/* Routes in Axum
use axum::{routing::get, Router};
async fn index() -> &'static str {
include_str!("../static/index.html")
}
fn app() -> Router {
Router::new()
.route("/", get(index))
.merge(solverforge_ui::routes())
}
solverforge_ui::routes() serves the embedded /sf/* assets. Your application
still owns its HTML pages and any job/solver API routes.
Include Required Assets in HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>solverforge-ui quickstart</title>
<link
rel="stylesheet"
href="/sf/vendor/fontawesome/css/fontawesome.min.css"
/>
<link rel="stylesheet" href="/sf/vendor/fontawesome/css/solid.min.css" />
<link rel="stylesheet" href="/sf/sf.css" />
</head>
<body class="sf-app">
<script src="/sf/sf.js"></script>
<script>
var tabs = SF.createTabs({
tabs: [
{ id: "plan", content: "<div>Plan view</div>", active: true },
{ id: "gantt", content: "<div>Gantt view</div>" },
],
});
document.body.appendChild(tabs.el);
var backend = SF.createBackend({ type: "axum" });
var solver;
var header = SF.createHeader({
title: "SolverForge Scheduler",
subtitle: "by SolverForge",
tabs: [
{ id: "plan", label: "Plan", active: true },
{ id: "gantt", label: "Gantt" },
],
onTabChange: function (id) {
tabs.show(id);
},
actions: {
onSolve: function () {
solver.start();
},
onPause: function () {
solver.pause();
},
onResume: function () {
solver.resume();
},
onCancel: function () {
solver.cancel();
},
},
});
document.body.prepend(header);
var statusBar = SF.createStatusBar({ header: header, constraints: [] });
header.after(statusBar.el);
solver = SF.createSolver({
backend: backend,
statusBar: statusBar,
onProgress: function (meta) {
console.log("progress", meta.currentScore, meta.bestScore);
},
onSolution: function (snapshot) {
console.log("best solution", snapshot.solution);
},
onPaused: function (snapshot, meta) {
console.log("paused", meta.snapshotRevision, snapshot.solution);
},
onComplete: function (snapshot, meta) {
console.log("completed", meta.currentScore, snapshot.solution);
},
});
</script>
</body>
</html>
SF.createSolver(...) now follows the retained-job lifecycle. Use
onProgress(...) for score and telemetry updates, onSolution(...) for
snapshot-bearing best_solution events, and onPaused(...) or
onComplete(...) when you need the exact retained snapshot after the runtime
reaches an authoritative lifecycle state.
The header renders the cancel action as Stop. Keep using the onCancel
configuration key and call solver.cancel(); delete() is reserved for
terminal retained-job cleanup.
Application Routes
solverforge-ui does not generate your scheduling API. The crate ships the UI
surface and a set of backend helpers. If you use
SF.createBackend({ type: 'axum' }), follow the canonical retained-job contract
documented in Integration & Assets. Older
Schedule-named route shapes are historical. Current generated apps expose the
retained /jobs/... contract.
Next Steps
- Read Components to build richer page layouts.
- Read Scheduling Views for timeline rail and Gantt examples.
- Read Integration & Assets for backend adapters, optional map modules, asset serving, and versioned bundle behavior.