@reldens/cms v0.15.0
Reldens CMS
A powerful, flexible Content Management System built with Node.js, featuring an admin panel, multi-domain frontend support, enhanced templating with reusable content blocks, and automated installation.
Features
- Quick Setup
- Web-based installer with a guided setup process
- Automatic database schema creation and seeding
- Environment configuration generation
- Directory structure initialization
- Frontend Engine
- Multi-domain support with domain-specific templates and partials
- Dynamic routing from database-driven routes
- Entity-based URLs (e.g.,
/articles/123) - Template fallback system (domain → default → base)
- Layout system with body content layouts and page wrappers
- Reusable content blocks with
{{ entity() }}template functions - Collection rendering with filtering and loop support
- Entity access control for public/private content
- Static asset serving with Express integration as default
- Template engine with Mustache integration as default
- Custom 404 handling
- Admin Panel
- Full CRUD operations for all entities including content blocks
- File upload handling with multiple storage buckets
- Role-based authentication and access control
- Advanced filtering and search across entity properties
- Bulk operations (delete multiple records)
- Relationship management with foreign key support
- Template-driven UI with customizable admin themes
-️ Database & Entities
- Multiple database drivers (Prisma by default, others via DriversMap)
- Automatic entity generation from a database schema
- Relationship mapping and foreign key handling
- Custom entity configuration with validation rules
- Translation support for entity labels and properties
- Content blocks management via cms_blocks table
- Entity access control via cms_entity_access table
- Configuration & Architecture
- Environment-based configuration (.env file)
- Modular service architecture (Frontend, AdminManager, DataServer, TemplateEngine)
- Event-driven system with hooks for customization
- Extensible authentication (database users or custom callbacks)
- File security with path validation and dangerous key filtering
Installation
Method 1: Automated Web Installer
npx reldens-cmsNavigate to http://localhost:8080 and follow the installation wizard.
Method 2: Manual Setup
const { Manager } = require('@reldens/cms');
const cms = new Manager({
projectRoot: process.cwd(),
entityAccess: {
cmsPages: { public: true, operations: ['read'] },
products: { public: true, operations: ['read'] },
users: { public: false }
}
});
cms.start();Configuration
Environment Variables
RELDENS_APP_HOST=http://localhost
RELDENS_APP_PORT=8080
RELDENS_ADMIN_ROUTE_PATH=/admin
RELDENS_ADMIN_SECRET=your-secret-key
RELDENS_DB_CLIENT=mysql
RELDENS_DB_HOST=localhost
RELDENS_DB_PORT=3306
RELDENS_DB_NAME=cms_db
RELDENS_DB_USER=username
RELDENS_DB_PASSWORD=password
RELDENS_STORAGE_DRIVER=prisma
RELDENS_DEFAULT_DOMAIN=example.com
RELDENS_DOMAIN_MAPPING={"dev.example.com":"development"}
RELDENS_SITE_KEY_MAPPING={"example.com":"main"}Custom Entity Configuration
const entityConfig = {
articles: {
listProperties: ['title', 'status', 'created_at'],
showProperties: ['title', 'content', 'author', 'status'],
editProperties: ['title', 'content', 'author_id', 'status'],
filterProperties: ['status', 'author_id'],
titleProperty: 'title',
parentItemLabel: 'Content',
properties: {
title: { type: 'string', isRequired: true },
content: { type: 'text' },
author_id: { type: 'reference', reference: 'users' },
featured_image: {
type: 'string',
isUpload: true,
allowedTypes: 'image',
bucket: 'uploads'
}
}
}
};
const cms = new Manager({
entitiesConfig: entityConfig
});Enhanced Templating System
Template Functions
Templates support dynamic content blocks, entity rendering, and collections:
Single Entity Rendering:
<!-- Render by any identifier field (like 'name' for content blocks) -->
{{ entity('cmsBlocks', 'header-main', 'name') }}
{{ entity('cmsBlocks', 'sidebar-left', 'name') }}
<!-- Render by ID (default identifier) -->
{{ entity('products', '123') }}
{{ entity('cmsPages', '1') }}Single Field Collections:
<!-- Extract and concatenate a single field from multiple records -->
{{ collection('cmsBlocks', {"status": "active", "category": "navigation"}, 'content') }}
{{ collection('products', {"featured": true}, 'title') }}Loop Collections:
<!-- Loop through records with full template rendering -->
{{ #collection('cmsBlocks', {"status": "active"}) }}
<div class="block">
<h3>{{row.title}}</h3>
<div class="content">{{row.content}}</div>
</div>
{{ /collection('cmsBlocks') }}
{{ #collection('products', {"category": "electronics"}) }}
<div class="product">
<h4>{{row.name}}</h4>
<p>Price: ${{row.price}}</p>
<img src="{{row.image}}" alt="{{row.name}}">
</div>
{{ /collection('products') }}Layout System
The CMS uses a two-tier layout system:
page.html - Full HTML wrapper:
<!DOCTYPE html>
<html lang="{{locale}}">
<head>
<title>{{title}}</title>
<meta name="description" content="{{description}}"/>
<link href="/css/styles.css" rel="stylesheet"/>
</head>
<body class="{{siteHandle}}">
{{{content}}}
<script src="/js/scripts.js"></script>
</body>
</html>layouts/default.html - Body content only:
{{ entity('cmsBlocks', 'header-main', 'name') }}
<main id="main" class="main-container">
<div class="container">
<div class="row">
<div class="col-md-3">
{{ entity('cmsBlocks', 'sidebar-left', 'name') }}
</div>
<div class="col-md-9">
{{{content}}}
</div>
</div>
</div>
</main>
{{ entity('cmsBlocks', 'footer-main', 'name') }}Pages can use different layouts by setting the layout field in cms_pages:
default- Header, sidebar, main content, footerfull-width- Full width without sidebarsminimal- Basic layout with minimal styling
Content Blocks
Create reusable content blocks in the cms_blocks table via admin panel:
INSERT INTO cms_blocks (name, title, content) VALUES
('contact-info', 'Contact Information', '<p>Email: info@example.com</p>'),
('product-sidebar', 'Product Categories',
'<div class="categories"><h3>Categories</h3><ul><li><a href="/products/electronics">Electronics</a></li></ul></div>');Entity Access Control
Control which entities are publicly accessible:
const cms = new Manager({
entityAccess: {
products: { public: true, operations: ['read'] },
cmsPages: { public: true, operations: ['read'] },
users: { public: false }
}
});Multi-Domain Setup
Directory Structure
templates/
├── layouts/
│ ├── default.html # Body content layouts
│ ├── full-width.html
│ └── minimal.html
├── domains/
│ ├── example.com/
│ │ ├── layouts/ # Domain-specific layouts
│ │ ├── partials/
│ │ │ ├── header.html
│ │ │ └── footer.html
│ │ ├── page.html # Domain-specific page wrapper
│ │ └── index.html
│ └── dev.example.com/
│ └── page.html
├── partials/
│ ├── header.html (default)
│ └── footer.html (default)
├── page.html (base HTML wrapper)
└── 404.htmlAdvanced Usage
Custom Authentication
const customAuth = async (email, password, roleId) => {
const user = await yourAuthService.authenticate(email, password);
return user && user.role_id === roleId ? user : false;
};
const cms = new Manager({
authenticationMethod: 'custom',
authenticationCallback: customAuth
});File Upload Configuration
const uploadConfig = {
mimeTypes: {
image: ['image/jpeg', 'image/png', 'image/webp'],
document: ['application/pdf', 'text/plain']
},
allowedExtensions: {
image: ['.jpg', '.jpeg', '.png', '.webp'],
document: ['.pdf', '.txt']
}
};
const cms = new Manager(uploadConfig);Event Hooks
cms.events.on('reldens.setupAdminRoutes', ({adminManager}) => {
// Add custom admin routes
adminManager.adminRouter.get('/custom', (req, res) => {
res.send('Custom admin page');
});
});
cms.events.on('adminEntityExtraData', ({entitySerializedData, entity}) => {
// Add extra data to admin views
entitySerializedData.customField = 'Custom Value';
});Default database Schema
Core Tables
routes- URL routing and SEO metadatacms_pages- Page content with layout assignmentscms_blocks- Reusable content blockscms_entity_access- Entity access control rulesentities_meta- Generic metadata storagecms_pages_meta- Page-specific metadata
Installation Options
The installer provides checkboxes for:
- CMS core tables
- User authentication system
- Default admin user
- Default homepage
- Default content blocks
- Entity access control rules
API Reference
Manager Class
start()- Initialize and start the CMSisInstalled()- Check if CMS is installedinitializeServices()- Initialize all services
Frontend Class
initialize()- Setup frontend routes and templateshandleRequest(req, res)- Main request handlerfindRouteByPath(path)- Database route lookupfindEntityByPath(path)- Entity-based URL handling
TemplateEngine Class
render(template, data, partials)- Main template rendering with enhanced functionsprocessEntityFunctions(template)- Process {{ entity() }} functionsprocessSingleFieldCollections(template)- Process single field collectionsprocessLoopCollections(template)- Process loop collectionsfetchEntityForTemplate(tableName, identifier, identifierField)- Load single entityfetchCollectionForTemplate(tableName, filtersJson)- Load entity collections
AdminManager Class
setupAdmin()- Initialize admin panelgenerateListRouteContent()- Entity list pagesgenerateEditRouteContent()- Entity edit formsprocessSaveEntity()- Handle form submissions
Installer Class
prepareSetup()- Setup installation routesexecuteInstallProcess()- Run installationgenerateEntities()- Create entity files
File Structure
project/
├── admin/
│ └── templates/ # Admin panel templates
├── templates/
│ ├── layouts/ # Body content layouts
│ ├── domains/ # Domain-specific templates
│ ├── partials/ # Shared template partials
│ ├── page.html # Base HTML wrapper
│ └── 404.html # Error page
├── public/
│ ├── css/ # Stylesheets
│ ├── js/ # Client scripts
│ └── assets/ # Static assets
├── entities/ # Generated entity classes
├── .env # Environment configuration
├── install.lock # Installation lock file
└── index.js # Main application fileContributing
- Fork the repository
- Create a feature branch
- Follow the coding standards in the JavaScript rules
- Submit a pull request
Need something specific?
Request a feature here: https://www.reldens.com/features-request
Documentation
https://www.reldens.com/documentation/cms
License
MIT License - see LICENSE file for details.
