155 lines
5.9 KiB
Markdown
155 lines
5.9 KiB
Markdown
|
|
# flutter folder structure — eutopic
|
||
|
|
|
||
|
|
model: deepseek-reasoner
|
||
|
|
test: instruction-following, feature-first structure, domain accuracy
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
```
|
||
|
|
lib/
|
||
|
|
├── main.dart
|
||
|
|
├── app.dart
|
||
|
|
│
|
||
|
|
├── core/
|
||
|
|
│ ├── theme/
|
||
|
|
│ │ ├── app_theme.dart
|
||
|
|
│ │ └── app_colors.dart
|
||
|
|
│ ├── router/
|
||
|
|
│ │ └── app_router.dart
|
||
|
|
│ └── constants/
|
||
|
|
│ └── app_constants.dart
|
||
|
|
│
|
||
|
|
├── shared/
|
||
|
|
│ ├── models/
|
||
|
|
│ │ ├── user.dart
|
||
|
|
│ │ ├── post.dart
|
||
|
|
│ │ ├── poster_post.dart
|
||
|
|
│ │ ├── story.dart
|
||
|
|
│ │ ├── survey.dart
|
||
|
|
│ │ ├── reaction.dart
|
||
|
|
│ │ ├── comment.dart
|
||
|
|
│ │ ├── invite_code.dart
|
||
|
|
│ │ └── social_handle.dart
|
||
|
|
│ ├── widgets/
|
||
|
|
│ │ ├── photo_grid.dart
|
||
|
|
│ │ ├── photo_swipe.dart
|
||
|
|
│ │ ├── emoji_picker.dart
|
||
|
|
│ │ ├── loading_indicator.dart
|
||
|
|
│ │ └── error_view.dart
|
||
|
|
│ ├── services/
|
||
|
|
│ │ ├── api_client.dart
|
||
|
|
│ │ ├── auth_service.dart
|
||
|
|
│ │ └── upload_service.dart
|
||
|
|
│ └── utils/
|
||
|
|
│ ├── date_formatter.dart
|
||
|
|
│ └── validators.dart
|
||
|
|
│
|
||
|
|
├── features/
|
||
|
|
│ ├── onboarding/
|
||
|
|
│ │ ├── onboarding_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── invite_gate.dart
|
||
|
|
│ │ │ ├── email_username_form.dart
|
||
|
|
│ │ │ ├── magic_link_confirm.dart
|
||
|
|
│ │ │ ├── social_handle_opt_in.dart
|
||
|
|
│ │ │ └── follow_suggestions.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── onboarding_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── feed/
|
||
|
|
│ │ ├── feed_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── post_card.dart
|
||
|
|
│ │ │ ├── post_photo_swipe.dart
|
||
|
|
│ │ │ ├── reaction_bar.dart
|
||
|
|
│ │ │ ├── comment_sheet.dart
|
||
|
|
│ │ │ └── survey_card.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── feed_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── posters/
|
||
|
|
│ │ ├── posters_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── poster_grid.dart
|
||
|
|
│ │ │ ├── poster_card.dart
|
||
|
|
│ │ │ ├── poster_filter_bar.dart
|
||
|
|
│ │ │ └── rsvp_button.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── posters_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── compose/
|
||
|
|
│ │ ├── compose_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── photo_picker_tile.dart
|
||
|
|
│ │ │ ├── caption_field.dart
|
||
|
|
│ │ │ ├── destination_toggle.dart
|
||
|
|
│ │ │ ├── tag_picker.dart
|
||
|
|
│ │ │ ├── event_fields.dart
|
||
|
|
│ │ │ ├── reaction_set_picker.dart
|
||
|
|
│ │ │ ├── savable_toggle.dart
|
||
|
|
│ │ │ └── upload_progress_animation.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── compose_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── stories/
|
||
|
|
│ │ ├── stories_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── story_player.dart
|
||
|
|
│ │ │ ├── story_filter_overlay.dart
|
||
|
|
│ │ │ ├── story_capture.dart
|
||
|
|
│ │ │ └── witness_list.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── stories_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── profile/
|
||
|
|
│ │ ├── profile_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── profile_header.dart
|
||
|
|
│ │ │ ├── profile_post_grid.dart
|
||
|
|
│ │ │ ├── social_handle_display.dart
|
||
|
|
│ │ │ ├── contact_prefs_display.dart
|
||
|
|
│ │ │ ├── follow_button.dart
|
||
|
|
│ │ │ └── settings_button.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── profile_provider.dart
|
||
|
|
│ │
|
||
|
|
│ ├── settings/
|
||
|
|
│ │ ├── settings_screen.dart
|
||
|
|
│ │ ├── widgets/
|
||
|
|
│ │ │ ├── social_handle_settings.dart
|
||
|
|
│ │ │ └── display_preferences.dart
|
||
|
|
│ │ └── providers/
|
||
|
|
│ │ └── settings_provider.dart
|
||
|
|
│ │
|
||
|
|
│ └── feedback/
|
||
|
|
│ ├── feedback_screen.dart
|
||
|
|
│ ├── widgets/
|
||
|
|
│ │ ├── active_survey_card.dart
|
||
|
|
│ │ ├── survey_question_tile.dart
|
||
|
|
│ │ └── free_text_field.dart
|
||
|
|
│ └── providers/
|
||
|
|
│ └── feedback_provider.dart
|
||
|
|
│
|
||
|
|
└── navigation/
|
||
|
|
├── app_navigation.dart
|
||
|
|
└── bottom_tab_bar.dart
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### design rationale
|
||
|
|
|
||
|
|
**feature-first** — each screen lives under `features/{name}/` with co-located widgets and state. no flat `screens/` or `widgets/` directory.
|
||
|
|
|
||
|
|
**shared models** in `shared/models/` so the `post.dart` model used by feed, posters, and compose lives in one place. feature-specific models (like invite_code for onboarding) could stay in the feature folder — here i kept them in shared since they're referenced across auth boundaries.
|
||
|
|
|
||
|
|
**no notification files** — per the spec: no notifications, no dms, no push alerts. you won't find a `notifications/` folder or a `push_service.dart`.
|
||
|
|
|
||
|
|
**story as tab** — the spec is explicit that stories are a bottom tab, not a top strip. `stories_screen.dart` lives at the same level as `feed_screen.dart`, matching the five-tab nav.
|
||
|
|
|
||
|
|
**compose as center tab** — `compose_screen.dart` is a top-level feature folder. the upload_service in `shared/services/` handles tus.io resumable upload, referenced by the compose provider.
|
||
|
|
|
||
|
|
**naming consistency** — `*_screen.dart` for entry-point widgets (one per feature), `*_provider.dart` for state (using provider or riverpod — TBD), descriptive names for sub-widgets.
|
||
|
|
|
||
|
|
**onboarding is a feature** — not stuffed into `auth/` or `screens/`. it has its own provider and five child widgets matching the five-step flow from the spec.
|