Back to list
gsmlg-app

project-screen

by gsmlg-app

Flutter Application Template for AI coder

1🍴 0📅 Jan 19, 2026

SKILL.md


name: project-screen description: Guide for creating screens with routing conventions (name/path constants) and adaptive scaffold (project)

Flutter Screen Development Skill

This skill guides the creation of screens following this project's routing and layout conventions.

When to Use

Trigger this skill when:

  • Creating a new screen or page
  • Adding a route to the application
  • User asks to "create a screen", "add a page", or "implement a new view"

Mason Template

Always use Mason template first:

# Basic screen with optional subfolder
mason make screen --name ScreenName --folder subfolder

# Options available:
# --has_adaptive_scaffold: Use AppAdaptiveScaffold (default: true)
# --has_app_bar: Include SliverAppBar (default: true)

Project Structure

Screens are organized in lib/screens/ by domain:

lib/screens/
├── app/                    # App-level screens (splash, error)
│   ├── splash_screen.dart
│   └── error_screen.dart
├── home/                   # Home feature
│   └── home_screen.dart
├── settings/               # Settings feature
│   ├── settings_screen.dart
│   ├── appearance_settings_screen.dart
│   └── accent_color_settings_screen.dart
└── showcase/               # Demo/example screens
    └── showcase_screen.dart

Routing Convention (MANDATORY)

Every screen MUST define static route constants:

class ProfileScreen extends StatelessWidget {
  static const name = 'Profile Screen';  // Display name
  static const path = '/profile';         // GoRouter path

  const ProfileScreen({super.key});
  // ...
}

Screen Template

import 'package:app_adaptive_widgets/app_adaptive_widgets.dart';
import 'package:app_locale/app_locale.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app_template/destination.dart';

class ExampleScreen extends StatelessWidget {
  static const name = 'Example Screen';
  static const path = '/example';

  const ExampleScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return AppAdaptiveScaffold(
      selectedIndex: Destinations.indexOf(const Key(ExampleScreen.name), context),
      onSelectedIndexChange: (idx) => Destinations.changeHandler(idx, context),
      destinations: Destinations.navs(context),
      appBar: AppBar(
        title: Text(context.l10n.screenTitle),
        centerTitle: true,
        foregroundColor: Theme.of(context).colorScheme.onPrimary,
        backgroundColor: Theme.of(context).colorScheme.primary,
      ),
      body: (context) => SafeArea(
        child: Center(
          child: Text('Screen content'),
        ),
      ),
    );
  }
}

Router Integration

After creating a screen, add it to lib/router.dart:

GoRoute(
  name: ExampleScreen.name,
  path: ExampleScreen.path,
  pageBuilder: (context, state) => NoTransitionPage(
    key: state.pageKey,
    child: const ExampleScreen(),
  ),
),

For screens in the main navigation, update lib/destination.dart:

static List<NavigationDestination> navs(BuildContext context) {
  return [
    // existing destinations...
    NavigationDestination(
      key: Key(ExampleScreen.name),
      icon: const Icon(Icons.example),
      label: context.l10n.example,
    ),
  ];
}

Key Dependencies

import 'package:app_adaptive_widgets/app_adaptive_widgets.dart';  // Responsive layout
import 'package:app_locale/app_locale.dart';                      // Localization
import 'package:app_artwork/app_artwork.dart';                    // Icons, animations
import 'package:flutter_app_template/destination.dart';           // Navigation

AppAdaptiveScaffold Features

Responsive Body Slots

AppAdaptiveScaffold(
  // Main body - used for medium+ breakpoints
  body: (context) => MainContent(),

  // Small screen body (mobile)
  smallBody: (context) => MobileContent(),

  // Medium-large screen body (tablet)
  mediumLargeBody: (context) => TabletContent(),

  // Large screen body (desktop)
  largeBody: (context) => DesktopContent(),

  // Extra large screen body
  extraLargeBody: (context) => WideDesktopContent(),
)

Secondary Body (Split View)

AppAdaptiveScaffold(
  body: (context) => ListView(...),

  // Secondary panel (detail view)
  secondaryBody: (context) => DetailView(),

  // Hide secondary on small screens
  smallSecondaryBody: AdaptiveScaffold.emptyBuilder,

  // Body to secondary ratio (0.3 = 30% body, 70% secondary)
  bodyRatio: 0.3,

  // Orientation of split
  bodyOrientation: Axis.horizontal, // or Axis.vertical
)

Collapsible Navigation Rail

AppAdaptiveScaffold(
  // Enable collapse toggle button
  showCollapseToggle: true,

  // Custom icons for toggle
  collapseIcon: Icons.menu_open,
  expandIcon: Icons.menu,

  // Control extended state externally
  isExtendedOverride: isNavExtended,

  // Listen for state changes
  onExtendedChange: (isExtended) {
    setState(() => isNavExtended = isExtended);
  },
)
AppAdaptiveScaffold(
  // Leading widget (collapsed state)
  leadingUnextendedNavRail: Icon(Icons.menu),

  // Leading widget (extended state)
  leadingExtendedNavRail: Text('My App'),

  // Trailing widget below destinations
  trailingNavRail: IconButton(icon: Icon(Icons.logout), onPressed: logout),

  // Rail width
  navigationRailWidth: 72,
  extendedNavigationRailWidth: 192,

  // Destination alignment
  groupAlignment: -1.0, // Top aligned
)

Drawer Configuration

AppAdaptiveScaffold(
  // Use drawer instead of bottom nav on small desktop
  useDrawer: true,

  // Custom breakpoint for drawer
  drawerBreakpoint: Breakpoints.smallDesktop,

  // Custom app bar when using drawer
  appBar: AppBar(title: Text('My App')),

  // Breakpoint to show app bar
  appBarBreakpoint: Breakpoints.small,
)

Breakpoints Reference

  • Breakpoints.small - Mobile (< 600px)
  • Breakpoints.medium - Tablet (600-840px)
  • Breakpoints.mediumLarge - Small desktop (840-1200px)
  • Breakpoints.large - Desktop (1200-1600px)
  • Breakpoints.extraLarge - Wide desktop (> 1600px)

AppAdaptiveAction (Responsive Action Buttons)

For action buttons that adapt to screen size:

// Define actions
final actions = [
  AppAdaptiveAction(
    title: 'Edit',
    icon: Icons.edit,
    onPressed: () => handleEdit(),
  ),
  AppAdaptiveAction(
    title: 'Delete',
    icon: Icons.delete,
    onPressed: () => handleDelete(),
    disabled: !canDelete,
  ),
];

// Display in AppBar or elsewhere
AppAdaptiveActionList(
  actions: actions,
  size: AppAdaptiveActionSize.medium, // small, medium, large
  direction: Axis.horizontal,
  hideDisabled: true,
)

Action Sizes:

  • small - Popup menu (overflow menu)
  • medium - Icon buttons only
  • large - Text buttons with icons

Localization

Add screen text to app_lib/locale/lib/l10n/app_en.arb:

{
  "exampleTitle": "Example",
  "@exampleTitle": {
    "description": "Title for the example screen"
  }
}

Then run: melos run gen-l10n

Testing

Create screen tests in test/screens/:

testWidgets('ExampleScreen renders correctly', (tester) async {
  await tester.pumpWidget(
    MaterialApp(home: ExampleScreen()),
  );
  expect(find.text('Example'), findsOneWidget);
});

Run tests: flutter test test/screens/example_screen_test.dart

Score

Total Score

55/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon