Flutter data layer
Skill almasumdev/awesome-flutter-agent-skills/.github/skills/architecture/flutter-data-layer
Curated agent skills, conventions, and workflows for building Flutter apps with AI coding agents.
npx -y skills add almasumdev/awesome-flutter-agent-skills --skill flutter-data-layerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Build an offline-first data layer in Flutter using the Repository pattern with Drift/Isar/sqflite for local storage and Dio for networking. Use this when implementing repositories, data sources, or caching.
SKILL.md
2.8 KB, as published. Nobody here has run it
Flutter Data Layer & Offline-First
Instructions
The data layer hides data origin (network, cache, DB) behind Repository interfaces that return domain entities.
1. Repository Interface (Domain)
Declared in the domain layer, pure Dart:
abstract class ArticleRepository {
Stream<List<Article>> watchAll();
Future<Article> getById(String id);
Future<void> refresh();
}
2. Repository Implementation (Data)
class ArticleRepositoryImpl implements ArticleRepository {
ArticleRepositoryImpl(this._api, this._dao);
final ArticleApi _api;
final ArticleDao _dao;
@override
Stream<List<Article>> watchAll() =>
_dao.watchAll().map((rows) => rows.map((r) => r.toDomain()).toList());
@override
Future<void> refresh() async {
final remote = await _api.fetchArticles(); // DTOs
await _dao.upsertAll(remote.map((d) => d.toRow()).toList());
}
@override
Future<Article> getById(String id) async =>
(await _dao.findById(id))?.toDomain() ?? (throw NotFoundException(id));
}
3. Data Sources
- Remote:
Dioclient wrapped in typed API classes (e.g.,retrofitcode-gen or hand-rolled). Seeflutter-dioskill. - Local:
- Drift: relational, reactive
Streamqueries, SQL power — preferred for complex schemas. - Isar / ObjectBox: object DB, fastest, good for read-heavy mobile apps.
- sqflite: low-level SQLite when you need raw control.
- shared_preferences / flutter_secure_storage: small key-value (tokens, flags) only.
- Drift: relational, reactive
4. Offline-First Strategy
- Single source of truth = the local DB.
- UI observes a
Streamfrom the DAO via the repository. - Background refresh: fetch remote, upsert into DB, stream automatically updates.
- Map errors explicitly — a network failure must not clear cached data.
5. DTOs vs Entities
- DTOs (
ArticleDto) mirror the API wire format. Place indata/. Usejson_serializableorfreezed'sfromJson. - Entities (
Article) live indomain/and are what the UI consumes. - Mappers (
extension ArticleDtoX on ArticleDto { Article toDomain() }) keep the conversion explicit and testable.
6. Checklist
- Repository interfaces in
domain/, implementations indata/. - UI never imports DTOs or DAO row classes.
- Reads are reactive (Stream) when possible; writes return
Future<void>. - DB migrations are versioned and tested.
- Network failures are wrapped in typed exceptions (
NetworkException,ServerException, ...).