Todo App Backend Template
Flutter — Schema, API & AI Guide
A production-ready Flutter Todo backend schema and Starter Kit on Back4app: ER diagram, data dictionary, JSON schema, API playground, code examples, and a one-click AI Agent prompt to deploy in minutes.
Key Takeaways
On this page you get a production-ready schema, a one-click AI prompt, and step-by-step Flutter code — so you can ship a Todo app without building the backend.
- Deploy in minutes — paste the AI Agent prompt and get a running app with frontend, backend, and database.
- Secure by default — row-level ACLs ensure each user only sees their own todos.
- Flutter-native SDK — typed objects, async/await, offline pinning, and Live Queries out of the box.
- REST + GraphQL — both APIs are auto-generated; no custom endpoints to write.
- Two classes — _User (built-in auth) and Todo (tasks with title, done, dueDate, priority, owner).
What Is the Flutter Todo App Backend Template?
Back4app is a backend-as-a-service (BaaS) ideal for Todo apps: managed backend, auth, real-time, and SDKs for 13+ technologies. The Flutter Todo App Backend Template is a pre-built, production-ready backend schema hosted on Back4app. It gives you two database classes (_User and Todo), ownership-based ACLs, REST and GraphQL APIs, and a one-click AI Agent prompt — so you can connect a Flutter frontend and ship a working Todo app in minutes instead of days.
Best for:
Overview
A Todo app is one of the most common starting points for learning backend development. Under the hood it needs user registration, task CRUD, ownership-based access control, and optionally real-time sync.
The schema below defines two classes — _User (built-in) and Todo — connected by a Pointer. With the Back4app Flutter SDK, you can interact with this backend from your app — querying, creating, updating, and deleting objects — without writing a custom API layer.
Why Build Your Flutter Todo Backend with Back4app?
Back4app gives you a ready backend and a typed SDK so you can build your Todo app without writing REST glue or managing auth yourself.
- •SDK & type safety: The SDK keeps Todo and User type-safe and handles JSON so you write less boilerplate.
- •Async & optional offline: Use async/await; supported SDKs offer local pinning so your list can work offline and sync when back online.
- •Live Queries: Subscribe to Todo changes so the UI updates in real time over WebSockets.
Same schema and APIs for every stack — switch clients later without changing the backend.
Core Benefits
A production-ready Todo backend so you can ship faster and focus on your app.
Ship Faster, No Backend Code
REST & GraphQL APIs and a ready-to-use schema — connect your app and go.
Secure by Default
ACLs and class-level permissions so users only access their own data.
Real-Time Updates
Live Queries over WebSockets for instant UI updates.
Built-In Auth
User sign-up, login, and session handling out of the box — no custom auth layer.
Works Offline
Local pinning keeps data available offline and syncs when you reconnect.
Deploy in Minutes
Use the AI Agent to create and deploy your Todo app from this template.
Ready to try it?
Let the Back4app AI Agent create your Todo app backend, connect the Flutter frontend, and deploy — all from a single prompt.
Free to start — 50 AI Agent prompts/month, no credit card required
Technical Stack
Everything powering this Todo app template at a glance.
ER Diagram
Entity-Relationship diagram for the Flutter Todo app data model.
The _User class contains objectId, username, email, password, createdAt, and updatedAt. The Todo class contains objectId, title, done, dueDate, priority, and an owner Pointer to _User, plus createdAt and updatedAt. Each _User owns zero or many Todo items.
View diagram source
erDiagram
_User {
String objectId PK
String username
String email
String password
Date createdAt
Date updatedAt
}
Todo {
String objectId PK
String title
Boolean done
Date dueDate
Number priority
Pointer owner FK
Date createdAt
Date updatedAt
}
_User ||--o{ Todo : "owns"
Integration Flow
Auth-to-CRUD sequence: how your Flutter app talks to Back4app — login, then query and create todos.
View diagram source
sequenceDiagram
participant User
participant App as Flutter App
participant Back4app as Back4app Cloud
User->>App: Login
App->>Back4app: Parse().login(username, password)
Back4app-->>App: Session token
App-->>User: Logged in
User->>App: Load todos
App->>Back4app: Query<Todo>().find()
Back4app-->>App: List<Todo>
App-->>User: Show list
User->>App: Create todo
App->>Back4app: todo.save()
Back4app-->>App: Todo (objectId)
App-->>User: Updated listData Dictionary
Complete field reference for every class in the schema.
| Field | Type | Description | Required |
|---|---|---|---|
| objectId | String | Auto-generated unique identifier | auto |
| title | String | Short description of the task | |
| done | Boolean | Whether the task is completed | — |
| dueDate | Date | Optional deadline for the task | — |
| priority | Number | Priority level (1 = high, 3 = low) | — |
| owner | Pointer<_User> | User who owns this task | — |
| createdAt | Date | Auto-generated creation timestamp | auto |
| updatedAt | Date | Auto-generated last-update timestamp | auto |
8 fields in Todo
Security & Permissions
How ownership, ACLs, and class-level permissions protect data in this schema.
Row-Level ACLs
Each Todo gets an ACL tied to its owner. Only the creator can read, update, or delete their own tasks.
Class-Level Permissions
CLPs restrict which roles or users can create, read, update, or delete objects at the class level — your first line of defense.
Pointer-Based Ownership
The owner Pointer links each Todo to its _User. Cloud Code triggers can auto-set ownership and enforce ACLs on save.
Schema (JSON)
Raw JSON schema definition — copy and use in your Back4app app or import via the API.
{
"classes": [
{
"className": "Todo",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"title": {
"type": "String",
"required": true
},
"done": {
"type": "Boolean",
"required": false,
"defaultValue": false
},
"dueDate": {
"type": "Date",
"required": false
},
"priority": {
"type": "Number",
"required": false,
"defaultValue": 3
},
"owner": {
"type": "Pointer",
"targetClass": "_User",
"required": false
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
},
{
"className": "_User",
"fields": {
"objectId": {
"type": "String",
"required": false
},
"username": {
"type": "String",
"required": true
},
"email": {
"type": "String",
"required": true
},
"password": {
"type": "String",
"required": true
},
"createdAt": {
"type": "Date",
"required": false
},
"updatedAt": {
"type": "Date",
"required": false
}
}
}
]
}Build with AI Agent
Use the Back4App AI Agent to build a real Todo app from this template: it will create the frontend, the backend (this schema, auth, and APIs), and deploy it — no manual setup. The prompt below describes this Todo stack so the Agent can generate a production-ready app in one go.
Create a Todo app on Back4app with this exact schema and behavior. Schema: 1. _User (use Back4app built-in): username (String, required), email (String, required), password (String, required); objectId, createdAt, updatedAt (system). 2. Todo: title (String, required), done (Boolean, default: false), dueDate (Date, optional), priority (Number, default: 3; 1=high, 2=medium, 3=low), owner (Pointer to _User; set to current user on create); objectId, createdAt, updatedAt (system). Security: - Set ACLs on every Todo so only the owner has read and write. No public read/write. - On create, set Todo.owner to the current user (e.g. via Cloud Code beforeSave or client-side). - Use Class-Level Permissions so only authenticated users can create/read/update/delete Todo. Auth: - Sign-up (username, email, password) and login; support logout/session. - After login, the app should only show and allow CRUD for the current user's todos. Behavior: - Full CRUD for Todo: create, list (only owner's), get one, update (toggle done, edit title, dueDate, priority), delete. - List todos with sort (e.g. by priority then dueDate or createdAt). Default priority for new todos: 3 (low). Deliver: - Create the Back4app app with the schema above, ACLs, and any Cloud Code needed (e.g. beforeSave on Todo to set owner). - Generate the frontend and connect it to this backend; deploy so the app is runnable end-to-end.
Press the button below to open the Agent with this template's prompt pre-filled.
API Playground
Try the REST and GraphQL endpoints for the Todo schema. Responses from the example data above — no Back4app account needed.
Uses the same Todo schema as this template.
Step-by-Step Flutter Integration
Connect to your Back4app backend from a Flutter app using the Back4app Flutter SDK.
Step 1: Install Back4app Flutter SDK
Add the Back4app SDK for your stack (e.g. npm, pubspec, or package manager).
YAMLdependencies: flutter: sdk: flutter parse_server_sdk_flutter: ^7.0.0Step 2: Initialize Back4app in your app
Initialize the Back4app SDK at app startup with your App ID and server URL.
Dartimport 'package:parse_server_sdk_flutter/parse_server_sdk_flutter.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Parse().initialize( 'YOUR_APP_ID', 'https://parseapi.back4app.com', clientKey: 'YOUR_CLIENT_KEY', autoSendSessionId: true, ); runApp(const MyApp()); }Step 3: Query all todos
Use the SDK to fetch all Todo objects, sorted by priority.
DartFuture<List<ParseObject>> getTodos() async { final query = QueryBuilder<ParseObject>(ParseObject('Todo')) ..orderByAscending('priority'); final response = await query.query(); if (response.success && response.results != null) { return response.results as List<ParseObject>; } return []; }Step 4: Create a todo
Create a new Todo with title, done, and priority, then save.
DartFuture<void> createTodo(String title, {int priority = 3}) async { final todo = ParseObject('Todo') ..set('title', title) ..set('done', false) ..set('priority', priority); final response = await todo.save(); if (response.success) { print('Todo created: ${response.result.objectId}'); } }Step 5: Update and delete todos
Update fields and save, or delete the object.
Dart// Mark a todo as done Future<void> markDone(String objectId) async { final todo = ParseObject('Todo') ..objectId = objectId ..set('done', true); await todo.save(); } // Delete a todo Future<void> deleteTodo(String objectId) async { final todo = ParseObject('Todo')..objectId = objectId; await todo.delete(); }
State Management Integration
Integrate the Back4app SDK with your app's state layer (e.g. context, store, or services).
Full Data Model
Copy a complete Todo model for type-safe serialization (e.g. class, interface, or type definition).
class Todo {
final String? objectId;
final String title;
final bool done;
final DateTime? dueDate;
final int priority;
final String? ownerId;
final DateTime? createdAt;
final DateTime? updatedAt;
Todo({
this.objectId,
required this.title,
this.done = false,
this.dueDate,
this.priority = 3,
this.ownerId,
this.createdAt,
this.updatedAt,
});
factory Todo.fromJson(Map<String, dynamic> json) {
return Todo(
objectId: json['objectId'] as String?,
title: json['title'] as String,
done: json['done'] as bool? ?? false,
dueDate: json['dueDate'] != null ? DateTime.parse(json['dueDate']) : null,
priority: json['priority'] as int? ?? 3,
ownerId: json['owner'] is Map ? (json['owner'] as Map)['objectId'] as String? : null,
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
);
}
Map<String, dynamic> toJson() {
return {
if (objectId != null) 'objectId': objectId,
'title': title,
'done': done,
if (dueDate != null) 'dueDate': dueDate!.toIso8601String(),
'priority': priority,
if (ownerId != null) 'owner': {'__type': 'Pointer', 'className': '_User', 'objectId': ownerId},
if (createdAt != null) 'createdAt': createdAt!.toIso8601String(),
if (updatedAt != null) 'updatedAt': updatedAt!.toIso8601String(),
};
}
}Offline-First & Local Datastore
Use pin() and unpin() so data is available offline and syncs when back online.
Supported SDKs include a local datastore. Pin Todo objects (or the whole class) to keep them on device; query pinned data when offline. When the app is back online, sync with the server.
Below: pin results after fetch, and unpin when you no longer need local copies.
// Pin todos after fetch (offline-first)
Future<void> fetchAndPinTodos() async {
final query = QueryBuilder<ParseObject>(ParseObject('Todo'))
..orderByAscending('priority');
final response = await query.query();
if (response.success && response.results != null) {
final results = response.results!.cast<ParseObject>();
await ParseObject.pinAllObjects(results);
// Now query from local store when offline:
// QueryBuilder<ParseObject>(ParseObject('Todo')).fromLocalDatastore();
}
}
// Unpin when no longer needed
Future<void> unpinAllTodos() async {
await ParseObject.unpinAll('Todo');
}Frequently Asked Questions
Common questions about the Todo app backend template.
Ready to Build Your Todo App?
Start your Flutter project in minutes. No credit card required.