Skip to main content

beej 0.1.0 copy "beej: ^0.1.0" to clipboard
beej: ^0.1.0 copied to clipboard

Plants a new Flutter app — material_ui, Riverpod, go_router, en/ne localization, theming, fastlane and the store-screenshot harness, with Appwrite, sqflite and the rest as explicit choices.

beej #

बीज — plant a new Flutter app.

A Dart CLI that generates a complete, buildable Flutter project: material_ui, Riverpod, routing, localization, theming with live personalization, an About module, release tooling and agent config — with the parts that genuinely differ left as explicit choices.

It is opinionated rather than general-purpose. The opinions came from thirteen production Flutter apps that had converged on one stack but drifted into five lib/ layouts, four analyzer configs and four localization setups. Defaults are neutral (com.example, English), and beej config is where you make them yours.

dart pub global activate --source git https://github.com/lohanidamodar/beej.git

beej config set org com.acme            # once, not per project
beej create tipot                       # interactive
beej create tipot --yes                 # take every default
beej create --spec app.yaml             # from a file
beej create tipot --yes --dry-run       # show the plan, write nothing

What you always get #

  • material_ui — Material decoupled from the Flutter SDK. Nothing under lib/ imports package:flutter/material.dart, and a generated test fails the build if that ever changes.
  • Riverpod 3, no code generation.
  • Localization in lib/l10n/ — English and Nepali, actually translated.
  • Theming from design tokens, with working personalization: accent colour, theme mode, language and text size, persisted and applied before the first frame.
  • The About module — privacy policy, open-source licences, share, rate, more apps, contact support — wired into routes and the settings list.
  • Error capture — FlutterError.onError, PlatformDispatcher.onError and a guarded zone around main, feeding a deduplicated, size-capped on-device log and a Diagnostics screen the user can share. It stays on the device: a shipped app that cannot see its own runtime failures is guessing, and the worst material_ui failures never reach flutter analyze.
  • Responsive helpers, shared UI (AsyncView, EmptyView, ErrorView, SectionLabel, context.toast, context.confirm), and a Launcher for every hand-off to another app.
  • PROJECT.md as the single guide, with CLAUDE.md and AGENTS.md pointing at it — scope, workflow, conventions, the responsive contract, a testing strategy and a done-checklist.
  • Agent skills in .claude/skills/: material-ui (the frozen-vs-modern Material traps), store-readiness (will the submission be accepted), app-store-optimization (will the listing be found and installed), and mobile-ui-design.
  • CI on day one — .github/workflows/ci.yml runs flutter analyze and flutter test on every push and pull request, so the generated guards actually hold. Releasing stays separate and manual.
  • Store screenshots as a workflow — manual workflows capture on a matching emulator or simulator, render with moksha, and open a PR. One renderer covers Play phone and tablet plus iPhone and iPad, from one committed copy file, so the listings look like the same app. Every image is checked against the store's upload rules first — an alpha channel, Play's 2:1 aspect limit and Apple's accepted dimensions each reject a perfectly valid PNG, and all three now fail in CI instead of at upload.
  • Agent tooling: .mcp.json declaring the Dart MCP server (it ships inside the Dart SDK, so nothing to install) plus Appwrite's hosted server when that backend is on, and project-scoped skills under .claude/skills/. Turn it all off with --no-agent-config, or narrow it with --skills=material-ui.

What you choose #

Option Values Default
org reverse-DNS prefix com.example
locales en plus any of ne en
platforms android, ios, web, windows, macos, linux all
backend appwrite, none none
router go_router, navigator go_router
nav tabs, drawer, tabs+drawer tabs+drawer
database sqflite, none none
icons picons, material picons
features.inAppUpdate bool true
features.notifications bool false
features.nepaliDates bool false
features.review bool true
tooling.fastlane bool true
tooling.githubWorkflow bool true
tooling.screenshots bool true
agents.mcp bool true
agents.skills all / none / list all

beej bricks lists what each contributes.

Making it yours #

beej ships neutral defaults — com.example, English only, no About URLs — so it is useful to anyone. beej config is where you set yours once instead of passing the same flags to every create:

beej config                    # show current settings and their file
beej config keys               # everything settable
beej config set org com.acme
beej config set locales en,ne
beej config set about.privacyPolicyUrl https://acme.com/{name-kebab}-privacy
beej config unset locales      # back to the built-in default

The file is $XDG_CONFIG_HOME/beej/config.yaml (%APPDATA%\beej on Windows), overridable with BEEJ_CONFIG. It is a spec file without a name, so it accepts exactly the same keys as --spec and is hand-editable.

About URLs accept {name} and {name-kebab}, expanded per project — which is what makes a per-app privacy-policy URL storable as a one-time preference.

Anything you do not set is simply absent: an About row is generated only when its value exists, because a row linking nowhere is worse than no row. beej warns when no privacy-policy URL is configured, since both stores require one before release.

Resolution order: built-in defaults < config < spec file < flags.

For agents #

beej spec --schema     # JSON Schema for the spec file
beej spec --example    # annotated example
beej create --spec app.yaml --yes

Precedence is flag > spec file > prompt > default. --yes never prompts, so it is safe in a script. --dry-run prints the resolved plan and writes nothing.

How it works #

flutter create produces the platform folders, then bricks render template files over that skeleton. Bricks are additive — a feature that is off simply never contributes. Three registries in the generated app are the seams a feature extends: core/bootstrap.dart, core/router/routes.dart, and features/settings/tiles.dart.

Install #

dart pub global activate --source git https://github.com/lohanidamodar/beej.git

One command, no clone. pub compiles a snapshot at activation time, so runs are clean and quick (~70ms) and nothing is re-resolved per invocation. Make sure ~/.pub-cache/bin is on your PATH.

Update with the same command; pin a version with --git-ref v0.1.0.

If you are working on beej itself #

./tool/install.sh          # compiles a standalone binary to ~/.local/bin/beej

~3ms rather than ~70ms, and it re-embeds templates first so a stale one cannot ship. The binary does not track source edits, so re-run it after changing beej.

What not to use #

dart pub global activate --source path . re-resolves dependencies on every invocation and prints "Resolving dependencies..." to stdout, which corrupts the output any agent or script is reading. It also starts in ~3s. Use one of the two above instead.

Development #

dart test                            # beej's own tests — seconds
dart run tool/verify_matrix.dart     # generate 10 configs, analyze + test each
dart run tool/verify_matrix.dart minimal --keep
dart run tool/embed_templates.dart   # after editing anything under templates/

Editing a template takes effect immediately when running from source — TemplateSource prefers the directory and falls back to the embedded copy. A test asserts the two agree, so a forgotten re-embed fails CI rather than shipping stale templates in a binary.

The matrix is the real safety net. Mutually exclusive bricks can never coexist in one project, so "the templates compile" is not achievable — proving the output compiles is what keeps fifteen toggles from rotting.

Package versions live in one place: lib/src/bricks/versions.dart. Bump there, then re-run the matrix.

What a generated project depends on #

One external repository: popupbits/fastlane-plugin-play_publisher, which is public. The release workflow is written into the project rather than calling a shared reusable workflow, so nothing in a generated repo depends on private infrastructure.

Known limitations #

The screenshot workflows have never run on a runner. Everything upstream of them is verified — capture, the job builder, and moksha rendering correct sizes for every device family — but emulator boot, the moksha checkout and gh pr create are unproven. Expect to fix something the first time.

No App Store preview video. moksha renders stills. Apple's 15-30 second recording is a separate job.

material_ui is an unusual choice. It is Material decoupled from the Flutter SDK, and everything generated here imports it instead of package:flutter/material.dart. If you want plain Flutter Material, beej is the wrong starting point — that assumption runs through the templates, the tests and the docs, and is not a flag you can flip.

0
likes
140
points
154
downloads

Documentation

API reference

Publisher

verified publisherdlohani.com.np

Weekly Downloads

Plants a new Flutter app — material_ui, Riverpod, go_router, en/ne localization, theming, fastlane and the store-screenshot harness, with Appwrite, sqflite and the rest as explicit choices.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

args, io, mustache_template, path, yaml, yaml_edit

More

Packages that depend on beej