mini_program_tooling
Developer tooling for the portable Flutter mini-program platform.
This package exposes the global miniprogram CLI used to create mini-programs,
build and validate authored flows, preview with watch/rebuild/refresh, publish
to local or AWS cloud delivery, deploy the managed AWS backend, initialize
embedding adapters for existing Flutter apps, bind host apps to cloud
environments, and manage the local backend lifecycle.
Install
Released package:
dart pub global activate mini_program_tooling
Repo-local contributor install:
dart pub global activate --source path <repo-root>/packages/mini_program_tooling
CLI surface
miniprogram create <mini-program-id>
miniprogram doctor
miniprogram backend init
miniprogram env init
miniprogram env configure <env-name> --provider aws --bucket <unique-bucket-name> --region <aws-region> [--aws-profile <aws-profile>]
miniprogram env list
miniprogram env use <local|env-name>
miniprogram env status
miniprogram build [mini-program-id]
miniprogram preview -d <chrome|edge|ios|linux|macos|windows|emulator-5554|android-device-id|android-wifi-device-id> [mini-program-id]
miniprogram validate [mini-program-id]
miniprogram publish [mini-program-id] [--target local|cloud] [--env <env-name>]
miniprogram cloud deploy [--env <env-name>]
miniprogram cloud status [--env <env-name>]
miniprogram cloud outputs [--env <env-name>] [--format text|dart-define]
miniprogram cloud logs [--env <env-name>]
miniprogram cloud destroy [--env <env-name>]
miniprogram cloud doctor [--env <env-name>]
miniprogram cloud rollback <version> [mini-program-id] [--env <env-name>]
miniprogram host run -d <device> [--env <env-name>]
miniprogram embed init [--project-root <path>] [--force]
miniprogram embed cloud configure [--env <env-name>]
miniprogram backend start --port 8080
miniprogram backend stop
miniprogram backend status
miniprogram backend reset-local --yes
Use miniprogram <command> --help, miniprogram <group> --help, or
miniprogram <group> <command> --help for command-specific options.
Examples
Check your machine and saved CLI state first:
miniprogram doctor
Create a standalone mini-program in the current directory:
miniprogram create coupon_center
The default scaffold uses only analytics, so it opens in a minimal generated
host app without native-route wiring. Add native_navigation only when your
host app has a real native route callback.
Use managed preview for the fastest authoring loop:
cd coupon_center
miniprogram preview -d chrome
Preview v1 currently supports:
chromeedgeioson macOS with Xcodelinuxmacoswindows- Android emulator ids such as
emulator-5554 - Android USB device ids such as
R58M123ABC - Android Wi-Fi device ids such as
192.168.1.25:5555
preview is a developer-only loop. It does not require backend init or
backend start, does not publish into backend/api/, and keeps a managed
hidden host app under .mini_program/preview_host.
During preview, the CLI:
- builds the mini-program before launch
- starts a tiny session-scoped localhost preview server when needed
- watches
manifest.json,stac/**,assets/**, andlib/default_stac_options.dart - rebuilds on save and triggers a full preview refresh
- prefers
adb reverse tcp:<port> tcp:<port>for Android emulator preview and useshttp://127.0.0.1:<port>/preview/when reverse is available - falls back to
http://10.0.2.2:<port>/preview/for emulator sessions when reverse is unavailable - auto-applies
adb reverse tcp:<port> tcp:<port>for Android USB preview and useshttp://127.0.0.1:<port>/preview/inside the device session - uses a resolved LAN host such as
http://192.168.1.10:<port>/preview/for Android Wi-Fi preview sessions
For Android Wi-Fi preview, the device must be able to reach your dev machine on
the same LAN. If auto-detection picks the wrong host IP, set
MINI_PROGRAM_PREVIEW_LAN_HOST=<your-lan-ip> before running preview.
Preview capability behavior in v1:
analyticslogs through the preview host and returns successnative_navigationopens a preview-native placeholder pagesecure_apireturns an explicit preview-only failure
Initialize a standalone backend workspace once:
miniprogram backend init
On Windows, this defaults to %LOCALAPPDATA%\mini_program\backend\. Use
miniprogram backend init --root <custom-path> only when you intentionally
want a different workspace location.
Initialize local CLI env once from a standalone mini-program workspace:
cd <workspace>/coupon_center
miniprogram env init
That writes both a workspace-local .mini_program/env.json and a user-level
fallback env file, so later commands can run from this workspace or from
unrelated directories without repeating setup.
Then build, validate, and publish without any platform repo path:
cd coupon_center
miniprogram build
miniprogram validate
miniprogram publish
If a standalone backend workspace was initialized earlier with
miniprogram backend init, publish writes manifests and screens into that
workspace instead of the platform repo backend.
From outside the mini-program folder, the explicit form still works:
miniprogram build coupon_center
miniprogram validate coupon_center
miniprogram publish coupon_center
Configure a named AWS cloud environment:
miniprogram env init
miniprogram env configure <env-name> --provider aws --bucket <unique-bucket-name> --region <aws-region> [--aws-profile <aws-profile>] [--cloudfront-base-url https://<cloudfront-domain>] [--api-base-url https://<api-domain>]
miniprogram env use <env-name>
miniprogram env list
miniprogram env status
Replace the placeholder values before running that command. In particular:
<env-name>should be something likemy-aws-prod<unique-bucket-name>must be globally unique in S3<aws-region>should be a real AWS region such asap-south-1--cloudfront-base-urland--api-base-urlare optional and should only be supplied when you already have those URLs
Where those optional URLs come from:
--api-base-urlis usually theBackendApiBaseUrlprinted byminiprogram cloud deployorminiprogram cloud outputs, for examplehttps://<api-id>.execute-api.<aws-region>.amazonaws.com/prod/api/- if you use
miniprogram cloud deploy, you normally do not need to pass--api-base-urlduringenv configure; the CLI can read the deployed stack output later --cloudfront-base-urlis the CloudFront distribution domain name, visible in the AWS CloudFront console as the distribution domain, for examplehttps://<distribution-id>.cloudfront.net- CloudFront is optional in the current AWS CLI flow; API Gateway + Lambda is enough for host-app testing
Cloud publish then uses the active named cloud environment by default:
cd coupon_center
miniprogram publish --target cloud
Or use an explicit env override:
miniprogram publish --target cloud --env my-aws-prod
One bucket can store many mini-programs for the same environment. Artifacts are keyed by mini-program ID and version:
artifacts/<mini-program-id>/<version>/manifest.json
artifacts/<mini-program-id>/<version>/screens/<screen-id>.json
metadata/catalog/<mini-program-id>.json
metadata/releases/<mini-program-id>/<version>.json
Host apps should use the API Gateway base URL printed by
miniprogram cloud outputs, not the S3 bucket URL.
Current cloud support in this phase:
- provider implementation shipped:
aws - planned next providers:
gcp,custom-s3-compatible - AWS deploy support in
mini_program_toolingassumes:- Windows + PowerShell
- region
ap-south-1 - fastest working path first
- normal developers use the published CLI only; they do not need to manually
use the repo
infra/folder
Important rule:
- if you signed in with the AWS root account, you can create IAM users, buckets, and everything else
- if you signed in with an IAM user/role and cannot create those things, you do not have enough permissions and need an admin to grant them
1. One-time AWS account setup
Best practice:
- use the root account only for:
- enabling MFA
- creating an admin identity
- do not use root for daily work
Fastest practical setup for your own standalone AWS account:
- sign in as root
- enable MFA on root
- open IAM
- create a user like
mini-admin - give it
AdministratorAccess - create:
- console access
- access key for CLI use
- sign out of root
- sign in as
mini-admin
For first setup, AdministratorAccess is the easiest path. Later you can
replace it with a narrower deploy policy.
2. Install tools on your computer
Install:
- AWS CLI
- AWS SAM CLI
- Node.js 24 or newer
- Flutter
- Dart
Then verify:
aws --version
sam --version
node --version
flutter --version
dart --version
miniprogram cloud deploy uses an AWS Lambda nodejs24.x backend template.
Keep AWS SAM CLI up to date enough to deploy nodejs24.x functions.
3. Connect your computer to AWS
Option A: access key profile
aws configure --profile my-aws
aws sts get-caller-identity --profile my-aws
Enter:
- Access key ID
- Secret access key
- Region:
ap-south-1 - Output format:
json
If that works, your computer is connected to AWS.
Option B: AWS SSO
aws configure sso --profile my-sso
aws sso login --profile my-sso
aws sts get-caller-identity --profile my-sso
For a new standalone personal account, the access-key profile path is usually simpler.
4. Create the S3 bucket
Bucket names must be globally unique.
Example:
aws s3api create-bucket --bucket my-mini-program-prod-ap-south-1-001 --region ap-south-1 --create-bucket-configuration LocationConstraint=ap-south-1 --profile my-aws
Enable versioning:
aws s3api put-bucket-versioning --bucket my-mini-program-prod-ap-south-1-001 --versioning-configuration Status=Enabled --region ap-south-1 --profile my-aws
aws s3api get-bucket-versioning --bucket my-mini-program-prod-ap-south-1-001 --region ap-south-1 --profile my-aws
Expected result:
{
"Status": "Enabled"
}
5. Create your mini-program
cd D:\
miniprogram create my_coupon_app
cd my_coupon_app
miniprogram preview -d chrome
Use preview first so you confirm the mini-program works before cloud deploy.
6. Configure miniprogram for AWS
Initialize env:
miniprogram env init
Configure the AWS environment:
miniprogram env configure my-aws-prod --provider aws --bucket my-mini-program-prod-ap-south-1-001 --region ap-south-1 --aws-profile my-aws
Select it:
miniprogram env use my-aws-prod
miniprogram env status
7. Publish and deploy to AWS
Publish the mini-program artifacts to S3:
miniprogram publish --target cloud
Check cloud prerequisites:
miniprogram cloud doctor
Deploy the API Gateway + Lambda backend:
miniprogram cloud deploy
Inspect outputs:
miniprogram cloud outputs
miniprogram cloud outputs --format dart-define
What the CLI does here:
- uploads artifacts to S3
- generates a managed SAM project locally
- runs
sam build - runs
sam deploy - creates or updates:
- API Gateway
- Lambda
- Lambda IAM role
You do not manually create API Gateway routes.
8. Connect a Flutter host app
If you do not have a host app yet:
cd D:\
flutter create my_mini_host
cd my_mini_host
miniprogram embed init
flutter pub get
Bind that host app to your AWS env:
miniprogram embed cloud configure --env my-aws-prod
Run it:
miniprogram host run -d chrome --env my-aws-prod
Or Windows desktop:
miniprogram host run -d windows --env my-aws-prod
That wraps flutter run and passes the deployed backend URL automatically.
For release APK builds, use the backend define from the cloud outputs:
miniprogram cloud outputs --format dart-define
cd D:\my_mini_host
flutter build apk --release --dart-define=MINI_PROGRAM_BACKEND_BASE_URL=https://<api-id>.execute-api.<aws-region>.amazonaws.com/prod/api/
Use the BackendApiBaseUrl shown by miniprogram cloud outputs; do not use
the S3 bucket URL directly. The host app loads through API Gateway + Lambda.
Demo lib/main.dart for a host app:
import 'package:flutter/material.dart';
import 'package:mini_program_sdk/mini_program_sdk.dart';
import 'mini_program/mini_program_launcher.dart';
import 'mini_program/mini_program_runtime_setup.dart';
void main() {
runApp(
MiniProgramScope(
config: buildMiniProgramConfig(),
child: const MyHostApp(),
),
);
}
class MyHostApp extends StatelessWidget {
const MyHostApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Mini Host',
debugShowCheckedModeBanner: false,
theme: ThemeData(colorSchemeSeed: Colors.teal, useMaterial3: true),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Host App Home')),
body: Center(
child: FilledButton(
onPressed: () {
openAppMiniProgram(
context,
appId: 'my_coupon_app',
title: 'My Coupon App',
);
},
child: const Text('Open My Coupon App'),
),
),
);
}
}
Generated host-app structure:
pubspec.yamlis updated withmini_program_sdkandmini_program_contractslib/mini_program/mini_program.dartis an optional generated barrel export if you prefer one app-local importlib/mini_program/mini_program_launcher.dartexposesopenAppMiniProgram(...)andAppMiniProgramLauncherlib/mini_program/mini_program_runtime_setup.dartresolvesMINI_PROGRAM_BACKEND_BASE_URLand buildsMiniProgramConfiglib/mini_program/app_host_bridge.dartis where developers wire real analytics, optional native screens, and secure API behaviorlib/main.dartstays app-owned; edit it to add buttons, tabs, or menu items that callopenAppMiniProgram(...)MiniProgramScopedoes not create or controlMaterialApp,MaterialApp.router, GetX, GoRouter, Provider, Bloc, Riverpod, themes, localization, routes, or navigator setup- Android release builds need internet access to load cloud mini-programs.
miniprogram embed initwritesandroid.permission.INTERNETintoandroid/app/src/main/AndroidManifest.xml. Debug builds also get cleartext/network config for local HTTP backend access.
9. Minimum policies you need
Easiest first setup:
- use
AdministratorAccesson your admin user
That is the shortest path to get working.
Narrower deploy user later needs at least:
- S3 bucket access
s3:ListBuckets3:GetBucketLocations3:GetBucketVersionings3:GetObjects3:PutObjects3:DeleteObjects3:AbortMultipartUpload
- CloudFormation
cloudformation:CreateStackcloudformation:UpdateStackcloudformation:DeleteStackcloudformation:DescribeStackscloudformation:DescribeStackEventscloudformation:DescribeStackResourcescloudformation:ListStackResourcescloudformation:CreateChangeSetcloudformation:ExecuteChangeSetcloudformation:DeleteChangeSetcloudformation:DescribeChangeSetcloudformation:GetTemplatecloudformation:GetTemplateSummarycloudformation:ValidateTemplate
- Lambda
lambda:CreateFunctionlambda:UpdateFunctionCodelambda:UpdateFunctionConfigurationlambda:DeleteFunctionlambda:GetFunctionlambda:GetFunctionConfigurationlambda:GetPolicylambda:AddPermissionlambda:RemovePermissionlambda:TagResourcelambda:UntagResourcelambda:ListTags
- API Gateway
apigateway:GETapigateway:POSTapigateway:PUTapigateway:PATCHapigateway:DELETEapigateway:TagResourceapigateway:UntagResource
- IAM role management for the Lambda execution role
iam:CreateRoleiam:DeleteRoleiam:GetRoleiam:PassRoleiam:TagRoleiam:UntagRoleiam:AttachRolePolicyiam:DetachRolePolicyiam:PutRolePolicyiam:DeleteRolePolicyiam:GetRolePolicyiam:ListRolePoliciesiam:ListAttachedRolePolicies
- If your bucket uses KMS encryption, also:
kms:Encryptkms:Decryptkms:GenerateDataKeykms:DescribeKey
10. If you still cannot create IAM users or buckets
Then one of these is true:
- you are not signed in as root or admin
- your IAM user/role is restricted
- your AWS account is inside an AWS Organization with SCP restrictions
In that case, ask the account admin for either:
AdministratorAccesstemporarily for setup- or a dedicated deploy user/role with the permissions above
Exact end-to-end command sequence
# 1. configure aws cli
aws configure --profile my-aws
aws sts get-caller-identity --profile my-aws
# 2. create bucket
aws s3api create-bucket --bucket my-mini-program-prod-ap-south-1-001 --region ap-south-1 --create-bucket-configuration LocationConstraint=ap-south-1 --profile my-aws
aws s3api put-bucket-versioning --bucket my-mini-program-prod-ap-south-1-001 --versioning-configuration Status=Enabled --region ap-south-1 --profile my-aws
# 3. create and test mini-program locally
cd D:\
miniprogram create my_coupon_app
cd my_coupon_app
miniprogram preview -d chrome
# 4. configure miniprogram aws env
miniprogram env init
miniprogram env configure my-aws-prod --provider aws --bucket my-mini-program-prod-ap-south-1-001 --region ap-south-1 --aws-profile my-aws
miniprogram env use my-aws-prod
miniprogram cloud doctor
# 5. publish and deploy
miniprogram publish --target cloud
miniprogram cloud deploy
miniprogram cloud outputs
# 6. host app
cd D:\
flutter create my_mini_host
cd my_mini_host
miniprogram embed init
flutter pub get
miniprogram embed cloud configure --env my-aws-prod
miniprogram host run -d chrome --env my-aws-prod
Official AWS docs:
- Root user best practices: https://docs.aws.amazon.com/IAM/latest/UserGuide/root-user-best-practices.html
- Create an administrative user: https://docs.aws.amazon.com/accounts/latest/reference/getting-started-step4.html
- Create an IAM user: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html
- Install AWS CLI: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
- Configure AWS CLI SSO: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
- Install AWS SAM CLI: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html
sam deploycapabilities: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-cli-command-reference-sam-deploy.html- Create S3 bucket with CLI: https://docs.aws.amazon.com/cli/v1/reference/s3api/create-bucket.html
- Enable S3 versioning: https://docs.aws.amazon.com/AmazonS3/latest/userguide/manage-versioning-examples.html
put-bucket-versioningCLI: https://docs.aws.amazon.com/cli/v1/reference/s3api/put-bucket-versioning.html
Initialize the embedding adapter for an existing Flutter app:
cd <existing-flutter-app>
miniprogram embed init
embed init updates the host app pubspec.yaml to use the published
mini_program_sdk and mini_program_contracts packages.
When the local backend is already running on port 8080, the generated
runtime setup uses target-aware defaults:
- Android local default:
http://10.0.2.2:8080/api/ - desktop, Chrome on the same machine, and iOS simulators:
http://127.0.0.1:8080/api/ - Android USB
adb reverseflows keep using127.0.0.1, and the shared SDK retries local loopback between10.0.2.2and127.0.0.1on transport failures
Conditions:
- the local backend should already be running on port
8080 - Android USB or emulator loopback may still depend on an active
adb reversesession when the device cannot route to10.0.2.2 - if the Android device or emulator connects after backend start, rerun
miniprogram backend start --port 8080or reapplyadb reverse - physical devices over Wi-Fi should override
MINI_PROGRAM_BACKEND_HOST=<computer-lan-ip>
So Android emulator development should usually work with:
flutter run -d emulator-5554
miniprogram embed init also writes Android release INTERNET permission and
debug-only cleartext/network configuration so cloud release APKs can call the
API Gateway backend and the generated emulator default can reach
http://10.0.2.2:8080/api/ without manual manifest edits.
For physical-device Wi-Fi or cloud testing, override either the full base URL or just the host/port:
flutter run -d chrome --dart-define=MINI_PROGRAM_BACKEND_HOST=192.168.1.25
flutter run -d windows --dart-define=MINI_PROGRAM_BACKEND_BASE_URL=https://mini.example.com/api/
If you need to target an app from another directory, use:
miniprogram embed init --project-root <existing-flutter-app>
Start and inspect the local backend:
miniprogram backend start --port 8080
miniprogram backend status
miniprogram backend stop
When adb is available, miniprogram backend start also tries
adb reverse tcp:<port> tcp:<port> for connected Android emulators and
devices. That keeps the common local Android flow on plain flutter run
instead of requiring a manual reverse step every time.
For local debugging, miniprogram backend start and miniprogram backend status print the target-specific URLs the generated host adapter expects:
- Android emulator:
http://10.0.2.2:<port>/api/ - desktop and Chrome on the same machine:
http://127.0.0.1:<port>/api/ - Android USB with
adb reverse:http://127.0.0.1:<port>/api/
The generated host runtime also logs the resolved backend base URL and whether it came from:
MINI_PROGRAM_BACKEND_BASE_URLMINI_PROGRAM_BACKEND_HOSTandMINI_PROGRAM_BACKEND_PORT- target-aware defaults
For Chrome and other web targets, the generated local backend workspace now
includes browser-friendly CORS and localhost private-network headers, so plain
local web runs can reach http://127.0.0.1:8080/api/ without manual backend
service patching.
miniprogram doctor reports:
- Dart runtime availability
flutteron PATH- managed pinned Stac builder status and pinned version
- saved env configuration
- optional platform repo root
- local backend workspace layout
- current backend health/state
Local CLI state
The CLI keeps repo-local state in:
.mini_program/env.json.mini_program/backend_workspace.json.mini_program/backend.local.json.mini_program/published_local_artifacts.json
It also keeps a user-level fallback file in:
~/.mini_program/global_env.json~/.mini_program/global_backend_workspace.json
Project-local preview also manages:
.mini_program/preview_host/
backend reset-local --yes only removes tracked local publish outputs. It does
not wipe all of backend/api/ or remove rollout, capability, or secure API
policy files that were not created by the CLI publish flow.
Notes
env usenow selects eitherlocalor a configured named cloud environment.env configurestores named cloud environments such asmy-aws-prodormy-gcp-staging.publish --target cloudis implemented forawsin this phase.cloud deploy|status|outputs|logs|destroy|doctor|rollbackare implemented forawsin this phase.gcpandcustom-s3-compatibleare the planned next cloud providers.- Standalone build/publish/validate no longer require a platform repo root.
previewis the fastest local authoring loop;publishplusbackend startremains the real local delivery simulation.- Normal builds use the managed pinned Stac builder bundled inside
mini_program_tooling. --stac-cli-scriptremains the escape hatch when you intentionally need to override that managed builder.- Local backend lifecycle commands can work from either:
- the default per-user
miniprogram backend initworkspace - the platform repo layout with
backend/local_backend_service/andbackend/api/
- the default per-user
publishfollows the same backend workspace resolution, so local publish outputs andbackend reset-local --yesstay attached to the initialized backend workspace.- Existing low-level Dart bins remain in the repo for compatibility.
- The repo PowerShell wrappers now delegate to the installed
miniprogramcommand for the standard text workflow and only fall back to legacy Dart entrypoints for compatibility-only modes such as-Output json. miniprogram ...is the preferred workflow.