Alpha

Type-safe IaC for Dart.

Terraform stays. You author in Dart. Define typed cloud resources and emit standard *.tf.json for the terraform apply pipeline you already run.

Cloud infrastructure in Dart

Cloud SQL, IAM, and a multi-container Cloud Run service with a cloud-sql-proxy sidecar — a final class … extends Stack. Same snippet as the repository README.

// infra/lib/app_infra.dart
// A Stack is one Terraform root module of GCP resources, written in Dart.
import 'package:terradart_core/terradart_core.dart';
import 'package:terradart_google/cloud_run.dart';
import 'package:terradart_google/cloud_sql.dart';
import 'package:terradart_google/iam.dart';
import 'package:terradart_google/provider.dart';

final class AppInfraStack extends Stack {
  AppInfraStack({required String projectId})
      : super(providers: [
          GoogleProvider(project: projectId, region: 'asia-northeast1'),
        ]) {
    add(GoogleSqlDatabaseInstance(
      localName: 'app_sql',
      name: TfArg.literal('app-sql'),
      databaseVersion: TfArg.literal(DatabaseVersion.postgres15),
      region: TfArg.literal('asia-northeast1'),
      settings: SqlDatabaseInstanceSettings(
        tier: TfArg.literal('db-f1-micro'),
      ),
    ));

    final runSa = add(GoogleServiceAccount(
      localName: 'run_sa',
      accountId: TfArg.literal('app-run-sa'),
    ));
    add(GoogleProjectIamMember(
      localName: 'run_sa_sql_client',
      project: TfArg.literal(projectId),
      role: TfArg.literal('roles/cloudsql.client'),
      member: TfArg.ref(runSa.iamMember),
    ));

    add(GoogleCloudRunV2Service(
      localName: 'app',
      name: TfArg.literal('app'),
      location: TfArg.literal('asia-northeast1'),
      template: CloudRunV2ServiceTemplate(
        serviceAccount: TfArg.ref(runSa.email),
        containers: [
          CloudRunV2ServiceServiceContainer(
            name: TfArg.literal('app'),
            image: TfArg.literal('gcr.io/cloudrun/hello'),
            ports: CloudRunV2ServiceContainerPort(
              containerPort: TfArg.literal(8080),
            ),
            env: [
              CloudRunV2ServiceEnvVar(
                name: TfArg.literal('DATABASE_URL'),
                source: CloudRunV2ServiceEnvVarFromLiteral(
                  TfArg.literal(
                    'postgresql://app-client@${projectId}.iam@localhost:5432/app',
                  ),
                ),
              ),
            ],
          ),
          CloudRunV2ServiceServiceContainer(
            name: TfArg.literal('cloud-sql-proxy'),
            image: TfArg.literal(
              'gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.18.1',
            ),
            args: TfArg.literal([
              '--port=5432',
              '--auto-iam-authn',
              '${projectId}:asia-northeast1:app-sql',
            ]),
          ),
        ],
      ),
    ));
  }
}

Curated packages wrap official Terraform providers: terradart_google (GA catalog, 1793 entries), terradart_google_beta (128 beta-only factories), terradart_appwrite, and terradart_cloudflare. The full factory list with runnable examples is on Coverage; complete stacks live in the cookbook and examples on GitHub (both growing).

Connect infra and app code with types

A boundary held together by string literals

Topic names in HCL or the console and again in your Cloud Run functions handlers. Renames do not reach subscribers via dart fix. IAM members drift with no compiler visibility. Infra values flowing into app code are often the layer Dart’s type system never sees.

Terraform stays the execution layer

TerraDart is not a parallel runtime. Write Terraform’s resource model as Dart factories and sealed types, then generate *.tf.json for the provider you already use. terraform plan, apply, and remote state stay unchanged.

Dart types where HCL cannot help

Fixed values become enums. Exactly-one-of blocks become sealed classes. Your infra module is a final class … extends Stack — loops, config, and refactors work like any other Dart code.

Read the design rationale →

Where TerraDart fits

TerraDart fits teams already centered on Dart, already running Terraform (or a compatible pipeline) or managing infrastructure in cloud consoles, where the seam between infra and app code hurts.

TerraDartHCLCDKTFPulumi
Dart authoring YesNoNoNo
Drop-in for terraform apply YesYesYesDifferent model
Curated Dart factories YesNoNoNo
Project status AlphaMatureArchived 2025Active

HCL has provider schema types; CDKTF bindings are typed in TypeScript and other languages. TerraDart’s difference is Dart-native authoring without replacing your Terraform execution pipeline.

See full comparison →

How it works in three steps

Author in Dart

Subclass Stack with curated factories from provider packages.

Generate Terraform JSON

stack.writeTo(...) writes *.tf.json — no custom apply runtime.

Apply with Terraform

terraform plan and apply unchanged; state stays where it is.

Details: /docs/architecture · README