One Codebase, Multiple Platforms: iOS, Android & Web
Cross-platform UI framework with native performance
Native platform integration for iOS/Android
Optimized WebView for Unity/Godot games
RESTful API with Dio HTTP client
Reactive state with Provider/Riverpod
Optimized for smooth 60 FPS gameplay
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:dio/dio.dart'; class GamePortalApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Game Portal', theme: ThemeData( primarySwatch: Colors.blue, useMaterial3: true, ), home: GameListScreen(), ); } } class GameListScreen extends StatefulWidget { @override _GameListScreenState createState() => _GameListScreenState(); } class _GameListScreenState extends State<GameListScreen> { final dio = Dio(); List<Game> games = []; bool isLoading = true; @override void initState() { super.initState(); fetchGames(); } Future<void> fetchGames() async { try { final response = await dio.get('https://api.yourdomain.com/games'); setState(() { games = (response.data['games'] as List) .map((json) => Game.fromJson(json)) .toList(); isLoading = false; }); } catch (e) { // Handle error print('Error fetching games: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Game Portal'), elevation: 2, ), body: isLoading ? Center(child: CircularProgressIndicator()) : GridView.builder( padding: EdgeInsets.all(16), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, childAspectRatio: 0.75, crossAxisSpacing: 16, mainAxisSpacing: 16, ), itemCount: games.length, itemBuilder: (context, index) { return GameCard( game: games[index], onTap: () => navigateToGame(games[index]), ); }, ), ); } void navigateToGame(Game game) { Navigator.push( context, MaterialPageRoute( builder: (context) => GamePlayerScreen(game: game), ), ); } } class GamePlayerScreen extends StatefulWidget { final Game game; GamePlayerScreen({required this.game}); @override _GamePlayerScreenState createState() => _GamePlayerScreenState(); } class _GamePlayerScreenState extends State<GamePlayerScreen> { late WebViewController controller; @override void initState() { super.initState(); controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..setBackgroundColor(Colors.black) ..setNavigationDelegate( NavigationDelegate( onProgress: (int progress) { // Update loading bar }, onPageFinished: (String url) { // Game loaded injectJavaScriptBridge(); }, ), ) ..addJavaScriptChannel( 'GameBridge', onMessageReceived: (JavaScriptMessage message) { // Handle game events handleGameEvent(message.message); }, ) ..loadRequest(Uri.parse(widget.game.gameUrl)); } void injectJavaScriptBridge() { controller.runJavaScript(''' window.addEventListener('gameready', function() { GameBridge.postMessage('ready'); }); window.addEventListener('gameover', function(e) { GameBridge.postMessage(JSON.stringify({ event: 'gameover', score: e.detail.score })); }); '''); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, body: SafeArea( child: WebViewWidget(controller: controller), ), ); } }