@maplex-studio/macustomise
v1.2.1
Published
A powerful Express.js middleware for managing user theme customization with database persistence. Built to work seamlessly with Tailwind CSS and shadcn/ui components.
Downloads
35
Readme
MaCustomise
A powerful Express.js middleware for managing user theme customization with database persistence. Built to work seamlessly with Tailwind CSS and shadcn/ui components.
Features
- 🎨 Complete Theme Management - Colors, fonts, radius, shadows, and more
- 💾 Database Persistence - Uses your existing madatabase instance
- 🚀 Express Middleware - Drop-in solution for theme APIs
- 🌐 Google Fonts Integration - Automatic font loading and management
- 🔒 User-based Themes - Per-user theme storage with optional public themes
- ⚡ Built-in Caching - Configurable caching for better performance
- 📱 CSS Generation - Automatic CSS variable generation
- 🛡️ Type Safety - Full TypeScript support for frontend integration
Installation
npm install @maplex-studio/macustomise @maplex-studio/madatabase expressQuick Start
import express = from 'express';
import { Database } from '@maplex-studio/madatabase';
import { createThemeMiddleware } = from '@maplex-studio/macustomise';
const app = express();
const db = new Database();
app.use(express.json());
// Initialize database
db.connect().then(() => {
// Add theme middleware
app.use(createThemeMiddleware({
database: db,
maxThemesPerUser: 15,
enablePublicThemes: true,
enableCaching: true
}));
app.listen(3000, () => {
console.log('Server running on port 3000');
console.log('Theme API available at /api/theme');
});
});Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| database | Database | required | Your madatabase instance |
| tableName | string | 'themes' | Database table name for themes |
| routePrefix | string | '/api/theme' | Base route for theme endpoints |
| enableCaching | boolean | true | Enable in-memory caching |
| cacheTTL | number | 300000 | Cache TTL in milliseconds (5 min) |
| maxThemesPerUser | number | 10 | Maximum themes per user |
| enablePublicThemes | boolean | false | Allow public/shared themes |
API Endpoints
GET /themes
Get all themes for a user or public themes.
Query Parameters:
userId(optional) - User ID to fetch themes for
// Get user themes
const response = await fetch('/api/theme/themes?userId=user123');
const themes = await response.json();
// Get public themes (if enabled)
const response = await fetch('/api/theme/themes');
const publicThemes = await response.json();GET /themes/:id
Get a specific theme by ID.
const response = await fetch('/api/theme/themes/theme-id-123');
const theme = await response.json();POST /themes
Create or update a theme.
const themeData = {
name: 'My Custom Theme',
userId: 'user123',
colors: {
'primary': '#3b82f6',
'secondary': '#64748b',
'background': '#ffffff',
// ... more colors
},
radius: 0.5,
shadows: {
enabled: true,
opacity: 0.1,
blur: 4
},
fonts: {
sans: 'Inter',
serif: 'Source Serif 4',
mono: 'JetBrains Mono'
},
isPublic: false
};
const response = await fetch('/api/theme/themes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(themeData)
});
const savedTheme = await response.json();DELETE /themes/:id
Delete a theme.
Query Parameters:
userId(optional) - User ID for authorization
const response = await fetch('/api/theme/themes/theme-id-123?userId=user123', {
method: 'DELETE'
});GET /default
Get the default theme.
const response = await fetch('/api/theme/default');
const defaultTheme = await response.json();GET /css/:id
Generate CSS for a theme.
// Get CSS for a specific theme
const response = await fetch('/api/theme/css/theme-id-123');
const css = await response.text();
// Get CSS for default theme
const response = await fetch('/api/theme/css/default');
const defaultCSS = await response.text();Theme Structure
{
id: 'theme-uuid',
userId: 'user123',
name: 'My Theme',
colors: {
'background': '#ffffff',
'foreground': '#0a0a0a',
'primary': '#0a0a0a',
'primary-foreground': '#ffffff',
'secondary': '#f5f5f5',
'secondary-foreground': '#0a0a0a',
'accent': '#f5f5f5',
'accent-foreground': '#0a0a0a',
'muted': '#f5f5f5',
'muted-foreground': '#737373',
'card': '#ffffff',
'card-foreground': '#0a0a0a',
'border': '#e5e5e5',
'input': '#e5e5e5',
'ring': '#a3a3a3',
'destructive': '#ef4444',
'destructive-foreground': '#ffffff'
},
radius: 0.5,
shadows: {
enabled: true,
opacity: 0.05,
blur: 2
},
fonts: {
sans: 'Inter',
serif: 'Source Serif 4',
mono: 'JetBrains Mono'
},
isPublic: false,
isDefault: false,
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
}Advanced Usage
Custom Middleware Setup
const { ThemeMiddleware } = require('macustomise');
const themeMiddleware = new ThemeMiddleware({
database: db,
tableName: 'custom_themes',
maxThemesPerUser: 20,
enablePublicThemes: true,
cacheTTL: 600000 // 10 minutes
});
app.use('/themes', themeMiddleware.getRouter());Error Handling
app.use('/api/theme', createThemeMiddleware({
database: db
}));
// Error handling middleware
app.use((err, req, res, next) => {
if (err.message.includes('theme')) {
res.status(500).json({ error: 'Theme operation failed' });
} else {
next(err);
}
});Integration with Authentication
// Add auth middleware before theme routes
app.use('/api/theme', authenticateUser, createThemeMiddleware({
database: db
}));
function authenticateUser(req, res, next) {
// Your auth logic here
const userId = getUserIdFromToken(req.headers.authorization);
req.userId = userId;
next();
}Frontend Integration
Use with the React Theme Customizer component:
import ThemeCustomizer from './ThemeCustomizer';
function App() {
return (
<ThemeCustomizer
apiEndpoint="/api/theme"
userId="user123"
onThemeChange={(theme) => {
console.log('Theme changed:', theme);
}}
/>
);
}Database Schema
The middleware automatically creates a themes table with the following structure:
| Column | Type | Description |
|--------|------|-------------|
| id | INTEGER | Primary key (auto-generated) |
| userId | STRING | User ID (nullable for public themes) |
| name | STRING | Theme name |
| colors | JSON | Color configuration object |
| radius | DECIMAL(3,2) | Border radius value |
| shadows | JSON | Shadow configuration object |
| fonts | JSON | Font configuration object |
| isPublic | BOOLEAN | Whether theme is public |
| isDefault | BOOLEAN | Whether theme is the default |
| createdAt | DATE | Creation timestamp |
| updatedAt | DATE | Last update timestamp |
CSS Variables Generated
The middleware generates CSS with these variables:
:root {
/* Colors */
--background: #ffffff;
--foreground: #0a0a0a;
--primary: #0a0a0a;
--primary-foreground: #ffffff;
/* ... all color variables */
/* Spacing */
--radius: 0.5rem;
/* Effects */
--shadow-opacity: 0.05;
--shadow-blur: 2px;
/* Fonts */
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
--font-serif: 'Source Serif 4', ui-serif, serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
}Performance Considerations
- Caching: Enable caching for better performance in production
- Database Indexing: The
userIdfield is automatically indexed - Font Loading: Google Fonts are loaded dynamically only when needed
- CSS Generation: CSS is generated on-demand and can be cached by browsers
License
MIT
Support
For issues and questions:
- Create an issue on GitHub
- Check existing documentation
- Review the examples in this README
Built with ❤️ for developers who love customizable themes.
