# Web Navigation Use this reference when fixing Flutter web URLs, browser history, refresh/direct load behavior, server rewrites, or non-root hosting. ## URL Strategies Flutter web supports two URL strategies: ### Hash Strategy ```text https://example.com/#/path/to/screen ``` Use it when you cannot configure the web server. Hash URLs avoid server rewrites because the route after `#` is not sent to the server. ### Path Strategy ```text https://example.com/path/to/screen ``` Use it when you control server rewrites and want clean, shareable paths. ```dart import 'package:flutter_web_plugins/url_strategy.dart'; void main() { usePathUrlStrategy(); runApp(const App()); } ``` `flutter_web_plugins` is an SDK dependency: ```yaml dependencies: flutter: sdk: flutter flutter_web_plugins: sdk: flutter ``` Call `usePathUrlStrategy()` before `runApp()`. ## Server Rewrites Path strategy uses the browser History API. Configure the server to serve `index.html` for app routes that are not real files. ### Nginx ```nginx location / { try_files $uri $uri/ /index.html; } ``` ### Apache ```apache RewriteEngine On RewriteBase / RewriteRule ^index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.html [L] ``` ### Firebase Hosting ```json { "hosting": { "public": "build/web", "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } ``` ### Vercel ```json { "rewrites": [ { "source": "/(.*)", "destination": "/index.html" } ] } ``` ### Netlify ```text /* /index.html 200 ``` ## Browser History Router-based navigation, including `go_router`, integrates with the browser URL and History API for direct loads, refresh, back, and forward behavior. Prefer canonical route state with `context.go(location)` for browser-visible navigation. `context.push(location)` is useful for page-stack style flows, but imperative navigation can be harder to reason about in browser history. Build locations with query parameters using `Uri`: ```dart context.go( Uri( path: '/search', queryParameters: {'q': query}, ).toString(), ); ``` ## Hosting At A Non-Root Path If the app is hosted at `https://example.com/myapp/`, update the base href in `web/index.html`: ```html ``` Keep app route paths app-relative unless the target project already includes the deployment prefix in routes: ```dart GoRouter( routes: [ GoRoute(path: '/', builder: (context, state) => const HomeScreen()), GoRoute(path: '/details/:id', builder: (context, state) => const DetailsScreen()), ], ); ``` Configure the hosting server so `/myapp/details/42` rewrites to the built `index.html` for that deployed app. ## Not Found And Error Routes For public web URLs, define a deliberate not-found or error surface: ```dart GoRouter( errorBuilder: (context, state) => NotFoundScreen(error: state.error), routes: [ // ... ], ); ``` Validate bad routes and malformed parameters. Do not let a bad URL crash during `int.parse`, forced casts, or missing path parameter access. ## Web Validation When feasible, run the app in Chrome and test: - direct load of `/`; - direct load of every changed route; - refresh on every changed route; - browser back and forward; - query parameter preservation; - unknown URL and malformed parameter behavior; - deployed non-root path if applicable. For production hosts, test after deployment as well as on the Flutter dev server. The dev server handles fallback routing automatically, while production hosting only works if rewrites are configured. ## Accessibility And Titles Navigation changes can affect focus, page announcements, and keyboard flow. After route changes, check that keyboard users can reach primary actions and that screen names, app bars, or semantic labels make the destination clear.