Prolifto
Developer guide

Storage

Configure Cloudinary or S3-compatible storage for media and PDFs.

Media and generated documents are stored through @prolifto/infrastructure. The provider is selected by STORAGE_PROVIDER.

Providers

ProviderUse it for
cloudinaryDefault. Managed image and video storage
s3AWS S3, Cloudflare R2, SeaweedFS, RustFS, or another S3-compatible store

Cloudinary

STORAGE_PROVIDER="cloudinary"
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="..."
NEXT_PUBLIC_CLOUDINARY_PRESET_NAME="..."
CLOUDINARY_API_KEY="..."
CLOUDINARY_API_SECRET="..."

Cloudinary is the default when STORAGE_PROVIDER is unset. The adapter uploads to a folder, returns the provider URL, and supports deleting and downloading assets.

S3-compatible storage

STORAGE_PROVIDER="s3"
S3_ENDPOINT="http://localhost:8333"
S3_REGION="us-east-1"
S3_ACCESS_KEY_ID="admin"
S3_SECRET_ACCESS_KEY="admin"
S3_BUCKET="prolifto"
S3_FORCE_PATH_STYLE="true"
S3_PUBLIC_URL_BASE="http://localhost:8333/prolifto"
S3_AUTO_CREATE_BUCKET="false"
S3_AUTO_PUBLIC_READ="false"

Notes:

  • S3_FORCE_PATH_STYLE defaults to true, which works for SeaweedFS and most local providers.
  • S3_PUBLIC_URL_BASE controls the URL returned for uploaded objects. For virtual-hosted buckets, set it to the real public bucket or CDN base.
  • S3_AUTO_CREATE_BUCKET and S3_AUTO_PUBLIC_READ are development conveniences and default to false. Keep them off for managed providers.
  • The adapter returns public object URLs. Front a private bucket with a CDN or add presigned-URL support before using one in production.
  • Mirror S3_ENDPOINT and S3_PUBLIC_URL_BASE in the storefront so next/image and the content security policy allow uploaded media.
  • Uploads are capped at 100 MB, with content-type detection and host validation for URL imports.

Local development

Start SeaweedFS:

pnpm storage:up
pnpm storage:logs
pnpm storage:down
pnpm storage:reset

RustFS is an alternative:

pnpm rustfs:up

RustFS exposes a console at http://localhost:9001 (rustfsadmin / rustfsadmin) and its S3 API at http://localhost:9000. Only run one storage service at a time.

Switching providers

Switching STORAGE_PROVIDER does not migrate existing media rows. Keep the previous provider reachable until old assets are deleted, or migrate the objects and update media.provider / media.url.

Generated PDFs

Invoice and receipt PDFs are generated by Puppeteer and stored through the same storage abstraction. If PDF generation fails, check:

  • The storage provider credentials.
  • The Puppeteer executable (PUPPETEER_EXECUTABLE_PATH, PUPPETEER_NO_SANDBOX).
  • The storage health endpoint.

Health check

The admin health endpoint checks the database and storage:

curl http://localhost:3000/api/my-store/health

A storage failure returns degraded; a database failure returns down.

On this page