RemixRemix

Build a settings screen

Use Remix CLI recipes to build, customize, and test a Flutter settings screen

Build Launchpad, a desktop-browser settings screen with a form, save state, dialog, and sidebar. You write the application; the CLI installs editable component recipes and their theme.

Launchpad with the Vanilla preset and a cyan preview button

The finished screenshot includes the medium Button height edit below. It is an application example, not a screen the CLI generates for you.

This walkthrough includes the complete application and test source below. The sample download contains both projects, generated adapters, and four behavior tests per preset.

Before you start

Use Flutter 3.44.0, its bundled Dart 3.12.0, Git, and a desktop browser. The samples use local state, with no backend or responsive mobile layout.

The September 7, 2026 captures used checkout bfae6507676fadea7632e2f7f66924935c04ca2a, with Remix 1.0.0-beta.9 and CLI 0.1.0. These are recorded checkout versions, not a claim that those packages are published. Keep the pin when reproducing the screenshots. That pinned CLI calls the compact preset default; current releases call the same preset vanilla. The commands below retain default so the recorded walkthrough remains reproducible.

Prepare the project and CLI

In the directory where you keep applications:

flutter create --empty --platforms=web remix_default_demo
cd remix_default_demo

In a second terminal, get the reviewed Remix checkout:

git clone https://github.com/btwld/remix.git remix-review
git -C remix-review checkout bfae6507676fadea7632e2f7f66924935c04ca2a
git -C remix-review rev-parse --show-toplevel

Use the printed absolute path in place of /path/to/remix below. Back in remix_default_demo, create pubspec_overrides.yaml:

dependency_overrides:
  remix:
    path: /path/to/remix/packages/remix

Then install the checkout CLI as a project-local development dependency:

dart pub add "dev:remix_cli@{path: /path/to/remix/packages/remix_cli}"
dart run remix_cli:remix --version

The version should be 0.1.0. Keep running CLI commands from the sample's package root, beside pubspec.yaml.

Initialize and install Button

dart run remix_cli:remix init --prefix Acme --preset default

Acme controls local names such as AcmeButton and acmeButtonStyle. Initialization writes remix.yaml and a managed barrel at lib/ui/ui.dart. It does not install a component yet.

Preview the first install:

dart run remix_cli:remix add button --dry-run

The plan should install theme before button. No source is written by --dry-run. Install when the plan matches:

dart run remix_cli:remix add button

Inspect lib/ui/components/button.dart, the recipe you own, and button.g.dart, the adapter produced by the generator. Edit the recipe, not the generated file. The CLI also adds the required dependencies and exports.

Render the first button

Replace lib/main.dart with this complete example:

import 'package:flutter/widgets.dart';

import 'ui/ui.dart';

void main() => runApp(const AcmeApp());

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

  @override
  Widget build(BuildContext context) {
    return WidgetsApp(
      color: const Color(0xFF000000),
      builder: (_, _) => Overlay(
        initialEntries: [
          OverlayEntry(
            builder: (_) => const AcmeThemeScope(
              theme: AcmeThemeData.light(),
              child: HomePage(),
            ),
          ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final theme = AcmeTheme.of(context);
    return ColoredBox(
      color: theme.background,
      child: Center(
        child: AcmeButton.primary(
          label: 'Continue',
          onPressed: () {},
        ),
      ),
    );
  }
}
flutter run -d chrome

The default Continue button on a white surface

You should see Continue centered in the app. Its callback is deliberately empty at this stage. Keep this terminal open; use another terminal in the same sample directory for the remaining CLI commands.

Build the settings screen

Install the remaining recipes, one item per command:

dart run remix_cli:remix add checkbox
dart run remix_cli:remix add textfield
dart run remix_cli:remix add dialog
dart run remix_cli:remix add card
dart run remix_cli:remix add sidebar
dart run remix_cli:remix add sidebar_layout

The existing theme is preserved. Sidebar also installs its toggle and tooltip dependencies. Sidebar Layout is a plain shell layout — no Spec, no generated adapter — that pairs an installed sidebar with a header and body, switching to a start-edge sheet below its compact breakpoint. Each command updates the barrel and generates the needed adapters.

Replace your application's lib/main.dart with the complete Vanilla source below. The same file is default_demo/lib/main.dart in the reviewed samples. Keep your CLI-installed lib/ui files; the next step changes one of them.

The complete app owns the form values, save counter, loading flag, dialog result, and sidebar selection. It uses WidgetsApp with a Navigator as the application host. Keep its host builder and scope placement together: the text field needs an overlay, and the dialog needs the invoking context's navigator and text defaults.

Customize your recipe

Open lib/ui/components/button.dart. In _metricsFor, change the medium minHeight from 36.0 to 44.0. Reload the app. All medium default buttons should use the taller recipe, while the cyan preview button keeps its instance-specific colors and rounded shape.

The application-owned recipe with minHeight set to 44.0

This changes a recipe value, not the generated widget signature. If you change recipe parameters, enums, or annotations, regenerate the adapter as described in the customization reference.

Check behavior and preserve edits

  1. Reload to reset local state. Enter Launchpad Studio as the workspace name.
  2. Clear Send a weekly summary, then press Save changes twice while loading.
  3. Confirm Save count: 1 and Summary: off when the save completes.
  4. Open and confirm the invitation dialog. Check that its result reaches the screen.
  5. Change the sidebar selection and test the preview button's callback.

Saved form values with one completed save and summary off

Now compare your edited Button with its bundled recipe:

dart run remix_cli:remix add button --diff

The diff's current side contains your 44.0 edit; proposed contains the bundled 36.0. The command does not replace your source. Repeat ordinary add:

dart run remix_cli:remix add button

Confirm the medium height remains 44.0. --overwrite is an explicit replacement operation; do not use it to inspect an update. See source-preservation details before trying it.

Try Fortal separately

Do not switch the Vanilla project's preset. From its directory, create a second application:

cd ..
flutter create --empty --platforms=web remix_fortal_demo
cd remix_fortal_demo

Repeat the checkout override and CLI installation from the first step in this new project. Then initialize Fortal and install its recipes:

dart run remix_cli:remix init --prefix Acme --preset fortal
dart run remix_cli:remix add button
dart run remix_cli:remix add checkbox
dart run remix_cli:remix add textfield
dart run remix_cli:remix add dialog
dart run remix_cli:remix add card
dart run remix_cli:remix add sidebar
dart run remix_cli:remix add sidebar_layout

Replace this app's lib/main.dart with the complete Fortal source below, also available as fortal_demo/lib/main.dart in the download.

The Fortal example uses AcmeScope and AcmeButton.solid, rather than AcmeThemeScope and AcmeButton.primary. Keep its complete host configuration. Do not apply the Vanilla preset's Button metrics edit to Fortal.

The Fortal settings screen in dark mode

Fortal supplies a different theme and recipe vocabulary, not a second runtime for your form. Repeat the same behavior checks. Neither preset adds a remix_fortal package dependency to the consumer application.

Run the tests

Copy test/workflow_test.dart from the matching downloaded project into each sample. Keep the project names used above; the tests import those names.

Replace analysis_options.yaml with the reviewed configuration:

include: package:flutter_lints/flutter.yaml

analyzer:
  exclude:
    - lib/ui/**/*.g.dart

This excludes generated adapters from the pinned generator's lint findings, not your authored recipes. Run from each sample directory:

flutter analyze
flutter test
flutter build web --release

Each sample has four tests covering form/save behavior, disabled controls, callbacks, dialog results and text decoration, and sidebar selection. Fix failures before treating a screenshot as evidence that the sample works.

Troubleshooting and evidence

  • Pub cannot resolve beta.10: check the absolute checkout path in pubspec_overrides.yaml.
  • Missing generated class: inspect the add command's generation error and the recipe's part declaration.
  • Missing overlay or incorrect dialog text: restore the complete sample's application host and scope placement.
  • No primary constructor: use the Vanilla sample, which this pinned walkthrough selects as default, or the solid constructor with fortal.

See the Open Code reference for configuration and command details.

Screenshots were captured from Flutter release web builds and an editor during the September 7 review. They show desktop states, not certification of all components or platforms. Recorded evidence tracks their hashes and source checkout. Assets and evidence remain alongside this documentation. Source panels above are expanded from the same archive during the documentation build, not maintained as separate copies.

View page source on GitHub

On this page