nomos_flutter 0.21.1
nomos_flutter: ^0.21.1 copied to clipboard
Drive the real Nomos GitHolon from a Flutter app — a local-first domain runtime. iOS runs the native-AOT kernel (no WebView memory cap); Android/macOS use a hidden secure WebView. Write TypeScript dom [...]
example/lib/main.dart
// nomos_flutter example — drives the REAL GitHolon through NomosScope. On iOS this runs the native-AOT
// kernel over dart:ffi (no WebView); elsewhere the hidden WebView host. Same NomosBridge protocol either way.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:nomos_flutter/nomos_flutter.dart';
const cloud = 'https://nomos.captainapp.co.uk';
const workspace = 'todo-dogfood-20260616-codex';
const listId = 'prof-convergence';
void main() => runApp(const MaterialApp(debugShowCheckedModeBanner: false, home: _Root()));
class _Root extends StatelessWidget {
const _Root();
@override
Widget build(BuildContext context) => NomosScope(
cloud: cloud,
workspace: workspace,
builder: (context, nomos) => TodoPage(nomos.bridge),
loadingBuilder: (context, bridge) => const Scaffold(
body: Center(child: Text('booting native kernel…')),
),
);
}
class TodoPage extends StatefulWidget {
final NomosBridge bridge;
const TodoPage(this.bridge, {super.key});
@override
State<TodoPage> createState() => _TodoPageState();
}
class _TodoPageState extends State<TodoPage> {
final _input = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('nomos_flutter · native kernel')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Row(children: [
Expanded(child: TextField(controller: _input,
decoration: const InputDecoration(hintText: 'new todo…', border: OutlineInputBorder(), isDense: true))),
const SizedBox(width: 8),
FilledButton(onPressed: () async {
final t = _input.text.trim();
if (t.isEmpty) return;
_input.clear();
await widget.bridge.offer(intentBytes: jsonEncode({
'domain': 'todo', 'directiveId': 'addTodo', 'payload': {'listId': listId, 'text': t},
}));
}, child: const Text('Add')),
]),
),
Expanded(
child: StreamBuilder<List<dynamic>>(
stream: widget.bridge.watch('todosByList', {'listId': listId}),
builder: (context, snap) {
final rows = snap.data ?? const [];
if (snap.hasError) return Center(child: Text('error: ${snap.error}'));
return ListView.builder(
itemCount: rows.length,
itemBuilder: (c, i) {
final d = (rows[i] as Map)['data'] as Map? ?? rows[i] as Map;
return ListTile(dense: true, title: Text((d['text'] ?? '?').toString()));
},
);
},
),
),
],
),
);
}
}