inertia_dart 1.0.0
inertia_dart: ^1.0.0 copied to clipboard
Dart implementation of Inertia.js protocol
Inertia Dart #
Build single page apps without building an API. This package implements the
server-side Inertia protocol for Dart and provides property helpers, SSR
support, and testing utilities. Pair it with a client adapter like
@inertiajs/react, @inertiajs/vue3, or @inertiajs/svelte.
New here? Follow the Build a Contacts App tutorial for a hands-on walkthrough using just
dart:io.
Using Serinus? Use the
serinus_inertiapackage for a more integrated experience — it providesInertiaModule,RequestContext.inertia(), and managed SSR support out of the box.
Install #
dart pub add inertia_dart
| Inertia.js client version | inertia_dart package version |
|---|---|
| 3.x | >=1.0.0 |
<3.0 |
<1.0.0 |
CLI #
Scaffold a Vite client with Inertia already wired:
dart run inertia_dart:inertia create my-app --framework react
Install Inertia into an existing Vite project:
dart run inertia_dart:inertia install --framework react --path ./web
Quickstart #
Create a page payload and return an Inertia JSON response from your server handler.
import 'package:inertia_dart/inertia_dart.dart';
final context = PropertyContext(headers: requestHeaders);
final page = InertiaResponseFactory().buildPageData(
component: 'Dashboard',
props: {
'user': {'name': 'Ada'},
'stats': LazyProp(() => loadStats()),
},
url: '/dashboard',
context: context,
version: '1.0.0',
);
final response = InertiaResponse.json(page);
For working server/client samples, see:
Props #
Property helpers let you control when data resolves and how it merges.
LazyPropandOptionalPropare excluded from the first load and only resolve on partial reloads.DeferredPropdefers evaluation until the client requests the group.MergePropsupports deep merge, append/prepend paths, and match-on keys.ScrollPropadds pagination metadata for infinite scroll behavior.OncePropadds once metadata with optional TTL and keys.
final props = {
'user': () => user,
'stats': OptionalProp(() => expensiveStats()),
'feed': DeferredProp(() => loadFeed(), group: 'feed', merge: true)
.append('items', 'id'),
'cursor': ScrollProp(() => pageData),
'token': OnceProp(() => token, ttl: Duration(hours: 1)),
};
Partial Reloads #
The request helpers parse advanced Inertia headers:
X-Inertia-Partial-DataX-Inertia-Partial-ExceptX-Inertia-ResetX-Inertia-Except-Once-PropsX-Inertia-Infinite-Scroll-Merge-IntentX-Inertia-Error-Bag
Use InertiaHeaderUtils or InertiaRequest to build the correct
PropertyContext for your server.
History Flags #
PageData supports history flags:
encryptHistoryclearHistory
Middleware #
Enable history encryption for every response with the built-in middleware:
final middleware = EncryptHistoryMiddleware();
final response = await middleware.handle(request, (req) async {
return next(req);
});
SSR #
Use SsrGateway to call your SSR server and render HTML:
final gateway = HttpSsrGateway(Uri.parse('http://localhost:13714'));
final ssr = await gateway.render(jsonPage);
Control SSR behavior in code with InertiaSsrSettings:
final settings = InertiaSsrSettings(
enabled: true,
endpoint: Uri.parse('http://127.0.0.1:13714/render'),
bundle: 'bootstrap/ssr/ssr.mjs',
runtime: 'node',
runtimeArgs: ['--trace-warnings'],
);
You can also start/stop/check a local SSR process:
final process = await startSsrServer(
SsrServerConfig.fromSettings(settings),
);
final healthy = await checkSsrServer(endpoint: settings.endpoint!);
await stopSsrServer(endpoint: settings.endpoint!);
process.kill();
CLI helpers for SSR bundles:
dart run inertia_dart:inertia ssr:start --runtime node
dart run inertia_dart:inertia ssr:check --url http://127.0.0.1:13714
dart run inertia_dart:inertia ssr:stop --url http://127.0.0.1:13714
Asset Manifest Helper #
InertiaAssetManifest loads a Vite-style manifest.json and renders tags.
final manifest = await InertiaAssetManifest.load('client/dist/.vite/manifest.json');
final tags = manifest.renderTags('index.html', baseUrl: '/');
Vite Asset Helper #
InertiaViteAssets reads a dev hot file or a production manifest and returns
script/style tags.
final assets = InertiaViteAssets(
entry: 'index.html',
hotFile: 'client/public/hot',
manifestPath: 'client/dist/.vite/manifest.json',
includeReactRefresh: true,
);
final tags = await assets.resolve();
final htmlTags = tags.renderAll();
dart:io HttpServer Helper #
If you are using dart:io directly, you can build requests and write responses
without a framework wrapper.
final request = inertiaRequestFromHttp(httpRequest);
final context = request.createContext();
final page = InertiaResponseFactory().buildPageData(
component: 'Home',
props: {'title': 'Inertia + HttpServer'},
url: request.url,
context: context,
);
final response = InertiaResponse.json(page);
await writeInertiaResponse(httpRequest.response, response);
Vite Hot File Helper #
The package ships a small Vite plugin to generate a public/hot file (Laravel
style).
If you want to generate the plugin file from Dart instead of copying it by hand, use:
import 'dart:io';
import 'package:inertia_dart/inertia_dart.dart';
Future<void> main() async {
await writeInertiaViteHotFilePlugin(Directory('client'));
}
That writes client/inertia_hot_file.js by default. You can also render the
source without writing a file:
final source = renderInertiaViteHotFilePlugin(
defaultHotFile: 'frontend/public/hot',
);
Then import it from your Vite config:
import { defineConfig } from 'vite'
import { inertiaHotFile } from './inertia_hot_file.js'
export default defineConfig({
plugins: [inertiaHotFile()],
})
A full template is available at assets/vite/vite.config.js.
Testing #
Use AssertableInertia and InertiaTestExtensions for response assertions.
response.assertInertia((page) {
page.component('Dashboard').has('user.name');
});
Learn More #
- Inertia Dart docs -- full API reference and tutorial
- Inertia core docs -- protocol specification and client adapters
serinus_inertia-- Serinus adapter withInertiaModule,RequestContext.inertia(), and managed SSR