I have been searching around for ages online for an example of a flutter app that supports the following:
- Persistent bottom navigation bar
- Navigator support for each bottom navigation bar item that persists state
- Navigators update the URL in flutter web on navigation
- Navigators support hyperlinking to a specific page in flutter web. For example if a user types www.myappdomain.com/#/profile they get navigated to the profile page. Or they type www.myappdomain.com/#/profile?id=123 they get navigated to the profile page for user 123.
I've been able to achieve points 1 and 2 with the following code:
import 'package:flutter/material.dart';
void main() {
  runApp(BaseApp());
}
class BaseApp extends StatefulWidget {
  @override
  _BaseAppState createState() => _BaseAppState();
}
class _BaseAppState extends State<BaseApp> {
  // define all navigation tabs for user
  static List<NavigationTabModel> _navigationTabs = [
    NavigationTabModel(
      title: 'Home',
      icon: Icons.home,
      url: '/home',
      navigatorKey: GlobalKey<NavigatorState>(),
    ),
    NavigationTabModel(
      title: 'Search',
      icon: Icons.search,
      url: '/search',
      navigatorKey: GlobalKey<NavigatorState>(),
    ),
    NavigationTabModel(
      title: 'Profile',
      icon: Icons.person,
      url: '/profile',
      navigatorKey: GlobalKey<NavigatorState>(),
    ),
  ];
  // route generator used to build all material page routes
  RouteGenerator _routeGenerator = RouteGenerator();
  // set the current tab to the home page
  int _currentIndex = 0;
  void _select(int index) {
    if (index == _currentIndex) {
      // case 1 - if user presses on currently selected tab
      // pop to first route - i.e. ensure no routes are over laid on top of the current route
      _navigationTabs[_currentIndex]
          .navigatorKey
          .currentState
          .popUntil((route) {
        return route.isFirst;
      });
    } else {
      // case 2 - user selects any other tab
      // rebuild application state with the newly selected navigation tab
      setState(() {
        _currentIndex = index;
      });
    }
  }
  /// generate a list of navigators that will have their state persisted in an
  /// indexed stack.
  List<Widget> _getPersistantStack() {
    return _navigationTabs.map((tab) {
      return WillPopScope(
        onWillPop: () async {
          return !await tab.navigatorKey.currentState.maybePop();
        },
        child: Navigator(
          key: tab.navigatorKey,
          initialRoute: tab.url,
          onGenerateRoute: _routeGenerator.generateRoute,
        ),
      );
    }).toList();
  }
  @override
  Widget build(BuildContext context) {
    /// ********************* HOLD POINT *********************
    /// MaterialApp contains our top-level Navigator. Top level navigator is
    /// required to enable navigation via urls in flutter web. Likely that this
    /// section requires refractoring in some way to enable url updates from the
    /// nested navigators and hyperlinking from web browsers to specific pages
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SafeArea(
          child: IndexedStack(
            children: _getPersistantStack(),
            index: _currentIndex,
          ),
        ),
        bottomNavigationBar: BottomNavigationBar(
          items: _navigationTabs.map((tab) {
            return BottomNavigationBarItem(
              label: tab.title,
              icon: Icon(tab.icon),
            );
          }).toList(),
          onTap: (int index) {
            _select(index);
          },
          currentIndex: _currentIndex,
          type: BottomNavigationBarType.fixed,
          // hide titles on navigation bar
          showSelectedLabels: false,
          showUnselectedLabels: false,
        ),
      ),
    );
  }
}
class NavigationTabModel {
  final String title;
  final IconData icon;
  final String url;
  final GlobalKey<NavigatorState> navigatorKey;
  NavigationTabModel({
    this.title,
    this.icon,
    this.url,
    this.navigatorKey,
  });
}
class RouteGenerator {
  Route<dynamic> generateRoute(RouteSettings settings) {
    // Widget builder (function that returns a widget) to construct the route page
    WidgetBuilder builder;
    // build different route (page) based on the route passed to the navigator
    switch (settings.name) {
      case '/home':
        builder = (BuildContext context) {
          return SamplePage(name: 'home');
        };
        break;
      case '/search':
        builder = (BuildContext context) {
          return SamplePage(name: 'search');
        };
        break;
      case '/profile':
        builder = (BuildContext context) {
          return SamplePage(name: 'profile');
        };
        break;
      case '/':
        builder = null;
        break;
      default:
        // If there is no such named route in the switch statement
        builder = (BuildContext context) {
          return SamplePage();
        };
    }
    // prevent page being added to default '/' route
    if (builder == null) {
      return null;
    }
    return MaterialPageRoute(
      builder: builder,
      settings: settings,
    );
  }
}
class SamplePage extends StatelessWidget {
  final String name;
  SamplePage({
    this.name,
  });
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('$name'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            RaisedButton(
              child: Text('push new route'),
              onPressed: () {
                Navigator.of(context).pushNamed('/$name');
              },
            ),
            SizedBox(
              height: 16,
            ),
            Expanded(
              child: ListView.builder(
                itemCount: 100,
                itemBuilder: (context, index) {
                  return Card(
                    child: Text(
                      index.toString(),
                    ),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
However I cannot figure out how to update this app to achieve points 3 and 4. Does anyone know how this can be achieved?
 
     
     
     
    