diff --git a/app/javascript/dashboard/components-next/template-preview/README.md b/app/javascript/dashboard/components-next/template-preview/README.md
new file mode 100644
index 000000000..38aadc1ef
--- /dev/null
+++ b/app/javascript/dashboard/components-next/template-preview/README.md
@@ -0,0 +1,121 @@
+# Template Preview System
+
+A comprehensive template preview system for WhatsApp and Twilio templates that provides real-time visual previews during template selection, campaign creation, and displays accurate rendered templates in message threads.
+
+## Features
+
+- **Multi-Platform Support**: WhatsApp and Twilio templates
+- **Real-Time Preview**: Interactive variable editing with live preview updates
+- **Template Type Detection**: Automatic detection and routing to appropriate preview components
+- **Variable Validation**: Real-time validation with error states
+- **Responsive Design**: Works across mobile and desktop
+- **Storybook Integration**: Complete component documentation and examples
+
+## Supported Template Types
+
+### WhatsApp Templates
+- **Text Templates**: Simple text with variables
+- **Media Templates**: Image/Video/Document headers with text
+- **Interactive Templates**: URL, Phone, Quick Reply buttons
+- **Copy Code Templates**: Discount/promo code functionality
+- **Combined Templates**: Media + Text + Buttons
+
+### Twilio Templates
+- **Text Templates**: Simple text with variables
+- **Media Templates**: Text + Image/Video
+- **Quick Reply Templates**: Interactive action buttons
+
+## Usage
+
+### Basic Usage
+
+```vue
+
+
+
+
+
+```
+
+### Preview Modes
+
+- **`display`**: Static preview with populated variables (for sent messages)
+- **`interactive`**: Live editing with input fields (for campaign creation)
+- **`placeholder`**: Show example values from template definition
+
+### Integration Examples
+
+See the stories in `stories/TemplatePreview.stories.js` for comprehensive examples covering all template types and use cases.
+
+## Component Architecture
+
+```
+template-preview/
+├── TemplatePreview.vue # Main container component
+├── components/ # Shared UI components
+│ ├── MessageBubble.vue # Platform-specific message bubble
+│ └── VariableInput.vue # Variable input field
+├── whatsapp/ # WhatsApp-specific previews
+│ ├── WhatsAppTextPreview.vue
+│ ├── WhatsAppMediaPreview.vue
+│ ├── WhatsAppButtonPreview.vue
+│ └── WhatsAppCopyCodePreview.vue
+├── twilio/ # Twilio-specific previews
+│ ├── TwilioTextPreview.vue
+│ ├── TwilioMediaPreview.vue
+│ └── TwilioQuickReplyPreview.vue
+└── stories/ # Storybook documentation
+ └── TemplatePreview.stories.js
+```
+
+## Services & Composables
+
+- **`TemplateTypeDetector`**: Identifies template types across platforms
+- **`TemplateNormalizer`**: Converts platform-specific formats to unified structure
+- **`useTemplateVariables`**: Composable for variable management and validation
+
+## Development
+
+### Running Storybook
+
+```bash
+npm run storybook
+```
+
+### Adding New Template Types
+
+1. Add type detection logic in `TemplateTypeDetector.js`
+2. Add normalization logic in `TemplateNormalizer.js`
+3. Create preview component in appropriate platform folder
+4. Add component mapping in `TemplatePreview.vue`
+5. Add story examples in `TemplatePreview.stories.js`
+
+## Design System
+
+The system uses Chatwoot's existing design tokens and follows the established component patterns:
+
+- **Colors**: Uses `n-alpha-2`, `n-slate-12`, etc. from the design system
+- **Spacing**: Consistent with existing message bubble components
+- **Typography**: Matches WhatsApp/platform styling
+- **Buttons**: Uses existing `Button.vue` component
+
+## Testing
+
+The system includes comprehensive Storybook stories that serve as both documentation and visual regression testing. Each template type and mode combination is covered.
\ No newline at end of file
diff --git a/app/javascript/dashboard/components-next/template-preview/TemplatePreview.story.vue b/app/javascript/dashboard/components-next/template-preview/TemplatePreview.story.vue
new file mode 100644
index 000000000..3694071d7
--- /dev/null
+++ b/app/javascript/dashboard/components-next/template-preview/TemplatePreview.story.vue
@@ -0,0 +1,322 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/template-preview/TemplatePreview.vue b/app/javascript/dashboard/components-next/template-preview/TemplatePreview.vue
new file mode 100644
index 000000000..aa1479bac
--- /dev/null
+++ b/app/javascript/dashboard/components-next/template-preview/TemplatePreview.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/template-preview/TemplatePreviewExamples.story.vue b/app/javascript/dashboard/components-next/template-preview/TemplatePreviewExamples.story.vue
new file mode 100644
index 000000000..972c3e4f0
--- /dev/null
+++ b/app/javascript/dashboard/components-next/template-preview/TemplatePreviewExamples.story.vue
@@ -0,0 +1,792 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/dashboard/components-next/template-preview/index.js b/app/javascript/dashboard/components-next/template-preview/index.js
new file mode 100644
index 000000000..b7f1bd6b0
--- /dev/null
+++ b/app/javascript/dashboard/components-next/template-preview/index.js
@@ -0,0 +1,6 @@
+// Main Template Preview Component
+export { default as TemplatePreview } from './TemplatePreview.vue';
+
+// Core Services
+export { TemplateTypeDetector } from 'dashboard/services/TemplateTypeDetector';
+export { TemplateNormalizer } from 'dashboard/services/TemplateNormalizer';
diff --git a/app/javascript/dashboard/services/TemplateNormalizer.js b/app/javascript/dashboard/services/TemplateNormalizer.js
new file mode 100644
index 000000000..7ff69a44e
--- /dev/null
+++ b/app/javascript/dashboard/services/TemplateNormalizer.js
@@ -0,0 +1,153 @@
+import { TemplateTypeDetector } from './TemplateTypeDetector';
+
+/**
+ * TemplateNormalizer - Convert platform-specific formats to unified structure
+ */
+export class TemplateNormalizer {
+ /**
+ * Normalize WhatsApp template to unified format
+ * @param {Object} template - WhatsApp template object
+ * @returns {Object} - Normalized template
+ */
+ static normalizeWhatsApp(template) {
+ const components = template.components || [];
+
+ return {
+ id: template.id,
+ name: template.name,
+ platform: 'whatsapp',
+ type: TemplateTypeDetector.detectWhatsAppType(template),
+ parameterFormat: template.parameter_format || 'POSITIONAL',
+ header: components.find(c => c.type === 'HEADER'),
+ body: components.find(c => c.type === 'BODY'),
+ footer: components.find(c => c.type === 'FOOTER'),
+ buttons: components.find(c => c.type === 'BUTTONS')?.buttons || [],
+ variables: this.extractWhatsAppVariables(template),
+ category: template.category,
+ language: template.language,
+ originalTemplate: template,
+ };
+ }
+
+ /**
+ * Normalize Twilio template to unified format
+ * @param {Object} template - Twilio template object
+ * @returns {Object} - Normalized template
+ */
+ static normalizeTwilio(template) {
+ const typeData = template.types?.[`twilio/${template.template_type}`] || {};
+
+ return {
+ contentSid: template.content_sid,
+ name: template.friendly_name,
+ platform: 'twilio',
+ type: TemplateTypeDetector.detectTwilioType(template),
+ body: template.body || typeData.body,
+ media: typeData.media || [],
+ actions: typeData.actions || [],
+ variables: template.variables || {},
+ category: template.category || 'utility',
+ language: template.language || 'en',
+ originalTemplate: template,
+ };
+ }
+
+ /**
+ * Extract variables from WhatsApp template
+ * @param {Object} template - WhatsApp template object
+ * @returns {Object} - Variables object with example values
+ */
+ static extractWhatsAppVariables(template) {
+ const variables = {};
+ const components = template.components || [];
+
+ components.forEach(component => {
+ // Extract from text content
+ if (component.text) {
+ const matches = component.text.match(/\{\{([^}]+)\}\}/g) || [];
+ matches.forEach(match => {
+ const variable = match.replace(/[{}]/g, '');
+
+ if (template.parameter_format === 'NAMED') {
+ // Named parameters: {{customer_name}}
+ const example =
+ component.example?.body_text_named_params?.find(
+ p => p.param_name === variable
+ )?.example || '';
+ variables[variable] = example;
+ } else {
+ // Positional parameters: {{1}}, {{2}}
+ const position = parseInt(variable, 10) - 1;
+ const example = component.example?.body_text?.[0]?.[position] || '';
+ variables[variable] = example;
+ }
+ });
+ }
+
+ // Extract from button URLs
+ if (component.buttons) {
+ component.buttons.forEach(button => {
+ if (button.url) {
+ const matches = button.url.match(/\{\{([^}]+)\}\}/g) || [];
+ matches.forEach(match => {
+ const variable = match.replace(/[{}]/g, '');
+ const example = button.example?.[0] || '';
+ variables[variable] = example;
+ });
+ }
+ });
+ }
+ });
+
+ return variables;
+ }
+
+ /**
+ * Extract variables from Twilio template
+ * @param {Object} template - Twilio template object
+ * @returns {Object} - Variables object with example values
+ */
+ static extractTwilioVariables(template) {
+ const variables = {};
+
+ // Extract from body text
+ if (template.body) {
+ const matches = template.body.match(/\{\{([^}]+)\}\}/g) || [];
+ matches.forEach(match => {
+ const variable = match.replace(/[{}]/g, '');
+ variables[variable] = template.variables?.[variable] || '';
+ });
+ }
+
+ // Extract from media URLs
+ const typeData = template.types?.[`twilio/${template.template_type}`] || {};
+ if (typeData.media) {
+ typeData.media.forEach(mediaUrl => {
+ const matches = mediaUrl.match(/\{\{([^}]+)\}\}/g) || [];
+ matches.forEach(match => {
+ const variable = match.replace(/[{}]/g, '');
+ variables[variable] = template.variables?.[variable] || '';
+ });
+ });
+ }
+
+ return variables;
+ }
+
+ /**
+ * Normalize template from any platform
+ * @param {Object} template - Template object
+ * @param {string} platform - Platform identifier ('whatsapp' | 'twilio')
+ * @returns {Object} - Normalized template
+ */
+ static normalize(template, platform) {
+ switch (platform) {
+ case 'whatsapp':
+ return this.normalizeWhatsApp(template);
+ case 'twilio':
+ return this.normalizeTwilio(template);
+ default:
+ throw new Error(`Unsupported platform: ${platform}`);
+ }
+ }
+}
diff --git a/app/javascript/dashboard/services/TemplateTypeDetector.js b/app/javascript/dashboard/services/TemplateTypeDetector.js
new file mode 100644
index 000000000..33948affe
--- /dev/null
+++ b/app/javascript/dashboard/services/TemplateTypeDetector.js
@@ -0,0 +1,71 @@
+/**
+ * TemplateTypeDetector - Unified service to identify template types across platforms
+ */
+export class TemplateTypeDetector {
+ /**
+ * Detect WhatsApp template type based on components
+ * @param {Object} template - WhatsApp template object
+ * @returns {string} - Template type identifier
+ */
+ static detectWhatsAppType(template) {
+ const components = template.components || [];
+ const hasHeader = components.find(c => c.type === 'HEADER');
+ const hasButtons = components.find(c => c.type === 'BUTTONS');
+
+ // Media templates (priority: header media)
+ if (hasHeader?.format === 'IMAGE') return 'whatsapp-media-image';
+ if (hasHeader?.format === 'VIDEO') return 'whatsapp-media-video';
+ if (hasHeader?.format === 'DOCUMENT') return 'whatsapp-media-document';
+
+ // Interactive templates (priority: special buttons)
+ if (hasButtons) {
+ const copyCodeButton = hasButtons.buttons?.find(
+ b => b.type === 'COPY_CODE'
+ );
+ if (copyCodeButton) return 'whatsapp-copy-code';
+ return 'whatsapp-interactive';
+ }
+
+ // Text templates
+ if (hasHeader?.format === 'TEXT') return 'whatsapp-text-header';
+ return 'whatsapp-text';
+ }
+
+ /**
+ * Detect Twilio template type
+ * @param {Object} template - Twilio template object
+ * @returns {string} - Template type identifier
+ */
+ static detectTwilioType(template) {
+ switch (template.template_type) {
+ case 'media':
+ return 'twilio-media';
+ case 'quick_reply':
+ return 'twilio-quick-reply';
+ default:
+ return 'twilio-text';
+ }
+ }
+
+ /**
+ * Get all supported template types
+ * @returns {Array} - Array of supported template types
+ */
+ static getSupportedTypes() {
+ return [
+ // WhatsApp types
+ 'whatsapp-text',
+ 'whatsapp-text-header',
+ 'whatsapp-media-image',
+ 'whatsapp-media-video',
+ 'whatsapp-media-document',
+ 'whatsapp-interactive',
+ 'whatsapp-copy-code',
+
+ // Twilio types
+ 'twilio-text',
+ 'twilio-media',
+ 'twilio-quick-reply',
+ ];
+ }
+}