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;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It mentions generating HTML mockups but lacks details on behavioral traits: no information on output format (e.g., inline HTML, file), performance (e.g., generation time), side effects (e.g., if it creates files), or error handling. The description is minimal and doesn't compensate for missing annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core purpose. It uses clear language ('Generate HTML theme preview mockups') without redundancy or fluff. Every word earns its place, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (9 parameters, no annotations, no output schema), the description is insufficient. It doesn't explain what the HTML output contains (e.g., full page, embeddable snippet), how to use it, or any limitations. For a tool that generates visual content, more context on the result and its usability is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 9 parameters with descriptions and constraints. The description adds no parameter-specific information beyond implying 'theme_colors' and 'preview_type' are relevant. Baseline is 3 since the schema does the heavy lifting, but the description doesn't enhance understanding of parameters like 'interactive' or 'enable_accessibility_testing'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Generate HTML theme preview mockups showing colors in realistic UI contexts.' It specifies the action (generate), output format (HTML mockups), and what they show (colors in UI contexts). However, it doesn't explicitly differentiate from sibling tools like 'create_color_wheel_html' or 'create_palette_html' which also generate HTML outputs, though the 'realistic UI contexts' aspect provides some distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, compare to sibling tools (e.g., 'create_color_wheel_html' for abstract visualizations vs. this for UI mockups), or specify ideal scenarios. The agent must infer usage from the purpose alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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