Expert on GigLedger's database schema, collections, data models, DTOs, caching strategy, and cost control. Use when designing database schemas, creating DTOs, understanding data flow from database, or optimizing queries. References docs/05_data_model_and_schema.md.
This skill provides deep expertise on GigLedger's database design:
Primary Reference: docs/05_data_model_and_schema.md
This document is the authoritative source for all database design decisions.
Reference: docs/05_data_model_and_schema.md section 1
Purpose: User profile and preferences
Schema:
{
"uid": "user123",
"displayName": "User Name",
"email": "[email protected]",
"favorites": {
"[category1]": ["item1", "item2"],
"[category2]": ["itemA"]
},
"preferences": {
"[preference1]": "value",
"[preference2]": true
},
"hasCompletedOnboarding": true,
"createdAt": "timestamp",
"updatedAt": "timestamp"
}
Access: Read/write by authenticated user only (uid must match)
Purpose: [Description]
Schema:
{
"id": "123",
"field1": "value",
"field2": 123,
"metadata": {
"cachedAt": 1234567890,
"status": "completed"
}
}
Access: [Access pattern]
Cache: [Cache duration/strategy]
Characteristics:
lib/features/{feature}/data/dto/Example:
class [Item]DTO {
final String? id;
final String? name;
final Timestamp? createdAt;
[Item]DTO.fromJson(Map<String, dynamic> json)
: id = json['id'],
name = json['name'],
createdAt = json['createdAt'];
[Item] toDomain() {
return [Item](
id: id ?? '',
name: name ?? '',
createdAt: createdAt?.toDate(),
);
}
}
Characteristics:
lib/features/{feature}/domain/models/Example:
class [Item] {
final String id;
final String name;
final DateTime? createdAt;
[Item]({
required this.id,
required this.name,
this.createdAt,
});
// Computed property
bool get isNew => createdAt != null &&
DateTime.now().difference(createdAt!).inDays < 7;
}
Always transform in the data layer:
class [Database][Item]Repository implements [Item]Repository {
@override
Future<[Item]> get[Item](String id) async {
final doc = await database
.collection('[collection]')
.doc(id)
.get();
// Transform DTO → Domain Model
final dto = [Item]DTO.fromJson(doc.data()!);
return dto.toDomain();
}
}
Completed/historical data:
In-progress/live data:
User data:
Enable database persistence for offline support.
Reference: docs/05_data_model_and_schema.md caching section
Critical rules to prevent runaway costs:
Reference: docs/05_data_model_and_schema.md cost control section
Good:
// Limited query with specific fields
final items = await database
.collection('[collection]')
.where('field', isEqualTo: value)
.limit(20)
.get();
Bad:
// Unbounded query
final allItems = await database
.collection('[collection]')
.get(); // Could fetch thousands of documents!
Reference: docs/05_data_model_and_schema.md and docs/12_security_rules.md
User data:
Protected data:
No client-side writes to protected data - Ever.
Future<[Item]> get[Item](String id) async {
final doc = await database
.collection('[collection]')
.doc(id)
.get();
if (!doc.exists) {
throw [Item]NotFoundException(id);
}
final dto = [Item]DTO.fromJson(doc.data()!);
return dto.toDomain();
}
Future<List<[Item]>> getAll[Items](String parentId) async {
final snapshot = await database
.collection('[parent]')
.doc(parentId)
.collection('[items]')
.get();
return snapshot.docs
.map((doc) => [Item]DTO.fromJson(doc.data()).toDomain())
.toList();
}
Future<List<[Item]>> get[Items]ByCategory(String category) async {
final snapshot = await database
.collection('[collection]')
.where('category', isEqualTo: category)
.orderBy('createdAt')
.limit(20)
.get();
return snapshot.docs
.map((doc) => [Item]DTO.fromJson(doc.data()).toDomain())
.toList();
}
Future<[Item]> get[Item](String id) async {
try {
final doc = await database
.collection('[collection]')
.doc(id)
.get();
if (!doc.exists) {
throw [Item]NotFoundException('Item $id not found');
}
final dto = [Item]DTO.fromJson(doc.data()!);
return dto.toDomain();
} on DatabaseException catch (e) {
if (e.code == 'permission-denied') {
throw PermissionDeniedException();
} else if (e.code == 'unavailable') {
throw NetworkException('Database unavailable');
}
rethrow;
}
}
Use this skill when:
When working with database:
docs/05_data_model_and_schema.mddata/dto/ matching database schema exactlydomain/models/ optimized for business logictoDomain() in DTOdata/repository_impl/.limit() on all collection queriesGigLedger's database design ensures:
Remember: Always reference docs/05_data_model_and_schema.md as the ultimate source of truth for database design.