Imported from bitplz/Portfolio (
AGENTS.md). Install upstream withnpx skills add bitplz/Portfolio. Copyright stays with the author.
AGENTS.md - AI Development Guide
Project Overview
This is a Flutter portfolio application showcasing personal projects and professional journey. It's deployed to web (Vercel) and supports mobile/tablet/desktop via responsive design. Uses GetX for state management and routing, EmailJS for contact forms.
Environment Setup
Required Versions
- Dart SDK:
>=3.4.0 <4.0.0(currently 3.5.4) - Flutter: Latest stable
- Node.js: For Vercel deployment
Key Dependency Versions
flutter_lints: ^5.0.0(compatible with Dart 3.4.0+)get: ^4.6.6(state management)emailjs: ^4.0.0(email service)firebase_core: ^4.7.0(Firebase initialization)flutter_neumorphic_plus: ^3.4.0(UI styling)
Note: Do not upgrade flutter_lints beyond 5.x as newer versions require Dart 3.8.0+. Use flutter pub outdated to check available updates before upgrading any dependencies.
Architecture & Key Components
1. State Management Pattern (GetX)
- Controller:
HomeController(tag:'home_controller') manages navigation, form state, and email sending- Use
Get.put()for initialization inHomeView.build(), access viaHomeController.instance(static getter) orGet.find<HomeController>(tag: 'home_controller') - Observable pattern:
RxInt selectedTabIndex,RxBool loading, text controllers wrapped inRx<TextEditingController> - Tab switching via
onSelectTab()returns corresponding View widget from switch statement (About/Resume/Portfolio/Contact) - EmailJS initialization in
onInit()with error handling; controllers properly disposed inonClose()
- Use
- Service:
AnalyticServices(Firebase analytics integration structure ready; Firebase initialization inmain.dartviafirebase_options.dart)
2. Responsive Design Three-Tier System
ResponsiveLayoutwidget wraps views with three builds:mobileView,tabView(optional, defaults tomobileView),desktopView; all wrapped inSelectionAreafor text selection support- Desktop (maxWidth > 1200): Sidebar + main content in Row with flex 24:76 ratio; padding calculated as
(maxWidth - 1200) / 2 - Mobile: Vertical stack with scrollable content and fixed bottom tab bar
- Tablet: Falls back to
tabViewparameter if provided, otherwisemobileView - Tab views (AboutView, ResumeView, etc.) follow pattern:
ResponsiveLayout→_buildMobileLayout()and_buildDesktopLayout()private methods - Content padding extracted in each view: mobile/tablet use
horizontalPadding: 10, desktop useshorizontalPadding: 30
3. View Structure (Single Page, Multi-Tab)
HomeViewis the only page; four tabs (AboutView,ResumeView,PortfolioView,ContactView) swap viagetTabView()- Views decomposed into
_buildMobileLayout()and_buildDesktopLayout()functions within each view file - Views access
HomeControllerviaGet.find<HomeController>(tag: 'home_controller')
4. UI Component Library
All custom widgets in lib/utils/common_widgets.dart:
CustomContainer: Animated border container with optional gradient backgroundAvatarContainer: Gradient-filled rounded container with shadowTimeLineListView: Timeline component usingtimeline_tilepackage (used in Resume view)TabItem: Custom tab button with selection highlightdownloadCVButton(): Neumorphic button launching CV URL viaurl_launchercardStyle(): Factory function returningNeumorphicStylefor 3D card effect
5. Email Integration (EmailJS)
- Config:
Environment.publicKey,Environment.privateKey,Environment.serviceId,Environment.templateIdfrom.envfile - Flow: Form fields in
ContactView→ validate withformKey→ callHomeController.sendEmail()→ async emailjs.send() → clear form - Error Handling:
EmailJSResponseStatuscaught separately;CommonMethods().showSuccessToast()/showDangerToast()for UI feedback - Rate Limiting:
LimitRate(id: 'web-app', throttle: 10000)prevents spam
5b. Firebase Integration (Firestore)
- Config:
firebase_options.dart(auto-generated by FlutterFire CLI) contains platform-specific credentials- Web: Configured with API key, App ID, Messaging Sender ID, Project ID (
portfolio-d4714), Auth Domain, Storage Bucket, Measurement ID - Mobile/Desktop: Currently throw
UnsupportedError; configure via FlutterFire CLI when needed
- Web: Configured with API key, App ID, Messaging Sender ID, Project ID (
- Initialization:
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform)called inmain.dartwith error handling - Data Service:
FirestoreService(inlib/services/firestore_service.dart) handles all Firestore operations- Collections:
education,experience,projects,personalDetails - Supports both futures (one-time fetch) and streams (real-time updates)
- Collections:
- Data Access Pattern:
PortfolioDataController(GetX singleton) fetches data from Firestore on app startup- Access via
PortfolioDataController.instanceorGet.find<PortfolioDataController>(tag: 'portfolio_data_controller') - Observable getters enable reactive UI updates via
Obx()wrapper
- Data Models:
lib/models/portfolio_models.dartcontains Education, Experience, Project, PersonalDetails with Firestore serialization - Migration:
lib/utils/firestore_migration.dartprovides utilities to migrate legacy data fromcommon_strings.dartto Firestore
6. Design System
- Color Palette (
lib/utils/app_colors.dart): Dark mode with accent yellows- Primary:
smokeyBlack(#121212),background(#1E1E1F) - Accent:
selectionColor(#F7D96A),accent(#FFDB70) - Containers:
lightBlackContainer(#2B2B2C) - Gradients:
linearGradient,tileLinearGradient,yellowGradientpre-defined
- Primary:
- Typography: Custom Poppins font family (weights: 300, 500, 600, 700, 900)
- Text Themes: Separate
mobileTextThemeanddeskTopTextTheme(defined intext_theme.dart) applied per device
External Dependencies
- Core:
flutter(SDK),get: ^4.6.6(state management),flutter_dotenv: ^6.0.1(environment variables) - UI:
flutter_neumorphic_plus: ^3.4.0,timeline_tile: ^2.0.0,flutter_svg: ^2.0.10+1,responsive_builder: ^0.7.1 - Services:
emailjs: ^4.0.0,url_launcher: ^6.3.0,flutter_map: ^8.3.0,latlong2: ^0.9.1,firebase_core: ^3.0.0,cloud_firestore: ^5.0.0 - Feedback:
fluttertoast: ^9.0.0 - Dev:
flutter_lints: ^5.0.0(linting; version constraint tied to Dart SDK 3.5.4)
Developer Workflows
Build & Deploy
- Web:
flutter build web→ outputs tobuild/web/→ deployed via Vercel (seevercel.jsonfor routing) - Mobile: Android via
android/build.gradle, iOS viaios/Runner.xcodeproj - Environment: Create
.envfile (included in pubspec.yaml assets) with EmailJS keys
Testing & Analysis
- Run lints:
flutter analyze(usesanalysis_options.yamlwith flutter_lints ^5.0.0) - Widget tests:
test/widget_test.dartexists but minimal; tests should follow Flutter conventions - Check outdated deps:
flutter pub outdated(warns about newer versions; assess compatibility before upgrading) - ⚠️ Dependency Note:
flutter_lintsis pinned to ^5.0.0 for Dart 3.5.4 compatibility; do not upgrade to 6.0.0+ without upgrading Dart SDK to 3.8.0+
Local Development
- Verify Dart SDK:
dart --version(should be 3.4.0 or later, ideally 3.5.4) flutter pub getto fetch dependenciesflutter pub outdatedto check for available updates—review compatibility before upgrading- Hot reload enabled; ensure
.envfile exists with valid EmailJS credentials - Responsive testing: Use Chrome DevTools device simulator or
flutter run -d chrome
Project Conventions
File Organization
lib/screens/homepage/: All tab views + controller (single-page app)lib/utils/:- Design tokens (
app_colors.dart,text_theme.dart) - UI widget library (
common_widgets.dart) - Content management (
common_strings.dart- education, experience, project descriptions as const Maps) - Utilities (
common_methods.dart,environment.dart,controllers.dart)
- Design tokens (
lib/services/: External service integrations (e.g.,analytics_services.dart)assets/: Images, SVGs, and fonts (all referenced inpubspec.yaml)
Naming & Patterns
- Controllers: Suffixed with
Controller, tagged on initialization - Views: Suffixed with
View, placed in feature folders - Private widgets: Prefixed with
_(e.g.,_SideBar,_ContactMap) - Observables: Wrapped in
Rx<T>or use.obssuffix (e.g.,RxInt,Rx<TextEditingController>) - Form handling: Use
GlobalKey<FormState>for validation; stored in controller
Responsive Breakpoints
- Mobile:
deviceScreenType == DeviceScreenType.mobile - Tablet:
deviceScreenType == DeviceScreenType.tablet - Desktop:
deviceScreenType == DeviceScreenType.desktop - Max desktop width: 1200px (constrain content via padding)
URL Launching
- Use
url_launcherfor external links (CV, social profiles) - Set
LaunchMode.platformDefaultfor cross-platform compatibility
Critical Files to Understand
lib/main.dart: App initialization, Firebase setup, theme config, responsive text theme selectionlib/firebase_options.dart: Firebase configuration (auto-generated by FlutterFire CLI); contains platform-specific credentialslib/models/portfolio_models.dart: Data models (Education, Experience, Project, PersonalDetails) with Firestore serializationlib/services/firestore_service.dart: Firestore CRUD operations and real-time streaminglib/screens/homepage/portfolio_data_controller.dart: GetX controller managing portfolio data from Firestorelib/screens/homepage/home_controller.dart: Tab switching logic, form state, EmailJS integrationlib/screens/homepage/home_view.dart: Main layout logic (3 device types); delegates to tab viewslib/utils/common_widgets.dart: Reusable UI components (CustomContainer, AvatarContainer, etc.)lib/screens/responsive_layout.dart: Wrapper for responsive buildspubspec.yaml: Dependencies, font assets, image assets
Firestore Database Structure
Collections & Documents
education collection: Education history (ordered by order field)
{
"title": "Institution Name",
"time": "YYYY - YYYY",
"desc": "Description",
"order": 1
}
experience collection: Work experience (ordered by order field)
{
"title": "Company Name",
"time": "Month YYYY - Month YYYY",
"desc": "Job description",
"order": 1
}
projects collection: Portfolio projects (ordered by order field)
{
"title": "Project Name",
"type": "Mobile Application|Web Application|Flutter Package",
"coverImage": "asset path or URL",
"iconUrl": "asset path or URL",
"playstoreUrl": "URL to store listing or empty string",
"about": "Detailed project description",
"order": 1
}
personalDetails/details document: Personal info and about me
{
"email": "rchauhan439@gmail.com",
"mobile": "+91 8810529272",
"address": "New Delhi - 110074",
"aboutMe": "About me text..."
}
Firestore Security Rules (Basic)
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Allow public read access to portfolio data
match /{document=**} {
allow read: if true;
}
// Restrict write access (configure based on authentication)
// match /{document=**} {
// allow write: if request.auth != null;
// }
}
}
Firestore Setup & Data Seeding
Initial Setup Steps
- Firebase Console: Go to
portfolio-d4714project → Firestore Database - Create Collections: Manually create
education,experience,projects,personalDetailscollections - Add Documents: Use Firebase Console to add documents matching the structure in "Firestore Database Structure" section, OR:
- AutoSeed with Migration Utility: Use
FirestoreMigrationclass fromlib/utils/firestore_migration.dartto programmatically seed Firestore with existing data
Programmatic Seeding (Data Migration)
To migrate legacy hardcoded data from common_strings.dart to Firestore:
-
Import the migration utility in a setup/admin screen:
import 'package:portfolio/utils/firestore_migration.dart'; -
Call the seeding function (e.g., on first app launch or via admin button):
seedFirestoreWithLegacyData(); // Uncommented code in firestore_migration.dart -
Migration helper methods available:
FirestoreMigration.getLegacyEducationData()- Returns List of education recordsFirestoreMigration.getLegacyExperienceData()- Returns List of experience recordsFirestoreMigration.getLegacyProjectsData()- Returns List of all projectsFirestoreMigration.getLegacyPersonalDetailsData()- Returns Map of personal details
Real-Time Data Sync
Views can optionally use streaming for live updates instead of one-time fetches:
- Replace
getEducation()witheducationStream()inFirestoreService - Wrap UI with
StreamBuilderto react to real-time changes - Example:
StreamBuilder<List<Education>>(stream: FirestoreService().educationStream(), ...)
Common Tasks
- Add new tab: Create view file in
lib/screens/homepage/, add case toHomeController.getTabView()andgetTabName(), implement withResponsiveLayoutwrapping_buildMobileLayout()and_buildDesktopLayout() - Update portfolio content: Add/edit documents in Firestore collections (
education,experience,projects,personalDetails) via Firebase Console; app fetches automatically viaPortfolioDataController - Access portfolio data in views: Use
PortfolioDataController.instance.getEducationData()or Obx wrapper for reactive updates:Obx(() => ListView(children: PortfolioDataController.instance.educationList.value)) - Seed Firestore with initial data: Use
FirestoreServicemethods or import fromcommon_strings.dartas migration; see Firestore Database Structure section - Add new page: Consider architectural impact—this is single-page; extract multi-page nav to GetX navigation
- Style changes: Modify
AppColorsand text themes centrally; useCustomContainerorAvatarContainerfor UI - External link: Use
url_launcherwithLaunchMode.platformDefault - Toast feedback: Call
CommonMethods().showSuccessToast()orshowDangerToast() - Access controllers: Use
HomeController.instanceorGet.find<HomeController>(tag: 'home_controller'); usePortfolioDataController.instanceorGet.find<PortfolioDataController>(tag: 'portfolio_data_controller')for data - Enable real-time updates: Switch from
getEducation()etc. toeducationStream()inFirestoreServicefor live data updates