TEMPLATE SYSTEM QUICKSTART - nself-org/nchat GitHub Wiki
Version: 1.0.0 Date: 2026-02-03
The Ι³Chat template system allows you to instantly transform your chat application to mimic popular platforms like WhatsApp, Telegram, Slack, or Discord. Each template includes:
- Complete UI redesign
- Platform-specific features
- Custom terminology
- Authentic color schemes
- Component overrides
import { useTemplate } from '@/templates/hooks/use-template'
function MyComponent() {
const {
template, // Current template object
templateId, // 'default' | 'whatsapp' | 'telegram' | 'slack' | 'discord'
colors, // Theme colors
features, // Feature config
terminology, // Custom labels
switchTemplate, // Function to switch templates
} = useTemplate()
return (
<div style={{ backgroundColor: colors.surfaceColor }}>
<h1>{template.name}</h1>
</div>
)
}import { useTemplate } from '@/templates/hooks/use-template'
function TemplateSwitcher() {
const { switchTemplate, templateId, isLoading } = useTemplate()
return (
<select
value={templateId}
onChange={(e) => switchTemplate(e.target.value)}
disabled={isLoading}
>
<option value="default">Ι³Chat</option>
<option value="whatsapp">WhatsApp</option>
<option value="telegram">Telegram</option>
<option value="slack">Slack</option>
<option value="discord">Discord</option>
</select>
)
}import { useThemeColors } from '@/templates/hooks/use-template'
function Card() {
const colors = useThemeColors()
return (
<div
style={{
backgroundColor: colors.cardColor,
color: colors.textColor,
border: `1px solid ${colors.borderColor}`,
}}
>
<h2 style={{ color: colors.primaryColor }}>Title</h2>
<p style={{ color: colors.textMutedColor }}>Description</p>
</div>
)
}import { useFeature } from '@/templates/hooks/use-template'
function ThreadButton({ messageId }) {
const hasThreads = useFeature('threads')
// Hide button if template doesn't support threads
if (!hasThreads) return null
return <button onClick={() => openThread(messageId)}>Reply in thread</button>
}import { useTerminology } from '@/templates/hooks/use-template'
function CreateChannelButton() {
const { t } = useTerminology()
return (
<button>
{t('createChannel')}
{/*
Returns:
- "Create Channel" for Ι³Chat/Slack/Discord
- "New Chat" for WhatsApp
- "New Chat" for Telegram
*/}
</button>
)
}Set template via environment variable:
# .env.local
NEXT_PUBLIC_PLATFORM_TEMPLATE=whatsappOverride template settings:
# .env.local
NEXT_PUBLIC_PLATFORM_TEMPLATE=slack
NEXT_PUBLIC_THEME_MODE=dark
NEXT_PUBLIC_SIDEBAR_POSITION=right
NEXT_PUBLIC_SIDEBAR_WIDTH=280
NEXT_PUBLIC_MESSAGE_DENSITY=compact
NEXT_PUBLIC_THEME_PRIMARY=#4A154BBest For: Teams wanting full features
Theme: Cyan/Blue (#00D4FF) Mode: Dark
Features:
- β All features enabled
- β Threads (panel)
- β Voice channels
- β E2E encryption
- β Bots & webhooks
Best For: Personal/small teams
Theme: Green (#25D366) Mode: Light
Features:
- β Chat bubbles
- β Double-check receipts (ββ)
- β Voice messages
- β Status/Stories
- β No threads
- β No public channels
Best For: Large communities
Theme: Blue (#0088CC) / Purple (#8774E1) dark Mode: System
Features:
- β Chat folders
- β Secret chats
- β Bots
- β Scheduled messages
- β Polls & quizzes
- β No voice channels
Best For: Professional teams
Theme: Aubergine (#4A154B) Mode: System
Features:
- β Thread panel
- β Workspace switcher
- β Huddles
- β App integrations
- β Workflows
- β No voice channels
Best For: Gaming/large groups
Theme: Blurple (#5865F2) Mode: Dark
Features:
- β Server list
- β Voice channels
- β Role colors
- β Rich embeds
- β Member list
- β No stories
function MessageActions({ message }) {
const { features } = useTemplate()
return (
<div>
{features.threads && <ThreadButton />}
{features.reactions && <ReactButton />}
{features.voiceMessages && <VoiceButton />}
{features.codeBlocks && <CodeButton />}
</div>
)
}function Message({ message }) {
const { template } = useTemplate()
// Use template-specific message component if available
const MessageComponent = template.components?.MessageItem ?? DefaultMessage
return <MessageComponent {...message} />
}function StatusBadge({ status }) {
const colors = useThemeColors()
const bgColor = {
online: colors.successColor,
away: colors.warningColor,
offline: colors.errorColor,
}[status]
return (
<span
style={{
backgroundColor: bgColor,
color: 'white',
padding: '4px 8px',
borderRadius: '4px',
}}
>
{status}
</span>
)
}function TemplatePreview() {
const { switchTemplate, templateId } = useTemplate()
const [originalTemplate, setOriginalTemplate] = useState(templateId)
const handlePreview = async (id) => {
setOriginalTemplate(templateId)
await switchTemplate(id)
}
const handleRevert = async () => {
await switchTemplate(originalTemplate)
}
return (
<div>
<button onClick={() => handlePreview('whatsapp')}>Preview WhatsApp</button>
<button onClick={handleRevert}>Revert</button>
</div>
)
}Main hook for accessing template system.
const {
template, // PlatformTemplate | null
templateId, // TemplateId
isLoading, // boolean
error, // Error | null
theme, // 'light' | 'dark'
setTheme, // (theme: 'light' | 'dark' | 'system') => void
colors, // ThemeColors
layout, // LayoutConfig
features, // FeatureConfig
isFeatureEnabled, // (feature: keyof FeatureConfig) => boolean
terminology, // TerminologyConfig
t, // (key: keyof TerminologyConfig) => string
switchTemplate, // (templateId: TemplateId) => Promise<void>
applyOverrides, // (overrides: PartialTemplate) => void
} = useTemplate()Get theme colors only.
const colors: ThemeColors = useThemeColors()Check if a specific feature is enabled.
const hasThreads: boolean = useFeature('threads')
const hasVoiceMessages: boolean = useFeature('voiceMessages')Get terminology translation function.
const { terminology, t } = useTerminology()
// Get translated term
const label = t('channel') // "Channel" or "Chat"
const plural = t('channelPlural') // "Channels" or "Chats"Load a template programmatically.
import { loadTemplate } from '@/templates'
const template = await loadTemplate('whatsapp')Create a customized template.
import { customizeTemplate } from '@/templates'
const custom = customizeTemplate(baseTemplate, {
theme: {
light: { primaryColor: '#FF0000' },
},
layout: {
sidebarWidth: 320,
},
})All templates include these 16 color properties:
| Property | Description |
|---|---|
primaryColor |
Main brand color |
secondaryColor |
Secondary brand color |
accentColor |
Accent/highlight color |
backgroundColor |
Main background |
surfaceColor |
Cards/elevated surfaces |
cardColor |
Card backgrounds |
popoverColor |
Popovers/dropdowns |
textColor |
Primary text |
textMutedColor |
Secondary text |
textInverseColor |
Text on primary backgrounds |
borderColor |
Default borders |
borderMutedColor |
Subtle borders |
buttonPrimaryBg |
Primary button background |
buttonPrimaryText |
Primary button text |
buttonSecondaryBg |
Secondary button background |
buttonSecondaryText |
Secondary button text |
successColor |
Success messages |
warningColor |
Warning messages |
errorColor |
Error messages |
infoColor |
Info messages |
linkColor |
Hyperlinks |
focusRingColor |
Focus indicators |
selectionBg |
Text selection |
highlightBg |
Highlighted text |
Common features you can check:
| Feature | Telegram | Slack | Discord | |
|---|---|---|---|---|
threads |
β | β | β | β |
reactions |
β | β | β | β |
voiceMessages |
β | β | β | β |
codeBlocks |
β | β | β | β |
markdown |
β | β | β | β |
gifPicker |
β | β | β | β |
typing |
β | β | β | β |
readReceipts |
β | β | β | β |
presence |
β | β | β | β |
| Key | Ι³Chat/Slack | Telegram | Discord | |
|---|---|---|---|---|
workspace |
Workspace | Telegram | Server | |
channel |
Channel | Chat | Chat | Channel |
directMessage |
Direct Message | Chat | Chat | Direct Message |
thread |
Thread | Reply | Reply | Thread |
member |
Member | Participant | Member | Member |
createChannel |
Create Channel | New Chat | New Chat | Create Channel |
import { ThemeEditor } from '@/components/admin/theme-editor'
;<ThemeEditor
onSave={(colors) => console.log('Saved', colors)}
onExport={(colors) => console.log('Exported', colors)}
/>import { TemplateGallery } from '@/components/admin/template-gallery'
;<TemplateGallery />// Check if template exists
const templates = getAvailableTemplates()
console.log(
'Available:',
templates.map((t) => t.id)
)
// Check current template
const { template, error } = useTemplate()
if (error) console.error('Template error:', error)// Ensure TemplateProvider wraps your app
import { TemplateProvider } from '@/templates/hooks/use-template'
<TemplateProvider>
<YourApp />
</TemplateProvider>
// Check if CSS variables are generated
const style = document.documentElement.style
console.log('Primary:', style.getPropertyValue('--primary'))// Check if feature is enabled
const { isFeatureEnabled } = useTemplate()
console.log('Threads enabled:', isFeatureEnabled('threads'))
// Get feature config
const { features } = useTemplate()
console.log('Thread style:', features.threadStyle) // 'panel' | 'inline' | 'popup'-
Always wrap app in TemplateProvider
<TemplateProvider> <App /> </TemplateProvider>
-
Use hooks instead of direct imports
// β Good const colors = useThemeColors() // β Bad import { colors } from '@/templates/whatsapp/config'
-
Check features before rendering
// β Good { hasThreads && <ThreadButton /> } // β Bad ;<ThreadButton /> // Will always render
-
Use terminology for labels
// β Good const { t } = useTerminology() <button>{t('createChannel')}</button> // β Bad <button>Create Channel</button> // Hardcoded
-
Prefer CSS variables over inline styles
// β Good <div className="bg-surface text-foreground"> // β Bad <div style={{ backgroundColor: colors.surfaceColor }}>
-
Documentation:
/Users/admin/Sites/nself-chat/docs/WHITE-LABEL-TEMPLATES-COMPLETE.md -
Implementation:
/Users/admin/Sites/nself-chat/docs/TASKS-109-113-COMPLETE.md -
Types:
/Users/admin/Sites/nself-chat/src/templates/types.ts -
Presets:
/Users/admin/Sites/nself-chat/src/lib/theme-presets.ts
Quick Start Guide v1.0.0 Last Updated: 2026-02-03