flutter-setup-declarative-routing

Навигация и прямые ссылки во Flutter

flutter/agent-pluginsОт разработчика платформы
3 048звёзд181форковУ всего репозитория

Что получите

Настроенная навигация Flutter по адресам, поддержка внешних ссылок и, при необходимости, вкладки с сохранением состояния.

Что передать

Проект Flutter, целевые платформы, домен, список экранов и правила доступа.

Автопроверка файлов

Проверен состав файлов. Запуск не тестировался. Что проверено

Оценки пользователей

Загрузка оценок…
Ваш опыт
Обсудить →

Как использовать

Помогает разработчикам Flutter настроить переходы между экранами по адресам и открытие нужного экрана из внешней ссылки. Подходит для веб-приложений с историей браузера и мобильных приложений с вложенной навигацией.

  1. Добавьте go_router и определите соответствие адресов экранам, включая параметры и перенаправления по состоянию входа.
  2. Настройте открытие ссылок для выбранных платформ и связь домена с мобильным приложением.
  3. Если есть вкладки, организуйте отдельные ветки с сохранением состояния и проверьте открытие ссылок на Android или iOS.

Условия работы

  • Используется пакет go_router; для веба источник предусматривает адреса без символа #.
  • Для Android и iOS нужно разместить на домене файлы, подтверждающие связь сайта с приложением, и настроить соответствующую платформу.
  • На iOS при использовании стороннего обработчика ссылок, например app_links, встроенный обработчик Flutter нужно отключить, чтобы избежать конфликта.

Пример запроса после установки

Настрой в нашем приложении Flutter открытие карточки товара по внешней ссылке на Android и iOS, сохранив состояние вкладок каталога и настроек.

Пример составлен по инструкции автора; результат запуска не проверялся.

Основание: инструкция закреплённой версии

Для установки

Node.js, npm и Git для команды выше. Подключения и инструменты для работы скилла настраиваются отдельно.

Совместимые агенты

Совместимость указана для инструкций. Запуск в каждом приложении не тестировался; для веб-чата способ подключения может отличаться.

Файлы скилла

GitHub
Читать инструкцию SKILL.md

Исходный текст закреплённой версии.

---
name: flutter-setup-declarative-routing
description: Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
metadata:
  model: models/gemini-3.1-pro-preview
  last_modified: Tue, 21 Apr 2026 21:08:03 GMT
---
# Implementing Routing and Deep Linking

## Contents
- [Core Concepts](#core-concepts)
- [Workflow: Initializing the Application and Router](#workflow-initializing-the-application-and-router)
- [Workflow: Configuring Platform Deep Linking](#workflow-configuring-platform-deep-linking)
- [Workflow: Implementing Nested Navigation](#workflow-implementing-nested-navigation)
- [Examples](#examples)

## Core Concepts

Use the `go_router` package for declarative routing in Flutter. It provides a robust API for complex routing scenarios, deep linking, and nested navigation. 

- **GoRouter**: The central configuration object defining the application's route tree.
- **GoRoute**: A standard route mapping a URL path to a Flutter screen.
- **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., a `BottomNavigationBar`). `StatefulShellRoute` maintains the state of parallel navigation branches.
- **Path URL Strategy**: Removes the default `#` fragment from web URLs, essential for clean deep linking across platforms.

## Workflow: Initializing the Application and Router

Follow this workflow to bootstrap a new Flutter application with `go_router` and configure the root routing mechanism.

### Task Progress
- [ ] Create the Flutter application.
- [ ] Add the `go_router` dependency.
- [ ] Configure the URL strategy for web/deep linking.
- [ ] Implement the `GoRouter` configuration.
- [ ] Bind the router to `MaterialApp.router`.

### 1. Scaffold the Application
Run the following commands to create the app and add the required routing package:
```bash
flutter create <app-name>
cd <app-name>
flutter pub add go_router
```

### 2. Configure the Router
Define a top-level `GoRouter` instance. Handle authentication or state-based routing using the `redirect` parameter.

```dart
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter_web_plugins/url_strategy.dart';

void main() {
  // Use path URL strategy to remove the '#' from web URLs
  usePathUrlStrategy();
  runApp(const MyApp());
}

final GoRouter _router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomeScreen(),
      routes: [
        GoRoute(
          path: 'details/:id',
          builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
        ),
      ],
    ),
  ],
  errorBuilder: (context, state) => ErrorScreen(error: state.error),
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
      title: 'Routing App',
    );
  }
}
```

## Workflow: Configuring Platform Deep Linking

Configure the native platforms to intercept specific URLs and route them into the Flutter application.

### Task Progress
- [ ] Determine target platforms (iOS, Android, or both).
- [ ] Apply conditional configuration for Android (Manifest + Asset Links).
- [ ] Apply conditional configuration for iOS (Plist + Entitlements + AASA).
- [ ] Run validator -> review errors -> fix.

### If configuring for Android:
1. **Modify `AndroidManifest.xml`**: Add the intent filter inside the `<activity>` tag for `.MainActivity`.
```xml
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="http" android:host="yourdomain.com" />
    <data android:scheme="https" />
</intent-filter>
```
2. **Host `assetlinks.json`**: Serve the following JSON at `https://yourdomain.com/.well-known/assetlinks.json`.
```json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourcompany.yourapp",
    "sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
  }
}]
```

### If configuring for iOS:
1. **Modify `Info.plist`**: Opt-in to Flutter's default deep link handler. 
*Note: If using a third-party deep linking plugin (e.g., `app_links`), set this to `NO` to prevent conflicts.*
```xml
<key>FlutterDeepLinkingEnabled</key>
<true/>
```
2. **Modify `Runner.entitlements`**: Add the associated domain.
```xml
<key>com.apple.developer.associated-domains</key>
<array>
  <string>applinks:yourdomain.com</string>
</array>
```
3. **Host `apple-app-site-association`**: Serve the following JSON (without a `.json` extension) at `https://yourdomain.com/.well-known/apple-app-site-association`.
```json
{
  "applinks": {
    "apps": [],
    "details": [{
      "appIDs": ["TEAM_ID.com.yourcompany.yourapp"],
      "paths": ["*"],
      "components": [{"/": "/*"}]
    }]
  }
}
```

### Validation Loop
Run validator -> review errors -> fix.
- **Android**: Test using ADB.
  ```bash
  adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp
  ```
- **iOS**: Test using `xcrun` on a booted simulator.
  ```bash
  xcrun simctl openurl booted https://yourdomain.com/details/123
  ```

## Workflow: Implementing Nested Navigation

Use `StatefulShellRoute` to implement persistent UI shells (like a bottom navigation bar) that maintain the state of their child routes.

### Task Progress
- [ ] Define `StatefulShellRoute.indexedStack` in the `GoRouter` configuration.
- [ ] Create `StatefulShellBranch` instances for each navigation tab.
- [ ] Implement the shell widget using `StatefulNavigationShell`.

```dart
final GoRouter _router = GoRouter(
  initialLocation: '/home',
  routes: [
    StatefulShellRoute.indexedStack(
      builder: (context, state, navigationShell) {
        return ScaffoldWithNavBar(navigationShell: navigationShell);
      },
      branches: [
        StatefulShellBranch(
          routes: [
            GoRoute(
              path: '/home',
              builder: (context, state) => const HomeScreen(),
            ),
          ],
        ),
        StatefulShellBranch(
          routes: [
            GoRoute(
              path: '/settings',
              builder: (context, state) => const SettingsScreen(),
            ),
          ],
        ),
      ],
    ),
  ],
);
```

## Examples

### High-Fidelity Shell Widget Implementation
Implement the UI shell that consumes the `StatefulNavigationShell` to handle branch switching.

```dart
class ScaffoldWithNavBar extends StatelessWidget {
  const ScaffoldWithNavBar({
    required this.navigationShell,
    super.key,
  });

  final StatefulNavigationShell navigationShell;

  void _goBranch(int index) {
    navigationShell.goBranch(
      index,
      // Support navigating to the initial location when tapping the active tab.
      initialLocation: index == navigationShell.currentIndex,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: navigationShell,
      bottomNavigationBar: NavigationBar(
        selectedIndex: navigationShell.currentIndex,
        onDestinationSelected: _goBranch,
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
        ],
      ),
    );
  }
}
```

### Programmatic Navigation
Use the `context.go()` and `context.push()` extension methods provided by `go_router`.

```dart
// Replaces the current route stack with the target route (Declarative)
context.go('/details/123');

// Pushes the target route onto the existing stack (Imperative)
context.push('/details/123');

// Navigates using a named route and path parameters
context.goNamed('details', pathParameters: {'id': '123'});

// Pops the current route
context.pop();
```

Проверка и особенности

Автоматическая проверка источника и файлов

Автоматически проверены публичный репозиторий, лицензия, заголовок SKILL.md, состав текстового пакета и Git-хеш каждого файла. Пакеты с исполняемыми файлами и срабатываниями применённых статических правил не включены. Ручной аудит всех инструкций и функциональный запуск не проводились. Внешние инструменты и сервисы не проверялись. Проверка не гарантирует безопасность.

В публичном списке установок на 2026-10-09 у скилла было 35 045 установок. Порог отбора — 1 000 установок. Число установок показывает распространённость, а не качество или безопасность инструкции.

Есть ссылки на внешние инструкции или инструменты: их содержимое и доступность могут изменяться отдельно от скилла.

Проверка состава
09.10.2026
Проверенная версия
0ef3972f93e2
Файлы с кодом
Не указаны в данных проверки
Изменения на GitHub
Нужна повторная проверкаПоследняя проверка: 11.10.2026
Как мы проверяем скиллы

Репозиторий и лицензия

flutter/agent-plugins
3 048 звёзд181 форков

Это показатели всего репозитория, а не установки скилла. Снимок требует обновления.

Последняя активность GitHub
06.10.2026
Лицензия
BSD-3-Clause
Добавлен в каталог
09.10.2026
Полный текст лицензии
Copyright 2026 The Flutter Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors
   may be used to endorse or promote products derived from this software without
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Ещё в этой категории

Все в категории

Обсуждение

Правила

Пользовались этим скиллом? Делитесь опытом без регистрации. Все комментарии проверяет модератор.

Мои комментарии