---
title: "Getting started with Workers"
description: "Compose Worker-compatible Playstack crypto and feed primitives with Web platform APIs and explicit environment bindings."
tags: ["frameworks","workers","getting-started","crypto","feeds"]
---

This guide demonstrates two edge-safe boundaries: a reusable cryptography service configured from Worker bindings, and a streaming RSS response returned directly from `fetch`.

## 1. Install portable packages

**Before you start:** use an existing Worker project with its generated `Env` type. These composition examples assume you supply encryption/signing key bindings, a content binding, `feedDefinition` and `streamPublishedEntries`. See [Crypto](/docs/packages/foundation/crypto) for key configuration and [Feeds](/docs/packages/content-intelligence/feeds) for content shapes. They do not provision infrastructure or secrets. For a complete local first program, use the [storage quickstart](/docs/getting-started#your-first-working-example), then return here for edge deployment.

```sh
npm install @playstack/core @playstack/crypto @playstack/feeds
```

These packages use Web platform primitives. Keep them on the same fixed Playstack version, confirm [package access](/docs/packages#access-policy), and run the relevant Worker tests for your selected version. Portable APIs alone do not establish deployment compatibility.

## 2. Configure Web Crypto explicitly

Convert environment bindings into package configuration in the application entry. Do not let the package read ambient environment variables:

```ts
import { systemClock } from '@playstack/core'
import { createCrypto } from '@playstack/crypto'

function cryptoFor(env: Env) {
  return createCrypto({
    crypto: globalThis.crypto,
    clock: systemClock(),
    encryptionKeys: JSON.parse(env.PLAYSTACK_ENCRYPTION_KEYS),
    signingKeys: JSON.parse(env.PLAYSTACK_SIGNING_KEYS),
  })
}
```

Each keyset must contain exactly one active key. Retain inactive keys while existing ciphertext or signed tokens may still reference them. Supply an atomic replay store before verifying single-use tokens.

If configuration is deployment-stable, parse it once at module scope or cache the configured service by binding identity. Request-specific actors and correlation metadata belong in operation context, not global service state.

## 3. Return a native streaming response

`@playstack/feeds` can stream directly from a Worker without a Next.js or Node.js adapter:

```ts
import { feedResponse } from '@playstack/feeds'

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url)

    if (url.pathname !== '/feed.xml') {
      return new Response('Not found', { status: 404 })
    }

    return feedResponse(
      'rss',
      feedDefinition,
      streamPublishedEntries(env.CONTENT),
      { content: 'full', cacheControl: 'public, max-age=60' },
    )
  },
}
```

The returned value is a standard `Response`, and the body is a standard `ReadableStream`. For large generated feeds, use the structural R2 storage adapter and publish a committed generation instead of rebuilding the document on every request.

## 4. Add edge persistence by contract

- Use [`@playstack/rate-limit-do`](/docs/packages/events-operations/rate-limit-do) when rate-limit state needs Durable Object atomicity.
- Use the R2 feed storage implementation from [`@playstack/feeds`](/docs/packages/content-intelligence/feeds) for generated documents.
- Provide application adapters for authentication, accounts, audit, and events rather than importing Node-specific Prisma or NestJS bindings.
- Queue observational events after the domain mutation has reached its own durable boundary.

## Verify the bundle

- Run the package's Worker compatibility target before deployment.
- Inspect the bundle for accidental Node built-ins and framework adapters.
- Keep raw subject identifiers out of rate-limit storage keys.
- Verify HMACs and webhooks against the exact request bytes.
- Treat `waitUntil` as delivery scheduling, not as a substitute for transactional durability.
