eutopic/LEARNING-SPEC.md

214 lines
9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LEARNING-SPEC.md
context for any agent writing flutter code for eutopic.
## who is reading this code
a junior developer. no flutter or dart experience. basic understanding of frontend concepts (html/css level). goal: understand the code well enough to write business logic, modify screens, and eventually own the codebase. not a throwaway learning exercise — this is the real app.
## annotation requirements
every file must include three layers of annotation. this is non-negotiable.
### 1. file-top architecture comment
a short paragraph (36 sentences) at the top of every file, inside a block comment. must explain:
- what this file is and what it does
- why it exists as a separate file (not just "it's a widget")
- how it connects to the rest of the app (what calls it, what it calls)
example format:
```dart
/*
* feed_screen.dart
*
* the main home feed. this is what the user sees after login — a chronological
* list of photo posts from people they follow. it lives at the '/' route and is
* the first tab in the bottom nav bar.
*
* this screen owns fetching the post list from the api and passing individual
* posts down to PostCard widgets. it does not know how to render a post — that
* is PostCard's job. separation of concerns: screen = data, widget = display.
*/
```
### 2. boilerplate explanation comments
every structural/architectural decision in the boilerplate must have a comment explaining *why*, not just *what*. target: someone who has never seen flutter before can read this file and understand the pattern.
things that always need explanation:
- `StatelessWidget` vs `StatefulWidget` — explain the difference and why this file uses one over the other
- `BuildContext context` — what it is and why it's passed everywhere
- `const` constructors — why they exist, what they do for performance
- `@override` — what it means in dart
- `super.key` — what keys are and why the constructor takes one
- `Widget build(BuildContext context)` — what this method is and when flutter calls it
- any `initState` / `dispose` usage — explain the lifecycle
- any `setState(() {})` — explain what it triggers and why it's needed
- named parameters with `{}` braces vs positional — explain the difference
- `required` keyword — explain what it enforces
- `?` nullable types — explain dart's null safety model briefly on first use per file
### 3. logic TODO blocks
for every section the developer will fill in themselves, write a TODO comment that includes:
- a plain-english description of what needs to happen
- a complete dart syntax example showing the pattern to use (as a comment)
- any gotchas or things to watch out for
format:
```dart
// TODO: [plain english description]
//
// example:
// [complete working dart code snippet]
//
// note: [any gotcha or important thing to know]
```
the example must be real, working dart — not pseudocode. it should be close enough to the actual task that the developer can adapt it directly.
## hard sections — write fully, annotate heavily
these three areas are too complex for a junior developer to implement from a TODO. write them completely, but annotate every non-obvious line as if explaining to someone who has never seen async dart or flutter internals:
1. **tus resumable upload** (`shared/services/upload_service.dart`)
- background isolates, tus_client package usage, progress callbacks
- explain what an isolate is, why uploads need one, what happens without it
2. **go_router deep-link invite handling** (`shared/router/app_router.dart`)
- the `redirect` callback, how deep links arrive, how the invite code is extracted from the uri
- explain what a deep link is and the ios/android app link mechanism briefly
3. **story auto-advance timer + gesture layer** (`features/stories/story_viewer_screen.dart`)
- `Timer.periodic`, `AnimationController` for the progress bar, `GestureDetector` for tap-left/tap-right and swipe-down-to-exit
- explain the animation controller lifecycle and why dispose() matters here
## dart syntax reference (include in every file)
every file must include this block, verbatim, near the top after the file-top architecture comment. it is a standing reference so the developer never needs to leave the file to look up basic syntax.
```dart
/*
* dart syntax reference — patterns used in this file
*
* variables
* final String name = 'ada'; // runtime constant — set once, never reassigned
*
* const int max = 10; // compile-time constant — value must be known at build time
*
* String? bio; // nullable — this variable can be null (dart null safety)
*
* late String token; // late — will be assigned before first use, not at declaration
*
* functions
* String greet(String name) { return 'hi $name'; } // regular function
*
* String greet(String name) => 'hi $name'; // arrow shorthand — same as above, one expression only
*
* void log({required String msg}) { ... } // named parameter — caller writes: log(msg: 'x')
*
* void log({String msg = 'hello'}) { ... } // named parameter with default value
*
* void log(String msg) { ... } // positional parameter — caller writes: log('x')
*
* async
* Future<String> fetchName() async { // async function — returns a Future (like a JS Promise)
* final result = await apiCall(); // await pauses here until the Future resolves
* return result;
* }
*
* lists & maps
* final items = <String>['a', 'b']; // typed list
*
* final map = <String, int>{'apples': 3}; // typed map (like a JS object/dict)
*
* for (final item in items) { print(item); } // for-in loop over a list
*
* items.map((x) => x.toUpperCase()).toList() // transform every item (like JS .map())
*
* items.where((x) => x != 'a').toList() // keep items matching condition (like JS .filter())
*
* classes
* class Post {
* final String id;
* final String? caption; // optional field — may be null
* const Post({required this.id, this.caption}); // const constructor, named params
* }
*
* null safety
* bio?.length // safe access — returns null if bio is null, not an error
*
* bio ?? 'no bio' // fallback — use 'no bio' if bio is null
*
* bio! // force-unwrap — crashes if null. avoid unless certain.
*
* control flow
* if (x != null) { ... } else { ... }
*
* final label = isOwn ? 'you' : user.name; // ternary — shorthand if/else (same as JS)
*
* switch (tag) {
* case 'event': ... break;
* default: ...
* }
*
* string interpolation
* 'hello $name' // insert a variable directly
*
* 'count: ${list.length}' // insert an expression — use braces when it's more than a variable
*/
```
this block should appear in every file. agents must not remove or shorten it — the developer is learning dart as they go and will refer to it repeatedly.
## style rules
- use lowercase prose in comments (matches the project's communication style)
- no marketing language or enthusiasm ("great!", "easy!", "simply")
- be direct. if something is genuinely complex, say so — don't oversimplify
- prefer short sentences over long ones
- comment *why* over *what* — the code shows what, the comment shows why
## file order
write files in this order so concepts build on each other:
1. `lib/main.dart`
2. `lib/app.dart`
3. `lib/core/theme/app_colors.dart`
4. `lib/core/theme/app_theme.dart`
5. `lib/shared/models/` — all model files
6. `lib/core/router/app_router.dart` — hard section
7. `lib/shared/services/api_client.dart`
8. `lib/shared/services/auth_service.dart`
9. `lib/shared/services/upload_service.dart` — hard section
10. `lib/core/widgets/bottom_nav_bar.dart`
11. `lib/shared/widgets/` — shared widgets (photo_viewer, emoji_picker_sheet, loading_indicator, error_view)
12. `lib/features/feed/` — full feature, end to end (reference pattern for all other features)
13. `lib/features/onboarding/`
14. `lib/features/compose/`
15. `lib/features/posters/`
16. `lib/features/stories/` — hard section (story_viewer_screen.dart)
17. `lib/features/profile/`
18. `lib/features/settings/`
19. `lib/features/feedback/`
## project context
- app: eutopic — photo-first social app, invite-only, no notifications, no DMs, no algorithm
- stack: flutter (dart), go_router, tus_client, lottie animations
- folder structure: feature-first (see `docs/ARCHITECTURE.md` — frontend section)
- full concept: `docs/CONCEPT.md`
- screen/navigation spec: `model-tests/02-flutter-folder-structure.md`
- no notification-related code anywhere — this is a hard constraint
- no push alerts, no unread badges, no FCM/APNs
## what counts as done
a file is complete when:
- it compiles without errors
- all three annotation layers are present
- every TODO block has a working dart example
- hard sections are fully implemented with line-level annotation
- no notification-related imports or widgets exist anywhere