Flutter
Build and query a ZXCV database from a Flutter app, then ship it to the edge. You’ll end with a screen that reads live data.
Create a project
In the dashboard click Start building, or run zxcv
from your terminal. Open Settings → API and copy your project ref and
anon key — the anon key is public and safe to ship, because access is enforced
server-side by your authorization rules.
Create a table
In the SQL editor, create a todos table with a couple of rows:
create table todos (
id bigint generated always as identity primary key,
title text not null,
is_complete boolean not null default false
);
insert into todos (title) values ('Read the docs'), ('Ship an app');Install the SDK
Add zxcv_flutter to your pubspec.yaml:
flutter pub add zxcv_flutterThat adds the dependency for you:
dependencies:
flutter:
sdk: flutter
zxcv_flutter: ^1.0.0Initialize the client
Initialize ZXCV once in main(), before runApp, so the client is ready for
the whole app. The anon key is safe to ship in client code:
import 'package:flutter/material.dart';
import 'package:zxcv_flutter/zxcv_flutter.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Zxcv.initialize(
project: 'acme-store',
anonKey: 'your-anon-key',
);
runApp(const MyApp());
}For real projects, keep your keys out of source with --dart-define (e.g.
flutter run --dart-define=ZXCV_ANON_KEY=...) and read them via
String.fromEnvironment('ZXCV_ANON_KEY').
Fetch and render
Use a FutureBuilder to run the query and a ListView to render the rows.
Zxcv.instance is the client you initialized in main():
import 'package:flutter/material.dart';
import 'package:zxcv_flutter/zxcv_flutter.dart';
class TodosPage extends StatelessWidget {
const TodosPage({super.key});
@override
Widget build(BuildContext context) {
final todos = Zxcv.instance
.from('todos')
.select('id, title, is_complete')
.order('id');
return Scaffold(
appBar: AppBar(title: const Text('Todos')),
body: FutureBuilder(
future: todos,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
}
final rows = snapshot.data ?? [];
return ListView.builder(
itemCount: rows.length,
itemBuilder: (context, i) {
final todo = rows[i];
return ListTile(title: Text(todo['title'] as String));
},
);
},
),
);
}
}Deploy
Ship your project to the global edge from your terminal:
npm i -g zxcv
zxcv link acme-store
zxcv deploy --prodEvery push gets a preview URL; --prod promotes to your domain. See
Deploy for custom domains and canaries.
Next steps
- Auth — add sign-in and row-level security
- Realtime — live updates as rows change
- SDK reference · Database