Service Adapters

Service Adapters

Product code calls external capabilities through src/services. src/adapters owns provider APIs, SDKs, and Cloudflare bindings, while src/core/services defines the shared contracts. Replacing a provider should leave most product flows unchanged.

Support matrix

ServiceAdapterRuntimeConfiguration
PaymentcreemNodeCREEM_API_KEY, CREEM_WEBHOOK_SECRET
PaymentstripeUniversalSTRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET
Storages3-compatibleNodeEndpoint, region, bucket, and access keys
Storager2-bindingWorkerNEXTDEVTPL_STORAGE R2 binding
MaildisabledUniversalNone; calls report an explicit configuration error
MailresendUniversalRESEND_API_KEY, EMAIL_FROM
MailsmtpNodeSMTP_HOST, port, and optional credentials
Mailcloudflare-emailWorkerNEXTDEVTPL_EMAIL Email binding
AIopenai-compatibleUniversalOpenAI, DeepSeek, or MiMo key and model
AIanthropicUniversalANTHROPIC_API_KEY, ANTHROPIC_MODEL
AIworkers-aiWorkerAI binding and WORKERS_AI_MODEL
AlertsnoopUniversalNone; records state without sending
AlertsemailUniversalALERT_EMAIL_TO, EMAIL_FROM, selected mail adapter
AlertswebhookUniversalALERT_WEBHOOK_URL, optional HMAC secret
AnalyticsnoopUniversalNo external request
AnalyticsloggerUniversalStructured server-side events
AnalyticsposthogUniversalPOSTHOG_API_KEY, optional host
Analyticsga4UniversalMeasurement ID, API secret, optional browser ID
AnalyticsumamiUniversalWebsite ID, API key, optional host
JobsinngestUniversalINNGEST_EVENT_KEY, INNGEST_SIGNING_KEY
Jobscloudflare-workflowsWorkerNEXTDEVTPL_WORKFLOW binding
Rate limitnoopUniversalNone; suitable for local or trusted networks
Rate limitupstashUniversalUpstash REST URL and token
Rate limitcloudflare-rate-limitWorkerSeven Rate Limiting bindings

The generator keeps only the selected implementation, packages, and variables. For Cloudflare it writes required bindings to wrangler.jsonc; create remote resources such as R2 buckets and then replace generated placeholders as needed.

Analytics adapters capture the typed event envelope; the local operations read model remains authoritative for revenue and AI cost metrics. Alert selection is fixed at generation time. Missing provider configuration falls back to the no-op adapter and is shown as an explicit operational state.

Call a service

Import the stable service entry point:

import { paymentService } from "@/services/payment";

const checkout = await paymentService.createCheckout({
  productId,
  successUrl,
  metadata: { userId },
});

The same pattern applies to mailService, storageService, aiService, jobService, and rateLimitService. Provider fields are normalized inside the adapter.

Replace an adapter

Choose the desired adapter when generating a new app. For an existing app, generate a temporary project with the target adapter, then merge the matching src/adapters/<service>, src/services/<service>.ts, package, environment, and deployment binding changes. Run the adapter tests and full build afterward.

Editing nextdevtpl.generated.json alone does not change generated source.

On this page