// DART FLUTTER WEB - Comprehensive Development Reference - by Richard Rembert
// Dart with Flutter Web enables building high-performance, cross-platform web applications
// with native-like performance and beautiful UIs from a single codebase
// ═══════════════════════════════════════════════════════════════════════════════
// 1. SETUP AND ENVIRONMENT
// ═══════════════════════════════════════════════════════════════════════════════
/*
DART FLUTTER WEB DEVELOPMENT SETUP:
1. Install Flutter SDK:
- Download from https://flutter.dev/docs/get-started/install
- Add Flutter to PATH
- Run: flutter doctor
2. Enable web support:
flutter config --enable-web
3. Create new Flutter web project:
flutter create --platforms web my_web_app
cd my_web_app
flutter run -d chrome
4. Essential dependencies (pubspec.yaml):
dependencies:
flutter:
sdk: flutter
# State management
provider: ^6.1.1
bloc: ^8.1.2
flutter_bloc: ^8.1.3
riverpod: ^2.4.9
# HTTP and networking
http: ^1.1.0
dio: ^5.3.2
socket_io_client: ^2.0.3
# UI components
material_design_icons_flutter: ^7.0.7296
flutter_svg: ^2.0.9
cached_network_image: ^3.3.0
animations: ^2.0.11
# Routing
go_router: ^12.1.3
auto_route: ^7.8.4
# Utilities
shared_preferences: ^2.2.2
intl: ^0.19.0
uuid: ^4.2.1
json_annotation: ^4.8.1
# Firebase integration
firebase_core: ^2.24.2
firebase_auth: ^4.15.3
cloud_firestore: ^4.13.6
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.7
json_serializable: ^6.7.1
flutter_lints: ^3.0.1
test: ^1.24.9
5. Web-specific configuration (web/index.html):
My Flutter Web App
*/
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:go_router/go_router.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:html' as html;
// ═══════════════════════════════════════════════════════════════════════════════
// 2. MAIN APPLICATION STRUCTURE
// ═══════════════════════════════════════════════════════════════════════════════
void main() {
runApp(MyWebApp());
}
class MyWebApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AppState()),
ChangeNotifierProvider(create: (_) => AuthService()),
ChangeNotifierProvider(create: (_) => ThemeService()),
ChangeNotifierProvider(create: (_) => NavigationService()),
],
child: Consumer(
builder: (context, themeService, child) {
return MaterialApp.router(
title: 'Flutter Web App',
theme: themeService.lightTheme,
darkTheme: themeService.darkTheme,
themeMode: themeService.themeMode,
routerConfig: AppRouter.router,
debugShowCheckedModeBanner: false,
);
},
),
);
}
}
// Application state management
class AppState with ChangeNotifier {
bool _isLoading = false;
String? _error;
Map _data = {};
bool get isLoading => _isLoading;
String? get error => _error;
Map get data => _data;
void setLoading(bool loading) {
_isLoading = loading;
notifyListeners();
}
void setError(String? error) {
_error = error;
notifyListeners();
}
void setData(Map data) {
_data = data;
notifyListeners();
}
void clearError() {
_error = null;
notifyListeners();
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 3. ROUTING AND NAVIGATION
// ═══════════════════════════════════════════════════════════════════════════════
class AppRouter {
static final GoRouter router = GoRouter(
initialLocation: '/',
routes: [
GoRoute(
path: '/',
name: 'home',
builder: (context, state) => const HomePage(),
),
GoRoute(
path: '/dashboard',
name: 'dashboard',
builder: (context, state) => const DashboardPage(),
routes: [
GoRoute(
path: '/analytics',
name: 'analytics',
builder: (context, state) => const AnalyticsPage(),
),
GoRoute(
path: '/settings',
name: 'settings',
builder: (context, state) => const SettingsPage(),
),
],
),
GoRoute(
path: '/profile/:userId',
name: 'profile',
builder: (context, state) {
final userId = state.pathParameters['userId']!;
return ProfilePage(userId: userId);
},
),
GoRoute(
path: '/auth',
name: 'auth',
builder: (context, state) => const AuthPage(),
),
GoRoute(
path: '/products',
name: 'products',
builder: (context, state) => const ProductsPage(),
routes: [
GoRoute(
path: '/:productId',
name: 'product-detail',
builder: (context, state) {
final productId = state.pathParameters['productId']!;
return ProductDetailPage(productId: productId);
},
),
],
),
],
errorBuilder: (context, state) => ErrorPage(error: state.error.toString()),
redirect: (context, state) {
final authService = context.read();
final isLoggedIn = authService.isAuthenticated;
final isLoggingIn = state.location == '/auth';
// Redirect to auth if not logged in and trying to access protected routes
if (!isLoggedIn && !isLoggingIn && state.location.startsWith('/dashboard')) {
return '/auth';
}
// Redirect to dashboard if logged in and on auth page
if (isLoggedIn && isLoggingIn) {
return '/dashboard';
}
return null; // No redirect
},
);
}
class NavigationService with ChangeNotifier {
int _selectedIndex = 0;
List _history = ['/'];
int get selectedIndex => _selectedIndex;
List get history => _history;
void setSelectedIndex(int index) {
_selectedIndex = index;
notifyListeners();
}
void addToHistory(String route) {
_history.add(route);
if (_history.length > 10) {
_history.removeAt(0);
}
notifyListeners();
}
void goBack() {
if (_history.length > 1) {
_history.removeLast();
final previousRoute = _history.last;
GoRouter.of(context as BuildContext).go(previousRoute);
}
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 4. STATE MANAGEMENT AND SERVICES
// ═══════════════════════════════════════════════════════════════════════════════
// Authentication service
class AuthService with ChangeNotifier {
bool _isAuthenticated = false;
User? _user;
String? _token;
bool get isAuthenticated => _isAuthenticated;
User? get user => _user;
String? get token => _token;
Future login(String email, String password) async {
try {
final response = await http.post(
Uri.parse('https://api.example.com/auth/login'),
headers: {'Content-Type': 'application/json'},
body: json.encode({
'email': email,
'password': password,
}),
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
_token = data['token'];
_user = User.fromJson(data['user']);
_isAuthenticated = true;
// Store token in local storage
html.window.localStorage['auth_token'] = _token!;
notifyListeners();
return true;
}
return false;
} catch (e) {
print('Login error: $e');
return false;
}
}
Future register(String email, String password, String name) async {
try {
final response = await http.post(
Uri.parse('https://api.example.com/auth/register'),
headers: {'Content-Type': 'application/json'},
body: json.encode({
'email': email,
'password': password,
'name': name,
}),
);
if (response.statusCode == 201) {
// Auto-login after registration
return await login(email, password);
}
return false;
} catch (e) {
print('Registration error: $e');
return false;
}
}
Future logout() async {
_isAuthenticated = false;
_user = null;
_token = null;
// Clear local storage
html.window.localStorage.remove('auth_token');
notifyListeners();
}
Future loadSavedToken() async {
final savedToken = html.window.localStorage['auth_token'];
if (savedToken != null) {
_token = savedToken;
// Verify token and load user data
await _loadUserFromToken();
}
}
Future _loadUserFromToken() async {
try {
final response = await http.get(
Uri.parse('https://api.example.com/auth/me'),
headers: {
'Authorization': 'Bearer $_token',
'Content-Type': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
_user = User.fromJson(data);
_isAuthenticated = true;
notifyListeners();
} else {
// Token is invalid
await logout();
}
} catch (e) {
print('Token verification error: $e');
await logout();
}
}
}
// User model
class User {
final String id;
final String email;
final String name;
final String? avatar;
final DateTime createdAt;
User({
required this.id,
required this.email,
required this.name,
this.avatar,
required this.createdAt,
});
factory User.fromJson(Map json) {
return User(
id: json['id'],
email: json['email'],
name: json['name'],
avatar: json['avatar'],
createdAt: DateTime.parse(json['created_at']),
);
}
Map toJson() {
return {
'id': id,
'email': email,
'name': name,
'avatar': avatar,
'created_at': createdAt.toIso8601String(),
};
}
}
// Theme service
class ThemeService with ChangeNotifier {
ThemeMode _themeMode = ThemeMode.system;
bool _isDarkMode = false;
ThemeMode get themeMode => _themeMode;
bool get isDarkMode => _isDarkMode;
ThemeData get lightTheme => ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
appBarTheme: const AppBarTheme(
elevation: 0,
centerTitle: true,
),
cardTheme: CardTheme(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
filled: true,
),
);
ThemeData get darkTheme => ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
appBarTheme: const AppBarTheme(
elevation: 0,
centerTitle: true,
),
cardTheme: CardTheme(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
),
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
filled: true,
),
);
void setThemeMode(ThemeMode mode) {
_themeMode = mode;
_updateDarkMode();
notifyListeners();
}
void toggleTheme() {
_isDarkMode = !_isDarkMode;
_themeMode = _isDarkMode ? ThemeMode.dark : ThemeMode.light;
notifyListeners();
}
void _updateDarkMode() {
switch (_themeMode) {
case ThemeMode.dark:
_isDarkMode = true;
break;
case ThemeMode.light:
_isDarkMode = false;
break;
case ThemeMode.system:
_isDarkMode = WidgetsBinding.instance.window.platformBrightness == Brightness.dark;
break;
}
}
}
// HTTP service for API calls
class ApiService {
static const String baseUrl = 'https://api.example.com';
final http.Client _client = http.Client();
Future