Skip to content

Newsletter Subscription Backend

The public newsletter flow creates a contact, then sends the newsletter welcome message. This page documents orchestration and business behavior. See the Newsletter Subscribe API for the complete request, response, validation, status, and rate-limit contract.

Architecture

text
Request -> VineJS -> SubscriptionsController -> BrevoService -> ResendService -> Response
ComponentResponsibility
start/routes.tsRegisters the public throttled route
validators/subscription.tsValidates the email input
subscriptions_controller.tsOrders provider calls and maps failures to HTTP
brevo_service.tsCreates the contact in the configured list
resend_service.tsRenders and sends the newsletter welcome message
emails/welcome.edgeOwns newsletter welcome content

Provider transport and credential configuration is documented in Email Infrastructure.

Orchestration

SubscriptionsController.subscribe() performs the flow synchronously:

  1. Validate email with subscribeValidator.
  2. Call BrevoService.addSubscriber(email, listId).
  3. If contact creation succeeds, await ResendService.sendWelcomeEmail(email).
  4. Return 201 only after both calls finish.
typescript
const { email } = await request.validateUsing(subscribeValidator)

await BrevoService.addSubscriber(email, listId)
await ResendService.sendWelcomeEmail(email)

response.status(201)
return renderSuccessResponsePayload({
  message: 'Successfully subscribed to the newsletter.',
})

Contact creation intentionally runs first. A duplicate or other contact failure therefore does not send a welcome message.

Failure Behavior

  • VineJS rejects missing or malformed email input before a provider call.
  • DuplicateSubscriberError maps to 409 Conflict.
  • Other contact-provider errors map to 500 Internal Server Error and skip welcome delivery.
  • Welcome-delivery errors map to 500 Internal Server Error after the contact has been created.
  • The controller records failures with request-scoped key newsletter:subscribe.
  • There is no queue, background retry, fallback provider, or compensating contact deletion.

The exact public error bodies belong to the API contract.

Welcome Template

apps/server/resources/views/emails/welcome.edge is specific to newsletter signup. Account registration does not render this template. ResendService passes the subscriber address to Adonis Mail and awaits delivery.

Tests

bash
node ace test --files tests/unit/validators/subscription_validator.spec.ts
node ace test --files tests/functional/subscriptions.spec.ts

The functional tests stub Brevo and Resend at the external-service boundary. They cover success, required and malformed email input, duplicate contacts, and unexpected contact-provider failure. Routine tests must not create live contacts or send live mail.

Current Boundaries

  • The endpoint creates one contact and sends one welcome template.
  • The application does not send newsletter campaigns or store delivery analytics.
  • Subscriber lifecycle operations outside signup are handled through approved provider operations.

Built with ❤️ by the Jubiloop team