Skip to documentation
Browse documentation
SimpcnDocsStorage configuration

The Simpcn handbook

Storage configuration

Separate upload credentials and endpoints from public asset delivery.

A TypeScript configuration

simpcn.config.ts
import type { UserConfig } from 'simpcn';

export default {
  root: 'public',
  // Keep essential assets local. Patterns are relative to root, without public/.
  // Example: ['favicon.ico', 'fonts/**', 'offline/**', 'images/fallback.png']
  exclude: [],
  publicBaseUrl: 'https://cdn.example.com/assets/',
  storage: {
    provider: 's3',
    bucket: 'YOUR_EXISTING_BUCKET',
    region: 'us-east-1',
    prefix: 'assets',
  },
} satisfies UserConfig;

Only TypeScript configuration with a default export is supported. Discovery walks up from the working directory. Paths inside the configuration are relative to that file; CLI path overrides are relative to the current working directory. The asset root defaults to public.

The bucket must exist. Exclude files with an exclude array of glob strings. Unknown configuration fields are rejected. Treat this executable TypeScript file as trusted project code.

Keep essential assets local

Some assets should stay with your application instead of depending on a separate CDN request. Keep fallback images, offline-page illustrations, essential icons, or fonts used by critical screens local when their availability matters more than moving them to storage.

Add these files or directories to exclude in simpcn.config.ts. This core setting applies to both the Next.js and Vite integrations and every supported storage provider.

simpcn.config.ts · choose the assets your app needs locally
root: 'public',
exclude: [
  'favicon.ico',
  'icons/**',
  'fonts/**',
  'offline/**',
  'images/fallback.png',
],

Patterns are relative to root. With root: 'public', use images/fallback.png to match public/images/fallback.png. Omit the leading slash and the public/ directory name. An empty array keeps every eligible file in the managed inventory.

Excluded files are left out of the managed inventory, so Simpcn does not upload them, rewrite their references, or require their CDN verification for a production build. Their original references continue through your framework's normal asset handling.

Source · remains local in development and production
<img src="/images/fallback.png" alt="Preview unavailable" />

Choosing a local asset does not add automatic fallback when a different CDN image fails. It also does not make a website work offline by itself: offline access still needs the application's caching or service-worker setup.

If you add exclusions after a migration, rebuild and redeploy to update compiled references. Keep the original files in your app. Previously uploaded copies remain in storage; Simpcn does not delete them.

Provider presets

ProviderConfigurationEvidence
s3Bucket and region; endpoint optional for AWS S3.S3-compatible adapter; live AWS not verified by repository integration tests.
minioAPI endpoint, bucket, region; path-style addressing selected.Local MinIO integration tests.
r2Account API endpoint, bucket, region: 'auto'.R2 configuration support; live R2 not verified by repository integration tests.
MinIO storage field — example local origin
storage: {
  provider: 'minio',
  endpoint: 'http://localhost:9000',
  bucket: 'YOUR_EXISTING_BUCKET',
  region: 'us-east-1',
  prefix: 'assets',
},
R2 storage field — replace placeholders
storage: {
  provider: 'r2',
  endpoint: 'https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com',
  bucket: 'YOUR_EXISTING_BUCKET',
  region: 'auto',
  prefix: 'assets',
},

Other S3-compatible services require their own integration testing, especially conditional upload behavior. A provider name does not guarantee equivalent service behavior.

Upload origin ≠ public delivery URL

storage.endpoint is the storage API used for uploads. publicBaseUrl is the public root used by compiled application references. Simpcn never derives one from the other.

Include the object prefix exactly once. With prefix: 'assets', use https://cdn.example.com/assets/. A local MinIO path-style delivery URL would include both bucket and prefix: http://localhost:9000/YOUR_EXISTING_BUCKET/assets/.

Production needs public read access through the chosen delivery origin. Upload credentials do not make assets public. Configure bucket access, CDN origins, CORS, and cache behavior with the provider.

Credentials stay outside browser code

.env.local — beside simpcn.config.ts
AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY
AWS_SECRET_ACCESS_KEY=YOUR_SECRET_KEY
# AWS_SESSION_TOKEN=OPTIONAL_SESSION_TOKEN

The CLI loads local environment files before loading configuration and creating the adapter. Shell values take precedence. The standard AWS SDK credential chain remains available. Do not paste secrets into configuration, commit them, or add browser-public environment prefixes.

Give migration credentials the object read/check and upload permissions needed for the selected bucket and prefix. Remote checks and verification use HEAD requests; Simpcn does not need to delete objects.

State, caching, and CI

Keep simpcn.config.ts at the project root. Deployment state defaults to simpcn/deployment-state.json; the local inventory defaults to simpcn/.build/manifest.json. Next.js also generates helpers under simpcn/.build/next/. Init creates or updates .gitignore to ignore the build directory and temporary state files while leaving deployment state trackable. Both state and manifest must stay outside the asset root.

After migration, commit deployment state alongside the matching source files, public assets, config, and lockfile. This lets a fresh Vercel or other CI checkout validate asset hashes and compile CDN URLs without uploading again or needing storage credentials. The build regenerates its local files. Missing or stale verification still fails the build: migrate changed assets and commit the updated state before deploying. Credentials stay in local environment files or your CI secret store.

Existing explicit paths remain supported. To adopt the new layout, update stateFile and manifestFile, move the existing deployment state to its configured location, and ensure no broad ignore rule hides it.

The default cache policy is public, max-age=0, must-revalidate. Configure cacheControl deliberately. Existing keys are replaced only with --overwrite; review CDN caches after replacement. The package does not purge caches, generate hashed delivery filenames, create buckets, or perform multipart uploads. Uploads above 5 GiB are rejected.

Something unclear? Open an issue.

Simpcn v0.1.3 · Experimental integrations are labeled.