Wiring up an appBar action to a login page using Flutter

Build and publish a Flutter app for the App Store and Google Play — updated for 2026 with current Flutter conventions and navigation best practices.

Apps that open with a mandatory sign-in screen lose users fast. Tolerance for friction at launch has only fallen further in recent years, and app store reviewers increasingly flag poor onboarding as a reason for low ratings. Wherever possible, apps should deliver their core value to anonymous users first, and offer sign-in as an optional upgrade to a more personalised experience. Think of it as the commute test: can a user get what they need from your app in the time it takes to check their phone between stops? If a login wall is the first thing they see, the answer is almost certainly no.

TL:DR – Tuck your login page behind an AppBar action. Keep the main experience open and accessible. Sign-in should be an invitation, not a toll booth.

Why hide a login page behind an AppBar action?

Placing login behind an AppBar action button means it never blocks the primary user journey. Anonymous users get full access to whatever your app can offer without credentials, while signed-in users enjoy a richer, personalised layer on top. Neither group is penalised by the other's preferences.

A practical bonus: login fields have room to breathe on their own dedicated screen rather than being squeezed onto a cramped launch page. The result is a cleaner UI and a more considered experience for users who do choose to sign in.

In Flutter, every screen is a route. Routes are self-contained, composable, and easy to navigate between — making this pattern straightforward to implement regardless of your app's complexity.

What's changed in 2026

Since this series began, Flutter's navigation story has matured considerably. The original Navigator 1.0 API — using Navigator.pushNamed and a static routes map — remains fully supported and is still a perfectly reasonable choice for simple apps. However, Navigator 2.0 (the declarative Router API) and the widely adopted GoRouter package have become the community standard for anything beyond a handful of screens.

GoRouter, now maintained under the flutter/packages umbrella, offers deep linking, URL-based routing for Flutter Web, and typed routes out of the box. If you are starting a new project in 2026, GoRouter is worth evaluating from day one. That said, the named-route approach shown below is still the quickest path to a working prototype and is entirely appropriate for smaller apps.

Flutter itself has also moved on. Null safety is now the baseline — all code in this series assumes sound null safety and a current stable SDK. Material 3 (useMaterial3: true) is the default theme in new projects, which affects how the AppBar and its action icons render, but the routing logic below is unaffected by theme choice.

Add the routes

Open main.dart. Add an initialRoute and a routes map to your MaterialApp. In 2026 projects the MaterialApp will typically already have theme and debugShowCheckedModeBanner set — slot the routing properties in alongside those.

MaterialApp(
  title: 'My App',
  debugShowCheckedModeBanner: false,
  theme: ThemeData(
    colorSchemeSeed: Colors.indigo,
    useMaterial3: true,
  ),
  initialRoute: '/',
  routes: {
    '/': (context) => const HomeScreen(),
    '/profile': (context) => const ProfileScreen(),
  },
);

Note the const constructors — these are idiomatic in modern Flutter and help the framework avoid unnecessary rebuilds.

Wire up the AppBar action

With the routes registered, update your AppBar's actions list to push the profile route when the icon is tapped. A person or account icon is conventional here and immediately communicates intent to the user.

AppBar(
  title: const Text('Home'),
  actions: [
    IconButton(
      icon: const Icon(Icons.account_circle_outlined),
      tooltip: 'Sign in / Profile',
      onPressed: () {
        Navigator.pushNamed(context, '/profile');
      },
    ),
  ],
),

Because the ProfileScreen is pushed onto the navigation stack inside a Scaffold, Flutter automatically provides a back arrow in the AppBar — no manual Navigator.pop(context) required. You can still add a pop call to a custom button if your design calls for it, but the default behaviour covers most cases cleanly.

Adapting this pattern for GoRouter

If your project is already using GoRouter, the same intent maps neatly onto its API. Replace the routes map with a GoRouter instance and swap Navigator.pushNamed for context.push:

final _router = GoRouter(
  routes: [
    GoRoute(path: '/', builder: (context, state) => const HomeScreen()),
    GoRoute(path: '/profile', builder: (context, state) => const ProfileScreen()),
  ],
);

// In your AppBar action:
onPressed: () {
  context.push('/profile');
},

The user experience is identical, but you gain deep-link support and web-compatible URLs with minimal extra effort.

Keeping the login page honest

Once the routing is wired up, the ProfileScreen itself should do one simple job: check whether the user is already authenticated and render either a sign-in form or a profile summary accordingly. In 2026 the most common approach is to listen to an auth state stream — whether from Firebase Auth, Supabase, or a custom backend — and use a StreamBuilder or a state-management solution such as Riverpod to drive the UI reactively.

The key principle remains what it always was: users who are already signed in should never be shown a login form. Persist the session, restore it on app launch, and only ask for credentials when there genuinely are none.

Next steps

At this point the routing skeleton is in place but the ProfileScreen is still empty. The next part of this series adds the sign-in form itself — text fields, validation, and connecting to an auth provider — while keeping the screen lightweight enough to feel fast on first open.