File storage

Store and retrieve application objects through explicit filesystem, S3, or R2 providers with validated keys, metadata, streaming bodies, and signed access.

Supported approaches

Portable object storage

available

Put, inspect, stream, and delete objects through an application-prefixed driver without hiding its native client.

Packages

@playstack/storage

Signed download and upload access

available

Issue bounded get or put URLs only when the provider declares the required signing capability.

Local and test storage

available

Use filesystem and in-memory contracts with the same key and metadata behavior as production object stores.

Frameworks and integrations

Frameworks and integrations

framework

Next.js

Compose Playstack server contracts, React bindings, SSR handoff, and route adapters at the Next.js application edge.

framework

NestJS

Connect portable Playstack capabilities to dependency injection, guards, decorators, request context, workers, and lifecycle hooks.

framework

Cloudflare Workers

Run portable contracts in Web-standard runtimes with explicit Workers KV, R2, Queues and Durable Object adapters.

integration

Cloudflare R2

Store portable Playstack objects through a structural R2 binding with explicit public and signed URL capabilities.

integration

Amazon S3

Store portable Playstack objects and issue bounded signed URLs through an application-configured AWS SDK client.

Package reference

@playstack/storage

Keep object policy above the provider

The storage boundary handles bytes, streams, metadata, prefixes, and provider capabilities. The application still decides who may upload, which content types are permitted, how records refer to objects, and when deletion is safe.

ts
import { createStorage } from '@playstack/storage'
import { S3StorageProvider } from '@playstack/storage/s3'

export const storage = createStorage({
  app: 'media',
  environment: 'production',
  provider: new S3StorageProvider({ client: s3, bucket }),
})

await storage.put(`accounts/${account.id}/avatars/${file.id}`, body, {
  contentType: file.contentType,
  cacheControl: 'private, max-age=3600',
  metadata: { ownerId: account.id },
})

Sign only supported operations

ts
const uploadUrl = await storage.signedUrl(objectKey, {
  operation: 'put',
  contentType: input.contentType,
  expiresInSeconds: 300,
})

Capabilities state whether a provider supports public URLs, signed downloads, and signed uploads. Unsupported behavior fails before an invalid URL reaches a client.

Stream across runtime boundaries

Returned objects expose Web ReadableStream bodies so portable code works in server and Worker runtimes. Node adapters accept familiar byte and stream inputs without forcing Node-only types into the core contract.

Go

Playstack Pro tag
OriginsPricingBlogNewsletterChangelogStatusRoadmap
ContributorsCommunityIn Use ShowcaseCase StudiesPartnersSponsors
FAQsSupportContact

© 2026 Playstack. All rights reserved.

With OSS
Terms of ServicePrivacy PolicyCookie PolicyImprint

By

Commune Software