Skip to content

Epic: Publish the PostKit client SDK for trusted consumers #4

Description

@patoperpetua

Objective

Create @singleton-sd/post-kit-client, a small, typed npm package that any trusted Node.js/TypeScript consumer can use to call the PostKit API without reimplementing authentication, request contracts, error handling, or transport logic.

Consumers

The SDK must support:

  • PoC backend APIs
  • Azure Functions
  • marketing-site server endpoints
  • SSR loaders/actions
  • server actions
  • background workers
  • scheduled jobs
  • other trusted server-side Node.js applications

It is not intended to expose long-lived PostKit credentials in browser bundles.

Required technology

  • TypeScript
  • ESM
  • Node.js >= 20
  • pnpm workspace package
  • public npm package under @singleton-sd/post-kit-client
  • shared contracts from @singleton-sd/post-kit-types
  • native fetch unless there is a strong reason to introduce another HTTP dependency

Desired API

Example:

import { PostKitClient } from '@singleton-sd/post-kit-client';

const postKit = new PostKitClient({
  endpoint: process.env.POSTKIT_URL!,
  apiKey: process.env.POSTKIT_API_KEY!,
});

await postKit.send({
  template: 'marketing.contact-us',
  to: 'hello@example.com',
  variables: {
    name,
    email,
    message,
  },
});

The final auth options should follow the API epic's selected tenant authentication strategy. Design the client so auth strategies can evolve without breaking the send API.

API design principles

  • Keep the package thin; business/template logic belongs in PostKit, not the SDK.
  • Consumers should not need to know storage paths or provider details.
  • Use typed errors for non-2xx responses.
  • Include correlation/request IDs in errors/results when returned by PostKit.
  • Allow callers to inject/configure fetch where useful for testing.
  • Support AbortSignal/timeouts cleanly.
  • Do not silently retry non-idempotent sends unless an idempotency strategy exists.

Type safety

Use shared contract types for:

  • send request
  • send response
  • PostKit error response
  • template key metadata where practical

Do not duplicate DTOs independently in API and SDK packages.

Browser safety

The package must clearly document that authenticated sending is for trusted server-side execution.

If the package can technically be bundled in a browser, ensure:

  • secrets are not automatically sourced from browser globals
  • docs strongly discourage direct public-browser use
  • no misleading client-side examples are provided

Public marketing forms should call their own application/server endpoint, which then calls PostKit.

Work

  • Create packages/post-kit-client.
  • Implement configurable PostKitClient.
  • Implement send().
  • Add typed result/error classes.
  • Add auth header strategy abstraction/config.
  • Support correlation IDs.
  • Support AbortSignal/request timeout.
  • Add tests using mocked HTTP/fetch.
  • Add package README and usage examples.
  • Configure package exports/types/build.
  • Configure npm publication under Singleton SD scope.
  • Add changelog/release integration.

Agent implementation notes

Inspect package publishing and generated/client conventions in singleton-sd/poc-plattform-kit before choosing package tooling. Follow PostKit root conventions established by Epic #1.

Do not couple the SDK to React, Astro, Azure Functions, or any single framework. Framework-specific integration belongs in examples/documentation or separate packages only if later justified.

Acceptance criteria

  • A plain Node.js TypeScript application can install the public npm package and send a PostKit email.
  • A marketing site's server-side endpoint can use the exact same SDK.
  • Request/response/error types are shared with the API rather than duplicated.
  • Auth configuration does not expose tenant switching as a trusted request-field shortcut.
  • Errors include useful status/code/correlation information.
  • Package can be built, tested, versioned, and published independently from the monorepo.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions