Lumen mounts directly into a Flutter Web canvas via HtmlElementView and a typed JS interop bridge — your users get the full editor, no iframe gymnastics.
// pubspec.yaml: lumen_flutter_web: ^3.0.0
import 'package:flutter/material.dart';
import 'package:lumen_flutter_web/lumen_flutter_web.dart';
class DeckScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Pitch deck')),
body: LumenEditorView( // HtmlElementView under the hood
apiKey: env.lumenKey,
deckId: 'acme-series-b',
template: 'investor.v3',
data: {
'company': 'Acme Health',
'arr': '\$48M',
'fda': true,
},
onEvent: (event) {
if (event.type == 'export.done') {
html.window.open(event.payload['url'], '_blank');
}
},
),
);
}
}Five steps from pubspec.yaml to a fully embedded editor — wired to your own templates, AI, data, image, and storage providers.
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
lumen_flutter_web: ^3.0.0 # Dart wrapper around the Lumen JS SDK<!-- web/index.html — load the Lumen runtime before main.dart.js -->
<script src="https://cdn.lumen.app/sdk/v3/lumen.min.js"
data-api-key="pk_live_xxx"></script>// main.dart — register the platform view once at startup
import 'package:lumen_flutter_web/lumen_flutter_web.dart';
void main() {
LumenSdk.init(
apiKey: const String.fromEnvironment('LUMEN_KEY'),
workspace: 'acme-health',
theme: LumenTheme.auto, // syncs with MediaQuery brightness
);
runApp(const MyApp());
}// Anywhere in your widget tree
LumenEditorView(
deckId: 'acme-series-b',
template: 'investor.v3',
host: myHostConfig, // your TemplateProvider, AiProvider, ...
initialData: {'company': 'Acme Health', 'arr': r'$48M'},
onEvent: (LumenEvent e) {
switch (e.type) {
case LumenEventType.exportDone:
html.window.open(e.payload['url'] as String, '_blank');
break;
case LumenEventType.error:
showSnack(e.payload['message'] as String);
break;
default:
break;
}
},
)Resolve template HTML + scene-graph schema by id.
Stream text completions and synthesize images.
Resolve `{{bindings}}` from CRMs, Postgres, REST.
Upload, search stock, return CDN-friendly URIs.
Load and save serialized DeckSnapshot blobs.
// lib/lumen/interfaces.dart — the contract host apps implement
abstract class TemplateProvider {
Future<List<TemplateMeta>> list({String? query});
Future<TemplateDoc> get(String id);
}
abstract class AiProvider {
Stream<AiChunk> generateText(AiTextRequest req);
Future<AiImage> generateImage(AiImageRequest req);
}
abstract class DataProvider {
Future<Map<String, dynamic>> resolve(String binding, {Map<String, dynamic>? ctx});
}
abstract class ImageProvider {
Future<Uri> upload(Uint8List bytes, {required String mime});
Future<List<StockImage>> search(String query);
}
abstract class StorageProvider {
Future<DeckSnapshot?> load(String deckId);
Future<void> save(String deckId, DeckSnapshot snap);
}
class LumenHostConfig {
final TemplateProvider templates;
final AiProvider ai;
final DataProvider data;
final ImageProvider images;
final StorageProvider storage;
const LumenHostConfig({
required this.templates,
required this.ai,
required this.data,
required this.images,
required this.storage,
});
}Dispatch LumenSdk.update(nodeId, value) from Dart to push host state into the canvas.
Provide a signed JWT via TemplateProvider — Lumen never sees your end-user credentials.
Only the providers you wire are bundled. Unused engines (charts, video) lazy-load on demand.