# 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.