Skip to main content
Glama

create_theme_preview_html

Generate HTML mockups to visualize color themes in realistic UI contexts like websites, mobile apps, and dashboards for design validation.

Instructions

Generate HTML theme preview mockups showing colors in realistic UI contexts

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Core handler function executing the tool logic: validates inputs, processes theme colors with accessibility checks, generates interactive HTML preview mockups, handles exports, and file saving.
    async function createThemePreviewHtml(
      params: CreateThemePreviewHtmlParams
    ): Promise<ToolResponse | ErrorResponse> {
      const startTime = Date.now();
    
      try {
        // Validate parameters
        const { error, value } = createThemePreviewHtmlSchema.validate(params);
        if (error) {
          return {
            success: false,
            error: {
              code: 'INVALID_PARAMETERS',
              message: 'Invalid parameters provided',
              details: error.details,
              suggestions: [
                'Ensure theme_colors is an object with color name keys and color value strings',
                'Check that preview_type is one of: website, mobile_app, dashboard, components',
                'Verify components array contains valid component names',
              ],
            },
            metadata: {
              execution_time: Date.now() - startTime,
              tool: 'create_theme_preview_html',
              timestamp: new Date().toISOString(),
            },
          };
        }
    
        const validatedParams = value as CreateThemePreviewHtmlParams;
    
        // Validate and process theme colors
        const processedThemeColors: Record<
          string,
          {
            hex: string;
            rgb: string;
            hsl: string;
            name: string;
            accessibility?: {
              contrastRatio: number;
              wcagAA: boolean;
              wcagAAA: boolean;
            };
          }
        > = {};
    
        const accessibilityNotes: string[] = [];
        const recommendations: string[] = [];
    
        // Required semantic colors for different preview types
        const requiredColors = getRequiredColorsForPreviewType(
          validatedParams.preview_type || 'website'
        );
        const missingColors: string[] = [];
    
        for (const [colorName, colorValue] of Object.entries(
          validatedParams.theme_colors
        )) {
          if (!colorValue || typeof colorValue !== 'string') {
            return {
              success: false,
              error: {
                code: 'INVALID_COLOR_VALUE',
                message: `Invalid color value for "${colorName}": ${colorValue}`,
                details: { colorName, colorValue },
                suggestions: [
                  'Ensure all color values are valid color strings',
                  'Use hex format like #FF0000',
                  'Use RGB format like rgb(255, 0, 0)',
                  'Use HSL format like hsl(0, 100%, 50%)',
                ],
              },
              metadata: {
                execution_time: Date.now() - startTime,
                tool: 'create_theme_preview_html',
                timestamp: new Date().toISOString(),
              },
            };
          }
    
          try {
            // Validate color format
            const colorValidation = validateColorInput(colorValue);
            if (!colorValidation.isValid) {
              return {
                success: false,
                error: {
                  code: 'INVALID_COLOR_FORMAT',
                  message: `Invalid color format for "${colorName}": ${colorValue}`,
                  details: {
                    colorName,
                    colorValue,
                    reason: colorValidation.error,
                  },
                  suggestions: [
                    'Use hex format like #FF0000',
                    'Use RGB format like rgb(255, 0, 0)',
                    'Use HSL format like hsl(0, 100%, 50%)',
                    'Check the color format documentation',
                  ],
                },
                metadata: {
                  execution_time: Date.now() - startTime,
                  tool: 'create_theme_preview_html',
                  timestamp: new Date().toISOString(),
                },
              };
            }
    
            const unifiedColor = new UnifiedColor(colorValue);
    
            // Calculate accessibility information
            let accessibility;
            if (colorName === 'text' || colorName === 'primary') {
              // Calculate contrast against background colors
              const backgroundColors = ['background', 'surface'];
              let bestContrast = 0;
    
              for (const bgColorName of backgroundColors) {
                if (validatedParams.theme_colors[bgColorName]) {
                  try {
                    const bgColor = new UnifiedColor(
                      validatedParams.theme_colors[bgColorName]
                    );
                    const contrast = unifiedColor.getContrastRatio(bgColor.hex);
                    bestContrast = Math.max(bestContrast, contrast);
                  } catch {
                    // Ignore errors for background color processing
                  }
                }
              }
    
              if (bestContrast > 0) {
                accessibility = {
                  contrastRatio: bestContrast,
                  wcagAA: bestContrast >= 4.5,
                  wcagAAA: bestContrast >= 7.0,
                };
    
                if (!accessibility.wcagAA) {
                  accessibilityNotes.push(
                    `Color "${colorName}" may not meet WCAG AA contrast requirements (${bestContrast.toFixed(2)}:1)`
                  );
                }
              }
            }
    
            processedThemeColors[colorName] = {
              hex: unifiedColor.hex,
              rgb: unifiedColor.toFormat('rgb'),
              hsl: unifiedColor.toFormat('hsl'),
              name: colorName,
              ...(accessibility && { accessibility }),
            };
          } catch (colorError) {
            return {
              success: false,
              error: {
                code: 'COLOR_PROCESSING_ERROR',
                message: `Failed to process color "${colorName}": ${colorValue}`,
                details: { colorName, colorValue, error: colorError },
                suggestions: [
                  'Verify the color format is supported',
                  'Check for typos in color values',
                  'Try a different color format',
                ],
              },
              metadata: {
                execution_time: Date.now() - startTime,
                tool: 'create_theme_preview_html',
                timestamp: new Date().toISOString(),
              },
            };
          }
        }
    
        // Check for missing required colors
        for (const requiredColor of requiredColors) {
          if (!processedThemeColors[requiredColor]) {
            missingColors.push(requiredColor);
          }
        }
    
        if (missingColors.length > 0) {
          recommendations.push(
            `Consider adding these semantic colors for better ${validatedParams.preview_type} preview: ${missingColors.join(', ')}`
          );
        }
    
        // Generate additional recommendations
        const colorCount = Object.keys(processedThemeColors).length;
        if (colorCount < 3) {
          recommendations.push(
            'Consider adding more semantic colors (background, text, primary, secondary) for a complete theme'
          );
        }
    
        if (
          validatedParams.preview_type === 'dashboard' &&
          !processedThemeColors['sidebar']
        ) {
          recommendations.push(
            'Dashboard previews work best with a sidebar color defined'
          );
        }
    
        // Prepare visualization data
        const visualizationData: ThemePreviewVisualizationData = {
          themeColors: processedThemeColors,
          previewType: validatedParams.preview_type || 'website',
          components: validatedParams.components || [
            'header',
            'content',
            'buttons',
          ],
          interactive: validatedParams.interactive !== false,
          responsive: validatedParams.responsive !== false,
          theme: validatedParams.theme || 'light',
          metadata: {
            title: 'Theme Preview',
            description: `${validatedParams.preview_type || 'Website'} preview with ${colorCount} theme colors`,
            timestamp: new Date().toLocaleString(),
            colorCount,
            previewType: validatedParams.preview_type || 'website',
          },
        };
    
        // Generate enhanced HTML with background controls
        let result: EnhancedVisualizationResult;
    
        try {
          const enhancedOptions: EnhancedHTMLOptions = {
            interactive: true, // Enable interactive features including JavaScript
            backgroundControls: {
              enableToggle: validatedParams.enable_background_controls ?? true,
              enableColorPicker: validatedParams.enable_background_controls ?? true,
              defaultBackground:
                validatedParams.theme === 'dark' ? 'dark' : 'light',
            },
            enableAccessibilityTesting:
              validatedParams.enable_accessibility_testing ?? true,
            includeKeyboardHelp: validatedParams.include_keyboard_help ?? true,
          };
    
          result = await enhancedHTMLGenerator.generateEnhancedThemePreviewHTML(
            visualizationData,
            enhancedOptions
          );
        } catch (htmlError) {
          throw new Error(
            `Failed to generate enhanced HTML: ${htmlError instanceof Error ? htmlError.message : String(htmlError)}`
          );
        }
    
        // Prepare export formats
        const exportFormats: Record<string, string | object> = {};
    
        exportFormats['css'] = generateThemeCSSExport(processedThemeColors);
        exportFormats['scss'] = generateThemeSCSSExport(processedThemeColors);
        exportFormats['json'] = {
          theme_colors: Object.fromEntries(
            Object.entries(processedThemeColors).map(([name, color]) => [
              name,
              {
                hex: color.hex,
                rgb: color.rgb,
                hsl: color.hsl,
                accessibility: color.accessibility,
              },
            ])
          ),
          preview_type: validatedParams.preview_type,
          components: validatedParams.components,
          metadata: visualizationData.metadata,
        };
    
        const executionTime = Date.now() - startTime;
    
        // Try to save file using enhanced file output manager
        let visualizationResult;
        try {
          await enhancedFileOutputManager.initialize();
    
          // If we have HTML content, save it using the enhanced file output manager
          if (result.htmlContent) {
            visualizationResult =
              await enhancedFileOutputManager.saveHTMLVisualization(
                result.htmlContent,
                {
                  toolName: 'create_theme_preview_html',
                  description: `Enhanced theme preview with ${colorCount} colors`,
                }
              );
          }
        } catch (fileError) {
          // If file saving fails, we'll fall back to returning HTML content directly
          logger.warn('Failed to save HTML file, falling back to content', {
            error: fileError as Error,
          });
        }
    
        return {
          success: true,
          data: {
            theme_colors: Object.fromEntries(
              Object.entries(processedThemeColors).map(([name, color]) => [
                name,
                color.hex,
              ])
            ),
            preview_type: validatedParams.preview_type || 'website',
            components: validatedParams.components || [
              'header',
              'content',
              'buttons',
            ],
            color_count: colorCount,
            accessibility_compliant: Object.values(processedThemeColors).every(
              color => !color.accessibility || color.accessibility.wcagAA
            ),
            file_path: result.filePath,
            file_name: result.fileName,
            file_size: result.fileSize,
            background_controls_enabled: result.backgroundControlsEnabled,
            accessibility_features: result.accessibilityFeatures,
          },
          metadata: {
            execution_time: executionTime,
            tool: 'create_theme_preview_html',
            timestamp: new Date().toISOString(),
            color_space_used: 'sRGB',
            accessibility_notes: accessibilityNotes,
            recommendations: [
              ...recommendations,
              'HTML file saved with interactive background controls',
              'Use Alt+T to toggle background theme',
              'Use Alt+C to open color picker',
            ],
          },
          visualizations: {
            html: result.htmlContent || `File saved: ${result.filePath}`,
            ...(visualizationResult?.html_file && {
              html_file: visualizationResult.html_file,
            }),
          },
          export_formats: exportFormats,
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        const errorStack = error instanceof Error ? error.stack : undefined;
    
        return {
          success: false,
          error: {
            code: 'INTERNAL_ERROR',
            message: `Theme preview HTML generation error: ${errorMessage}`,
            details: {
              errorMessage,
              errorStack,
              errorType: error?.constructor?.name || 'Unknown',
            },
            suggestions: [
              'Verify all theme colors are in valid formats',
              'Check that the preview type and components are supported',
              'Try with a simpler theme color set',
            ],
          },
          metadata: {
            execution_time: Date.now() - startTime,
            tool: 'create_theme_preview_html',
            timestamp: new Date().toISOString(),
          },
        };
      }
    }
  • Joi schema defining input parameters including theme_colors, preview_type, components, and various options.
    const createThemePreviewHtmlSchema = Joi.object({
      theme_colors: Joi.object()
        .pattern(Joi.string(), Joi.string())
        .required()
        .description('Semantic color mapping object'),
    
      preview_type: Joi.string()
        .valid('website', 'mobile_app', 'dashboard', 'components')
        .default('website')
        .description('Preview type'),
    
      components: Joi.array()
        .items(
          Joi.string().valid(
            'header',
            'sidebar',
            'content',
            'footer',
            'buttons',
            'forms',
            'cards'
          )
        )
        .default(['header', 'content', 'buttons'])
        .description('Components to show'),
    
      interactive: Joi.boolean().default(true).description('Enable interactivity'),
    
      responsive: Joi.boolean().default(true).description('Responsive design'),
    
      theme: Joi.string()
        .valid('light', 'dark', 'auto')
        .default('light')
        .description('Color theme for the visualization'),
    
      enable_background_controls: Joi.boolean()
        .default(true)
        .description('Enable interactive background controls'),
    
      enable_accessibility_testing: Joi.boolean()
        .default(true)
        .description('Enable accessibility testing and warnings'),
    
      include_keyboard_help: Joi.boolean()
        .default(true)
        .description('Include keyboard shortcuts help'),
    });
  • ToolHandler export that defines the tool name, description, parameters schema, and handler wrapper.
    export const createThemePreviewHtmlTool: ToolHandler = {
      name: 'create_theme_preview_html',
      description:
        'Generate HTML theme preview mockups showing colors in realistic UI contexts',
      parameters: createThemePreviewHtmlSchema.describe(),
      handler: async (params: unknown) =>
        createThemePreviewHtml(params as CreateThemePreviewHtmlParams),
    };
  • Central import and registration of the tool into the ToolRegistry singleton.
    import { createThemePreviewHtmlTool } from './create-theme-preview-html';
    
    // Import and register PNG generation tools
    import { createPalettePngTool } from './create-palette-png';
    import { createGradientPngTool } from './create-gradient-png';
    import { createColorComparisonPngTool } from './create-color-comparison-png';
    
    // Import and register theme generation tools
    import { generateThemeTool } from './generate-theme';
    import { generateSemanticColorsTool } from './generate-semantic-colors';
    
    // Import color utility tools
    import { mixColorsTool } from './mix-colors';
    import { generateColorVariationsTool } from './generate-color-variations';
    import { sortColorsTool } from './sort-colors';
    import { analyzeColorCollectionTool } from './analyze-color-collection';
    
    // Import export format tools
    import { exportCssTool } from './export-css';
    import { exportScssTool } from './export-scss';
    import { exportTailwindTool } from './export-tailwind';
    import { exportJsonTool } from './export-json';
    
    // Register conversion tools
    toolRegistry.registerTool(convertColorTool);
    
    // Register analysis tools
    toolRegistry.registerTool(analyzeColorTool);
    toolRegistry.registerTool(checkContrastTool);
    
    // Register accessibility tools
    toolRegistry.registerTool(simulateColorblindnessTool);
    toolRegistry.registerTool(optimizeForAccessibilityTool);
    
    // Register palette generation tools
    toolRegistry.registerTool(generateHarmonyPaletteTool);
    
    // Register gradient generation tools
    toolRegistry.registerTool(generateLinearGradientTool);
    toolRegistry.registerTool(generateRadialGradientTool);
    
    // Register visualization tools
    toolRegistry.registerTool(createPaletteHtmlTool);
    toolRegistry.registerTool(createColorWheelHtmlTool);
    toolRegistry.registerTool(createGradientHtmlTool);
    toolRegistry.registerTool(createThemePreviewHtmlTool);
  • Helper function determining required semantic colors for different preview types (website, mobile_app, etc.).
    function getRequiredColorsForPreviewType(previewType: string): string[] {
      const baseColors = ['background', 'text', 'primary'];
    
      switch (previewType) {
        case 'website':
          return [...baseColors, 'surface', 'secondary'];
        case 'mobile_app':
          return [...baseColors, 'surface', 'accent'];
        case 'dashboard':
          return [
            ...baseColors,
            'surface',
            'sidebar',
            'accent',
            'success',
            'warning',
            'error',
          ];
        case 'components':
          return [
            ...baseColors,
            'secondary',
            'success',
            'warning',
            'error',
            'info',
          ];
        default:
          return baseColors;
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ColorMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server