Customization

Metronic Composer

Metronic Composer is an HTML file-based mini CMS(Content Management System) built with Python , Flask , and Jinja . It dynamically serves Metronic Tailwind HTML templates to help developers efficiently manage HTML code through structured partials, blocks, layouts and page contents, making code browsing and extraction easier.

Features

Metronic Composer offers the following features to streamline the integration of Metronic HTML templates with your application stack.

Mini CMS

Effortlessly manage HTML templates and instantly preview changes on localhost.

Code Inspection

Easily browse and extract HTML code from the views within structured file system.

Reusable HTML

Generate each page using reusable and centrally managed HTML components and layouts.

Save Time

Find and analyze the HTML code you need, then seamlessly transfer it to your project.

Prototype Showcase

Customize styles, navigations, and page blocks for effective prototype demos.

Integrated Testing

Apply changes and test them across all template pages before integrating into your project.

Code Organization

Refer to the Composer's view and asset arrangements to efficiently organize your project.

Data Models

Refer to preset data arrays with demo content for iterating lists, tables, and other UI elements.

Configuration

Easily change global settings like KeenIcons style, menus, and layout options on the fly.

How It Works

Make Metronic Composer your development companion to accelerate your Metronic Tailwind based projects. Pay once and enjoy lifetime access, using it for unlimited projects.
1

Purchase Metronic

Purchase Metronic from Themeforest Market and download the latest version.
2

Purchase Composer

Purchase Composer from Composer Pricing and download the version compatible with your Metronic version from the from Keenthemes Market .
3

Use Composer

Unpack the Metronic package, copy the content and paste it into the Composer's directory. and follow the Composer Installation guide to start using Composer.

Pricing

Make Metronic Composer your development companion to accelerate your Metronic Tailwind based projects. Pay once and enjoy lifetime access, using it for unlimited projects.
Single Developer
$99
one-time payment
plus local taxes

License for 1 developer, usable on unlimited projects.

Purchase
Team
$299
one-time payment
plus local taxes

License for a team of any size, usable on unlimited projects.

Purchase
Secured payment by Paddle with
100% money back guarantee!

FAQ

Check out the FAQ section below to learn more about Composer before making a purchase decision. If you have any questions, feel free to contact our Keenthemes Pre-sale Support .

Preparation

To set up the necessary folder preparation, follow the steps below:
1

Download

Download the latest Metronic Composer and metronic-tailwind-html from Themeforest .
2

Unzip theme folder

Unzip both folders into a directory, for example, myproject :
  • myproject/metronic-tailwind-html
  • myproject/metronic-composer
Ensure the folders are side by side
3

Copy metronic-tailwind-html

Open a terminal inside the myproject folder:
				
					cd myproject

				
			
4

Copy content of metronic-tailwind-html

Copy the content of the metronic-tailwind-html into metronic-composer/themes/metronic-tailwind-html
For Windows :
				
					xcopy /E /I  metronic-tailwind-html\* metronic-composer\themes\metronic-tailwind-html\

				
			
For Unix/Linux :
				
					cp -R metronic-tailwind-html/* metronic-composer/themes/metronic-tailwind-html

				
			
You can verify metronic-composer/themes/metronic-tailwind-html to see if the content is copied there.

Installation

Follow the guide below to get started with the Dynamic Preview.
1

Install Python

Ensure you have the latest version of Python installed. Download it from the official Python website. To verify the installation, open your terminal and run:
				
					python --version

				
			
In some operating systems, Python 3 is used instead of Python. If you have Python 3 installed, you can verify the installation by running the following command:
				
					python3 --version

				
			
If Python is installed, it will display the version number.
2

Launch Terminal

Start a command prompt window or terminal and change directory to the package's root directory.
				
					cd metronic-composer

				
			
3

Run the script

To start the development server and build the preview, run the following command in the terminal:
For Windows :
				
					run.bat

				
			
For Unix/Linux :
				
					./run.sh

				
			
The run script will install Flask and other dependencies needed for the preview to run for the first time. This may take some time, please wait while the installation is in progress. The preview will be accessible at http://localhost:8001/ after the installation is complete.

Static HTML Files Generation

Follow the steps below to generate static HTML files using Metronic Composer.
1

Launch Terminal

Open a command prompt or terminal window. Change your directory to the package's root directory. Use the following command:
				
					cd metronic-composer

				
			
2

Run the generate script

To start the development server and build the preview, execute the appropriate script based on your operating system:
For Windows :
				
					generate.bat

				
			
For Unix/Linux :
				
					./generate.sh

				
			
3

Locate the Generated HTML Files

Once the script completes execution, all pages will be generated and exported into HTML files. You can find the exported HTML files in the following directory: themes/metronic-tailwind-html/dist/html
Each page will have its own HTML file named to match the page name. The HTML files will correspond to their respective page URLs. For instance, a page accessible via example.com/dashboard will have an HTML file named dashboard.html .

Troubleshooting

This section provides common issues and solutions for installing Metronic Dynamic Preview and running it.
The issue usually happens on Windows. Python is not recognized as an internal or external command, operable program or batch file. This error occurs when the Python executable is not added to the system's PATH .
Check if Python is installed on your system by typing python --version or python3 --version in your command prompt or terminal. If Python is installed, it will display the version number.
If Python is not installed, download the latest version from the official Python website and install it.

When running the installer, make sure to tick the box that says "Add Python to environment variables". This will ensure that Python is added to the systems PATH variable.

If Python is installed but still not recognized, you may need to add Python to your system's PATH variable. Here's how to do it on Windows:
1

Environment Variables

Search for Environment Variables in the Windows search bar and select Edit the system environment variables then click on Environment Variables .
3

Edit Variables

Under System variables , find the Path variable, select it, and click on Edit .
4

Add Variable

Click on New and add the path where Python is installed. By default, it is C:\PythonXX , where XX is the version number.
5

Complete

Click on OK to close all dialog boxes and restart your command prompt or terminal.
The issue usually happens on Unix/Linux. bash: ./run.sh: Permission denied .
To make the run.sh file executable on Unix/Linux , you can run the following command in the terminal:
				
					chmod +x run.sh

				
			
The command makes the run.sh file executable, which means that you can run it as a script. Running the script will start the Flask development server and build the preview.

Theme API

The Preview Tool utilizes the libs/theme_helper.py file for global Theme API settings as listed in the below table.
Method Description
layout(file, param={}, render=True) Renders a specified layout file with optional parameters. If render is set to True, the layout is rendered directly.
partial(file, param={}) Renders a specified partial file with optional parameters. This method is used to include reusable components in a layout or page.
page(file, param={}) Renders a specified page file with optional parameters. This method is typically used for rendering full pages within an application.
getPartial(scope, file, param={}, render=True, prettify=False) Retrieves and optionally renders a partial file within a given scope, using optional parameters. The prettify option can be used to format the output for readability.
getAssets(type) Retrieves all assets of a specified type (e.g., CSS, JavaScript) from the project.
getAsset(type, name) Retrieves a specific asset by type and name, such as a particular CSS or JavaScript file.
getPageUrl(page) Generates the URL for a specified page, making it easier to link to other pages within the application.
getKeenIcon(name, class_name="", icon_type=None) Retrieves a Keen Icon by its name, with optional class names and icon type for customization.
getBreadcrumbs(menu_items=None, exclude_active=False) Generates breadcrumb navigation from the given menu items. Optionally, the active menu item can be excluded.
getUrl(path) Generates a full URL from a given path, useful for creating links within the application.
includeAssets(files) Includes a list of asset files (e.g., CSS, JavaScript) in the current view or layout.
getActiveMenu(menu_items=None) Identifies and returns the currently active menu item from the given menu items.
getCurrentMenuLinkTitle(menu_items=None) Retrieves the title of the currently active menu item from the given menu items.
getConfig(key, by_demo=True) Retrieves configuration settings by key, with an option to specify if the settings are for a specific demo.
api(data) Handles API requests for demo by processing the provided data and returning the appropriate response.
code(code, param={}) Executes or processes a block of code with optional parameters.
file(path) Reads and returns the contents of a file specified by the path.
json(path) Reads a JSON file from the specified path and returns its contents as a JSON object.

App Settings

The Preview Tool utilizes the config/app.yaml file for global settings as listed in the below table.
Property Value Default
keenicons.default
Sets the default icon style for KeenIcons.
enum
"filled" | "duotone" | "outline" | "solid"
"outline"
keenicons.demo1
Sets the KeenIcons icon style for demo1.
enum
"filled" | "duotone" | "outline" | "solid"
"outline"
container.default
Specifies the default layout container type.
enum
"fixed" | "fluid"
"fixed"
container.demo1
Specifies the default layout container type for demo1.
enum
"fixed" | "fluid"
"fixed"
The Preview Tool utilizes the config/menu.yaml file for menu settings used in generating menus like the sidebar menu and megamenu. This configuration file contains multiple menu settings defined with the following common properties.
Property Value Default
section
Defines the title of the section that groups menu items.
string -
title
Defines the title of the menu item.
string -
path
Specifies the URL path for the menu items link.
string -
icon
Defines the icon name of the menu item.
string -
children
An array of submenu items.
[] -

Views

Views represent the HTML structure and are located in the views directory, which contains the layouts, pages, and partials used to generate HTML pages.

Layout Views

Layout Views represent the HTML structure for page layouts that wrapps contents during the page generation. views/layouts contains multiple layouts where each layout used for varouse cases such as, application, authentication or error pages. For application pages multiple layouts are supported as demo1, demo2, etc where each layout has unique structure and design.
Path Description
views/layouts/base.html The base layout code serves as the foundation for generating all HTML pages. It includes essential structural tags and assets ensuring a consistent layout across the entire application.
views/layouts/auth Contains the layout code designed for authentication pages, offers a tailored structure and styling optimized for login, registration, and password reset functionalities.
views/layouts/error Contains the layout code designed for error pages, designed to provide a specific structure and styling for displaying error messages like 404 and 500 pages.
views/layouts/demo1 Contains the layout code required for rendering the main content and features of the application.
				
					<!DOCTYPE html>
<html class="h-full" lang="en">
 <head>
  <meta charset="utf-8"/>
  <meta content="max-snippet:-1, max-image-preview:large, max-video-preview:-1" name="robots"/>
  <link href="https://keenthemes.com/" rel="canonical"/>
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport"/>
  <meta content="" name="description"/>
  <meta content="@keenthemes" name="twitter:site"/>
  <meta content="@keenthemes" name="twitter:creator"/>
  <meta content="summary_large_image" name="twitter:card"/>
  <meta content="" name="twitter:title"/>
  <meta content="" name="twitter:description"/>
  <meta content="og-image.png" name="twitter:image"/>
  <meta content="https://keenthemes.com/" property="og:url"/>
  <meta content="en_US" property="og:locale"/>
  <meta content="website" property="og:type"/>
  <meta content="" property="og:site_name"/>
  <meta content="" property="og:title"/>
  <meta content="" property="og:description"/>
  <meta content="og-image.png" property="og:image"/>
  <title>
   {% block title %}{% endblock %}
  </title>
  <link href="{{ theme.getAssetUrl('media/app/favicon.ico') }}" rel="shortcut icon"/>
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;display=swap" rel="stylesheet"/>
  <link href="{{ theme.getAssetUrl('vendors/apexcharts/apexcharts.css') }}" rel="stylesheet"/>
  <link href="{{ theme.getAssetUrl('vendors/keenicons/styles.bundle.css') }}" rel="stylesheet"/>
  {% for path in theme.getAssets('css') %}
  <link href="{{ theme.getAssetUrl(path) }}" rel="stylesheet"/>
  {% endfor %}
  <link href="{{ theme.getAssetUrl('css/styles.css') }}" rel="stylesheet"/>
 </head>
 <body class="flex h-full sidebar-fixed header-fixed bg-light {{ theme.getDemo() }}" data-theme="true" data-theme-mode="light">
  <!--begin::Theme mode setup on page load-->
  <script>
   const defaultThemeMode = 'light'; // light|dark|system
		let themeMode;
		
		if ( document.documentElement ) {
			if ( localStorage.getItem('theme')) {
					themeMode = localStorage.getItem('theme');
			} else if ( document.documentElement.hasAttribute('data-theme-mode')) {
				themeMode = document.documentElement.getAttribute('data-theme-mode');
			} else {
				themeMode = defaultThemeMode;
			}

			if (themeMode === 'system') {
				themeMode = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
			}
			
			document.documentElement.classList.add(themeMode);
			document.body.classList.add(themeMode);
		}
  </script>
  <!--end::Theme mode setup on page load-->
  <!--begin::Page layout-->
  {% block layout %}
	{% endblock %}
  <!--end::Page layout-->
  <!--begin::Page scripts-->
  <script src="{{ theme.getAssetUrl('js/core.bundle.js') }}">
  </script>
  <script src="{{ theme.getAssetUrl('vendors/apexcharts/apexcharts.min.js') }}">
  </script>
  {% for path in theme.getAssets('js') %}
  <script src="{{ theme.getAssetUrl(path) }}">
  </script>
  {% endfor %}
  <!--end::Page scripts-->
 </body>
</html>

				
			

Partial Views

Partial views, residing in the views/partials directory, encapsulate reusable HTML structures for various components or sections of pages within the application.
				
					{% set items = [
	{
		'logo': 'jira.svg',
		'title': 'Jira',  
		'description': 'Project management',
		'checkbox': False
	},
	{
		'logo': 'inferno.svg',
		'title': 'Inferno', 
		'description': 'Ensures healthcare app',
		'checkbox': True
	},
	{
		'logo': 'evernote.svg',
		'title': 'Evernote', 
		'description': 'Notes management app',
		'checkbox': True
	},
	{
		'logo': 'gitlab.svg',
		'title': 'Gitlab', 
		'description': 'DevOps platform',
		'checkbox': False
	},
	{
		'logo': 'google-webdev.svg',
		'title': 'Google webdev', 
		'description': 'Building web expierences',
		'checkbox': True
	}
] %}
<div class="dropdown-content light:border-gray-300 w-full max-w-[320px]">
 <div class="flex items-center justify-between gap-2.5 text-2xs text-gray-600 font-medium px-5 py-3 border-b border-b-gray-200">
  <span>
   Apps
  </span>
  <span>
   Enabled
  </span>
 </div>
 <div class="flex flex-col scrollable-y-auto max-h-[400px] divide-y divide-gray-200">
  {% for item in items %}
  <div class="flex items-center justify-between flex-wrap gap-2 px-5 py-3.5">
   <div class="flex items-center flex-wrap gap-2">
    <div class="flex items-center justify-center shrink-0 rounded-full bg-gray-100 border border-gray-200 size-10">
     <img alt="" class="size-6" src="{{ theme.getAssetUrl('media/brand-logos/' + item.logo) }}"/>
    </div>
    <div class="flex flex-col">
     <a class="text-2sm font-semibold text-gray-900 hover:text-primary-active" href="#">
      {{ item.title }}
     </a>
     <span class="text-2xs font-medium text-gray-600">
      {{ item.description }}
     </span>
    </div>
   </div>
   <div class="flex items-center gap-2 lg:gap-5">
    {% if item.checkbox == True %}
    <label class="switch switch-sm">
     <input checked="" type="checkbox" value="1"/>
    </label>
    {% else %}
    <label class="switch switch-sm">
     <input type="checkbox" value="2"/>
    </label>
    {% endif %}
   </div>
  </div>
  {% endfor %}
 </div>
 <div class="grid p-5 border-t border-t-gray-200">
  <a class="btn btn-sm btn-light justify-center" href="#">
   Go to Apps
  </a>
 </div>
</div>

				
			

Page Views

Page views, located in the views/pages directory, contain HTML code specific to individual pages within the application, providing a structured representation of each page's content. Each page is launched from the entry file index.html within its respective directory in the application's structure.
				
					{% extends theme.layout('demo:main', render=False) %}

{% set content_menu = theme.config.get('menu').get("sidebar")[3].get('children') %}

{% block content %}
	{{ theme.partial('navbar/begin') }}
		{{ theme.partial('container/begin', {'id': 'hero_container'}) }}
			{{ theme.partial('menu/navbar', {'items': content_menu}) }}
		{{ theme.partial('container/end') }}
	{{ theme.partial('navbar/end') }}
	
	{{ theme.partial('container/begin') }}
		{{ theme.partial('toolbar/begin') }}
			{{ theme.partial('toolbar/heading/begin') }}
<h1 class="text-2xl font-semibold leading-none text-gray-900 mb1.5">
 Account
</h1>
<div class="flex items-center gap-2 text-sm font-medium">
 <span class="text-gray-700">
  Jayson Tatum
 </span>
 <a class="text-gray-600 hover:text-primary" href="mailto:jaytatum@ktstudio.com">
  jaytatum@ktstudio.com
 </a>
 <span class="size-0.75 bg-gray-600 rounded-full">
 </span>
 <a class="font-semibold btn btn-link text-primary hover:text-primary-active" href="#">
  Personal Info
 </a>
</div>
{{ theme.partial('toolbar/heading/end') }}
		{{ theme.partial('toolbar/end') }}
	{{ theme.partial('container/end') }}

	{{ theme.partial('container/begin') }}
		{{ theme.page('account/home/get-started/-content') }}
	{{ theme.partial('container/end') }}
{% endblock %}