Skip to content

Getting started

  1. Add the runtime dependencies to your Flutter project

    Terminal window
    flutter pub add solid_annotations flutter_solidart provider

    flutter_solidart is the state-management runtime that backs Solid’s reactive primitives, and provider is the dependency-injection plumbing for @SolidEnvironment. You don’t have to learn either directly — Solid generates the boilerplate that uses them — but they appear in the generated lib/ output, so they need to be in your pubspec.

  2. Add the generator and build_runner as dev dependencies

    Terminal window
    dart pub add --dev solid_generator build_runner

    Solid ships as a build_runner builder — there is no separate CLI to install.

  3. Update (or create) build.yaml at the project root so build_runner watches the source/ folder. Most projects already have a build.yaml from other generators (freezed, json_serializable, …); just add source/** to the existing sources list. New projects can drop the file in as-is:

    build.yaml
    targets:
    $default:
    sources:
    - source/**
    - lib/**
    - $package$
  4. I’d also suggest installing the very_good_analysis package to get amazing linting rules for your Flutter project.

    Terminal window
    flutter pub add dev:very_good_analysis

    Then in your analysis_options.yaml file, add the following line

    analysis_options.yaml
    include: package:very_good_analysis/very_good_analysis.yaml

    This is an example of an analysis_options.yaml file

    analysis_options.yaml
    include: package:very_good_analysis/analysis_options.yaml
    analyzer:
    errors:
    must_be_immutable: ignore # Ignore immutability rule, because Solid generates immutable classes but you write mutable ones
    linter:
    rules:
    public_member_api_docs: false # Disable documentation requirement for public members
    # Same-package imports must be relative — `package:<self>/…` resolves to `lib/`,
    # the generated realm, which is the wrong target for an authored file.
    always_use_package_imports: false
    prefer_relative_imports: true

If you’re using an AI coding assistant (Claude Code, Cursor, Codex, GitHub Copilot, Amp, OpenHands, etc.), these three steps teach it the inverted source/-vs-lib/ rule and Solid’s annotation contract — so it stops trying to edit lib/ and silently losing your work.

  1. Drop AGENTS.md at your app root.

    Most AI coding tools auto-load AGENTS.md at session start, so the rule applies to every interaction — even short or routine-looking ones — without depending on skill triggering.

    Terminal window
    curl -o AGENTS.md https://raw.githubusercontent.com/nank1ro/solid/main/skills/solid/assets/AGENTS.md

    If your tool only looks for CLAUDE.md, symlink it:

    Terminal window
    ln -s AGENTS.md CLAUDE.md
  2. Install the Solid skill.

    Terminal window
    npx skills add nank1ro/solid

    Or copy skills/solid/ from the Solid repo into your editor’s skill location. The skill gives the agent deeper guidance (full annotation contract, scripts, troubleshooting) when it triggers on Solid-related work. AGENTS.md is the always-loaded baseline; the skill is the on-demand reference.

  3. Point HTTP-docs tools at the LLM-friendly bundle (optional).

    If your tool fetches documentation over HTTP (Cursor @docs, ChatGPT custom GPTs, claude.ai web search, …), point it at /llms-full.txt — the full docs as a single LLM-friendly file. A short index lives at /llms.txt.

The code you write is the source of truth, and Solid generates the boilerplate code needed to make the app working.

There is an important difference between writing normal Flutter code and writing Solid code: In Flutter, the lib folder is the source of truth, while in Solid, the source folder is the source of truth.

You never have to edit the lib folder manually, as it is generated by Solid.

I decided not to use the lib folder directly because I don’t want to touch the original files, but I wanted to keep the same naming and structure, without adding complexity to you like part files or similar.

I wanted to use lib as the input folder, but flutter build doesn’t allow building (as far as I know) an app from a different folder than lib.

In addition, Solid is not a common generator because it transpiles your existing code to an optimized version of it.

To ensure Solid properly manages the lifecycle of your reactive atoms, configure flutter_solidart in your app’s main() function:

source/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_solidart/flutter_solidart.dart';
import 'counter.dart';
void main() {
SolidartConfig.autoDispose = false;
runApp(const MaterialApp(home: CounterPage()));
}

Setting SolidartConfig.autoDispose = false tells the library to let Solid manage disposal of reactive atoms manually, rather than automatically disposing them when they go out of scope.

Run the generator with build_runner:

Terminal window
# one-shot build
dart run build_runner build --delete-conflicting-outputs
# watch mode (recommended during development)
dart run build_runner watch --delete-conflicting-outputs

flutter run does not auto-reload when build_runner rewrites files under lib/, because no IDE save event fires for filesystem changes. There are two supported workflows:

  • Press r in the flutter run terminal after build_runner emits.
  • Use dashmonx, which wraps flutter run and triggers hot reload automatically when files under lib/ change. Any flutter run flag passes through, e.g. dashmonx -d chrome for a web target.

Solid prioritises producing correct, runnable code over polishing it. The generated lib/ output may miss some const opportunities, leave unused imports, or pick a non-preferred import form. Run dart fix after build_runner to apply the lint-driven fixes (prefer_const_constructors, unnecessary_import, prefer_relative_imports, …):

Terminal window
dart fix --apply

In CI, chain the two commands so the generated output is always lint-clean:

Terminal window
dart run build_runner build --delete-conflicting-outputs
dart fix --apply