Developer Resources
Storage Service Setup
Central place to configure uploads for both local disk and object storage (S3-compatible) deployments used by `@nomor/storage` and the Nest API module.
Storage Service Setup
Central place to configure uploads for both local disk and object storage (S3-compatible) deployments used by @nomor/storage and the Nest API module.
1. Install Dependencies
Already added to the monorepo, but make sure the workspace has these packages:
@nomor/storage(workspace package)@aws-sdk/client-s3sharpzod
Run pnpm install at the repo root if you have not pulled the updated lockfile.
2. Environment Variables
All envs live in apps/api/.env (or use apps/api/sample.env as a template).
env
# Local storage roots
UPLOAD_LOCATION=apps/api/uploads
# Object storage / S3 (optional)
STORAGE_BUCKET_ENDPOINT=http://localhost:9000
STORAGE_BUCKET_ACCESS_KEY=your_access_key
STORAGE_BUCKET_SECRET_KEY=your_secret_key
STORAGE_BUCKET_NAME=portfolio-storage
STORAGE_BUCKET_REGION=us-east-1
STORAGE_BUCKET_PUBLIC_URL=http://localhost:9000Leave the object storage variables empty to stay on local disk only.
3. Local Disk Only
- Ensure
UPLOAD_LOCATIONpoints to the writable directory (apps/api/uploadsby default). - Run the Nest API once or call
StorageManager.ensureLocalStructure()to create theimage,video,file,pdf, andxlsxfolders. - Uploads stay inside the repo and responses include
localPath/relativePathvalues.
4. Object storage / S3
- Set the object storage env vars above.
STORAGE_BUCKET_PUBLIC_URLis optional; when provided, response URLs use it instead of the raw endpoint. - Restart the API after updating envs so the
StorageManagerpicks up the remote config. - Upload responses now include
remoteKeyandremoteUrlpointing at the bucket while still retaining the local relative path.
5. Runtime Behavior
- All files are uploaded using Multer to the local
UPLOAD_LOCATIONfirst. StorageManageroptimizes images to WebP (quality 85, effort 6) whenoptimize=true.- When object storage is configured, the optimized file is pushed via AWS SDK v3 and the temporary local file is deleted (set
cleanupLocalOnSuccess: falsewhen instantiatingStorageManagerif you need to keep it). - When a remote upload fails and fallback is disabled, the temporary file is also removed to keep the API host stateless (
cleanupLocalOnFailuredefaults totruewhen object storage is enabled). - Fallback to disk only happens when object storage is not configured. If a remote upload fails,
StorageManagerthrowsStorageUploadFailedErrorso the caller can surface the error to clients.
6. Using the Storage Manager Elsewhere
import { StorageManager } from "@nomor/storage";
const storage = new StorageManager();
await storage.ensureLocalStructure();
const result = await storage.handleUpload(file, { optimize: true });This shared package allows other apps in the monorepo to reuse the same configuration surface.