Skip to content

Cloudflare

terradart_cloudflare wraps the official cloudflare/cloudflare provider (v5) — every resource and data source at its pinned version. Its place in a TerraDart project is the edge around your Dart app: the zone, DNS records, rules and certificates in front of a backend on Cloud Run, AWS or Firebase Hosting, in the same Dart codebase as that backend.

pubspec.yaml
dependencies:
terradart_core: ^0.35.0
terradart_cloudflare: ^0.35.0

CloudflareProvider takes no token, so credentials never enter the synthesized JSON, and synth needs none. terradart plan and terradart apply authenticate with CLOUDFLARE_API_TOKEN (or the other CLOUDFLARE_* variables the provider reads). With them in place, terradart apply synthesizes the Stack and applies it.

lib/edge_stack.dart
import 'package:terradart_cloudflare/dns.dart';
import 'package:terradart_cloudflare/provider.dart';
import 'package:terradart_cloudflare/zone.dart';
final class EdgeStack extends Stack {
EdgeStack({required String accountId})
: super(
providers: [const CloudflareProvider()],
appExports: AppExports('lib/generated/edge_stack.app.dart'),
) {
final zone = add(CloudflareZone(
'main',
name: .literal('example.com'),
account: ZoneAccount(id: .literal(accountId)),
));
final api = add(CloudflareDnsRecord(
'api',
zoneId: zone.ref, // only a CloudflareZone fits here
name: .literal('api.example.com'),
type: .cname,
ttl: .literal(1),
content: .content(.literal('ghs.googlehosted.com')),
proxied: .literal(true),
));
addConstant('apiHost', .ref(api.name));
}
}

The app reads the host it is served from as EdgeStackConstants.apiHost instead of a second copy of the string. The Stack can sit next to a Google, AWS or Appwrite Stack in the same package, or share one Stack with them by listing both providers.

  • Enums. Inputs with a fixed value set, such as a DNS record’s type, are Dart enums (.cname). The sets come from the provider’s documentation and its Go validators, re-extracted on every schema bump.
  • Sealed choices. Arguments the provider declares mutually exclusive are one sealed argument: a DNS record has content or structured data, written content: .content(...) or content: .data(...).
  • Typed nested objects. The plugin-framework provider describes objects as nested attributes; each becomes a helper class (ZoneAccount) rather than a Map.
  • References. zoneId: zone.ref, accountId: account.ref: an argument that names another resource takes that resource. A user group’s members take the account member (CloudflareUserGroupMembers(userGroupId: group.ref, members: [.new(id: member.ref)])).