Content Management
SaaSyBase includes a full blog CMS, editable site pages, and a unified image/file storage system — all managed through the admin dashboard.
Blog & CMS
A full-featured blog is built into the app with public-facing pages, admin CRUD operations, rich text editing, and SEO support.
Routes
| Type | Route | Purpose |
|---|---|---|
| Public | /blog | Blog listing page |
| Public | /blog/[slug] | Individual blog post |
| Public | /blog/category/[category] | Posts filtered by category |
| Admin | /admin/blog | List, create, edit, and delete posts |
Rich text editing
Blog posts use the TipTap editor, which supports images, links, colors, text alignment, YouTube embeds, horizontal rules, and more. Content is stored as HTML and sanitized via lib/htmlSanitizer.ts to prevent XSS attacks.
Official docs: TipTap docs.
Categories
Blog posts use a many-to-many category system. A post can belong to multiple categories, and categories can contain multiple posts. Categories are managed in the admin blog interface.
SEO fields
Every blog post and site page includes dedicated SEO fields:
metaTitle,metaDescription,canonicalUrl,noIndex- Open Graph:
ogTitle,ogDescription,ogImage
Note
SitePage model (shared with editable site pages) and differentiated by the collection field (page vs blog).Tip
Site Pages
Editable public pages like Terms, Privacy, and Refund Policy are managed in the admin dashboard. Core pages are seeded automatically if they don't exist.
Routes
| Type | Route | Purpose |
|---|---|---|
| Admin | /admin/pages | List, create, and edit site pages |
| Public | /terms | Terms of service |
| Public | /privacy | Privacy policy |
| Public | /refund-policy | Refund policy |
| Public | /[slug] | Dynamic catch-all for custom pages |
Template variables
Pages support template variables that are interpolated at render time from admin settings. For example, {{siteName}} is replaced with your configured site name.
Note
Image & File Uploads
SaaSyBase includes a unified file storage system for managing images, logos, and other public assets. These are managed via the built-in image picker inside the blog editor and site configuration pages.
Storage Providers
The active storage provider is determined by the FILE_STORAGE environment variable.
- Local Filesystem (
fs): The default behavior. Files are saved directly topublic/_uploads/and served automatically by Next.js. Ideal for local development or single-server deployments. - S3-Compatible (
s3): Recommended for production on serverless platforms like Vercel. Works with AWS S3, Cloudflare R2, MinIO, or DigitalOcean Spaces.
Note
FILE_STORAGE="s3" before you enable admin-managed uploads in production if you expect files to survive redeploys or instance replacement.S3 Configuration
To enable S3 uploads, configure the following environment variables in your .env file:
FILE_STORAGE="s3"FILE_S3_BUCKET: Your bucket nameAWS_REGION: Your bucket regionAWS_ACCESS_KEY_ID&AWS_SECRET_ACCESS_KEYFILE_S3_ENDPOINT: (Optional) For non-AWS providers like R2 or SpacesFILE_CDN_DOMAIN: (Optional) A custom CDN URL to serve the assets through
Leave FILE_CDN_DOMAIN unset if you are happy serving files directly from the bucket origin. Set it when you want a custom asset domain or an extra CDN layer in front of S3-compatible storage.
Security & Scopes
The backend API (/api/admin/file/upload) is strictly protected by the admin role guard and rate-limited. It accepts a scope parameter to organize uploads internally:
file: General assets (blog images, hero banners).logo: Branding assets (site logos, favicons).
Note
lib/htmlSanitizer.ts before storage to prevent active content from riding along with the upload.
