Streamline your Lovelace configuration with a powerful card template system.
This card is for Lovelace on Home Assistant.
- What is This Card?
- Installation
- Configuration
- Real-World Examples
- Examples
- Tips and Best Practices
- Troubleshooting
- Contributing
Have you ever found yourself copying and pasting the same card configuration over and over in your Home Assistant dashboard? For example, you might have multiple light cards that all look the same, just with different entities. Every time you want to change how these cards look, you have to change each one individually. This is time-consuming and prone to errors.
This is where streamline-card comes to help! It allows you to:
- Create a template for your cards once
- Reuse that template multiple times
- Only change the template in one place to update all cards using it
- Use variables to customize each instance of the template
- Use JavaScript to make your cards dynamic and smart
streamline-card is an adaptation by @brunosabot of decluttering-card which is not maintained anymore.
There are two ways to install this card. The recommended way is through HACS (Home Assistant Community Store), but you can also install it manually.
HACS is like an app store for Home Assistant. It makes installing and updating custom cards much easier. Here's how to install using HACS:
-
Install HACS if you don't have it:
- If HACS is not installed yet, download it following the instructions on https://hacs.xyz/docs/use/download/download/
- Follow the HACS initial configuration guide at https://hacs.xyz/docs/configuration/basic
-
Install the Card:
- Go to
HACSin your Home Assistant sidebar - Search for
Streamline Cardin HACS - Click on the card when you find it
- Click the
Downloadbutton at the bottom right
- Go to
Note
- Follow those steps first to make sure the card is installed and working properly.
- Usually, you would create a template for the card at this step, but we’ll skip that for now.
- Once you know that the card is working you can head over to Configuration
- Adding the Card:
- Go back to your dashboard
- Click the menu icon (⋮) at the top right corner
- Click
Edit dashboard - Click
Add cardat the bottom right - Search for
Streamline Card
Warning
If you don't see the card, try clearing your browser cache.
If you prefer to install manually or can't use HACS, follow these steps:
-
Download the Card:
- Download this file: streamline-card.js
- Save it to your Home Assistant
<config>/wwwfolder
-
Add to Resources:
- Go to your dashboard
- Click the menu icon (⋮) at the top right
- Click
Edit dashboard - Click the menu icon again
- Click
Manage resources - Click
Add resource - Enter
/local/streamline-card.js?v=1in the URL field - Select
JavaScript Module - Click
Create
-
Add to Dashboard:
- Refresh your browser page
- Edit your dashboard
- Click
Add card - Search for
Streamline Card
Warning
After updating the file, you'll need to change the version number in the URL (e.g., from v=1 to v=2) to make sure your browser loads the new version.
Let's learn how to use this card step by step.
A template is like a blueprint for your cards. It defines how your card will look and behave, but leaves certain parts (variables) empty so you can fill them in later.
For example, let's say you want to create a template for a light card. The template might look like this:
my_light_template:
card:
type: custom:bubble-card
name: "[[room_name]] Light" # This will be filled in later
icon: "[[light_icon]]" # This will be filled in later
entity: "[[light_entity]]" # This will be filled in laterThere are two ways to set up your templates: through YAML files or through the UI. Let's look at both methods:
Method 1: YAML Configuration (Recommended when you have many Templates)
-
Create a Templates Directory: Create a folder called
streamline_templatesin your Home Assistant configuration directory. -
Add Template Files: In this folder, create YAML files for your templates. For example,
light_template.yaml:
default:
- light_icon: mdi:ceiling-light
card:
type: custom:bubble-card
name: "[[room_name]] Light"
icon: "[[light_icon]]"
entity: "[[light_entity]]"- Include Templates in Dashboard: In your dashboard configuration file, add:
streamline_templates: !include_dir_named ../streamline_templates/Note: An example template file,
streamline_templates.example.yaml, is provided in thedist/directory of this repository. You can copy this file to any of the supported locations (such as/config/www/community/streamline-card/or/config/www/streamline-card/) and rename it tostreamline_templates.yamlto get started quickly with your own templates.
The streamline-card will automatically attempt to load the streamline_templates.yaml file from several locations, in the following order:
/config/www/community/streamline-card/streamline_templates.yaml(default for HACS installations)/config/www/streamline-card/streamline_templates.yaml(commonly used for manual installations)
If the file is not found in the first location, the card will try the next, and so on. This fallback mechanism ensures maximum compatibility with different Home Assistant setups.
What does this mean for you?
- You can place your
streamline_templates.yamlfile in any of these locations, depending on how you installed the card and your Home Assistant directory structure. - Only one file is needed; the card will use the first one it finds.
- This makes it easy to provide or override templates without modifying the card code.
Method 2: UI Configuration (Easier for Beginners)
-
Open Raw Editor:
- Go to your dashboard
- Click the menu icon (⋮)
- Click
Raw configuration editor
-
Add Templates: At the top of the file, add:
streamline_templates:
my_light_template:
default:
- light_icon: mdi:ceiling-light
card:
type: custom:bubble-card
name: "[[room_name]] Light"
icon: "[[light_icon]]"
entity: "[[light_entity]]"Each template has three main parts:
- Template Name: This is how you'll refer to your template later.
my_light_template: # This is the template name- Default Values (Optional): These are values that will be used if not specified when using the template.
default:
- light_icon: mdi:ceiling-light- Card Configuration: This is the actual card configuration, with variables in double brackets.
card: # Use 'card' for normal cards
type: custom:bubble-card
name: "[[room_name]] Light"
icon: "[[light_icon]]"
entity: "[[light_entity]]"
# OR
element: # Use 'element' for picture-elements
type: icon
icon: "[[icon]]"Variables are placeholders in your template that get replaced with actual values when you use the template. They are written with double brackets: [[variable_name]]
Tip
Some important rules about variables:
- Always put them in double brackets:
[[like_this]] - If a variable is alone on a line, put it in single quotes:
'[[variable_name]]' - Variables can be used anywhere in the template
- You can set default values for variables in the
defaultsection
You can make your templates dynamic using JavaScript. Any key that ends with _javascript will be evaluated as JavaScript code.
The javascript code has access to the following data
- states: An object containing all states
- user: An object containing the current user information, for instance
user.nameoruser.is_admin - variables: An object containing all the variables you've defined in your template
- areas: An object containing all areas defined in Home Assistant, for instance you can use
areas.kitchen.icon
Here's an example of a dynamic weather card that changes color based on temperature:
weather_template:
card:
type: custom:bubble-card
card_type: button
button_type: state
entity: "[[weather_entity]]"
styles_javascript: |
const temp = states['[[weather_entity]]'].attributes.temperature;
return `
.bubble-button-card-container {
background-color: ${
temp < 0 ? 'var(--info-color)' :
temp > 30 ? 'var(--error-color)' :
'var(--primary-color)'
};
}
`;Let's look at some complete examples you can use in your own configuration:
Example 1: Simple Light Card
# Define the template in ui raw configuration editor or file
streamline_templates:
light_template:
default:
- icon: mdi:ceiling-light
card:
type: custom:bubble-card
card_type: button
button_type: "[[type]]"
entity: "[[entity]]"
name: "[[name]]"
icon: "[[icon]]"
tap_action:
action: toggle
hold_action:
action: more-info# Using the template:
- type: custom:streamline-card
template: light_template
variables:
- name: Living Room Light
- entity: light.living_room
- type: sliderExample 2: Weather Card with Dynamic Styling
# Define the template in ui raw configuration editor or file
streamline_templates:
weather_card:
card:
type: custom:bubble-card
card_type: button
button_type: state
entity: "[[entity]]"
name: "[[name]]"
show_state: true
scrolling_effect: false
card_layout: large
sub_button:
- name: Min
icon: mdi:thermometer-low
entity: "[[entity]]"
attribute: forecast[0].templow
show_background: false
show_attribute: true
- name: Wind
icon: mdi:weather-windy
entity: "[[entity]]"
attribute: wind_speed
show_background: false
show_attribute: true
card_mod:
style: |
.bubble-name {
background-color: ${
state_attr(config.entity, 'temperature') < 10 ?
'var(--info-color)' :
state_attr(config.entity, 'temperature') > 30 ?
'var(--warning-color)' :
''
};
}# Using the template:
- type: custom:streamline-card
template: weather_card
variables:
- name: Current Weather
- entity: weather.homeExample 3: Alarm Card with State-Based Colors
# Define the template in ui raw configuration editor or file
streamline_templates:
alarm_template:
default:
- name: ""
- columns: 2
card:
type: custom:bubble-card
card_type: button
button_type: state
entity: "[[entity]]"
name: "[[name]]"
show_state: true
icon: mdi:alarm-light
columns: "[[columns]]"
card_layout: large
styles: |
.bubble-button-card-container {
background-color: ${
state === 'disarmed' ? 'var(--success-color)' :
state === 'triggered' || state ==='pending' ? 'var(--error-color)' :
'var(--warning-color)'
};
}# Using the template:
- type: custom:streamline-card
template: alarm_template
variables:
- name: House Alarm
- entity: alarm_control_panel.home_alarmExample 4: Dynamic Grid of Lights
# Define the template in ui raw configuration editor or file
streamline_templates:
lights_grid:
default:
- entity: sensor.number_lights_on
card:
type: grid
square: false
columns: 3
cards_javascript: |
const onLightEntities = states['[[entity]]'].attributes.lights_on_entity || [];
return onLightEntities.map(entity => ({
type: 'custom:button-card',
template: 'light_brightness',
entity: entity
}));# Using the template:
- type: custom:streamline-card
template: lights_grid
variables:
- entity: sensor.active_lightsExplore real-world template examples to help you get started and inspire your own creations:
- Bubble Light Template:
- A reusable light control card with toggle, name, icon, and slider/button options. Demonstrates default values for variables.
- Bubble Cover Template:
- A cover (e.g., window shutter) control card showing dynamic JavaScript styling (
_javascriptsuffix) and service call actions in sub-buttons.
- A cover (e.g., window shutter) control card showing dynamic JavaScript styling (
- Entity List Template:
- DRY configuration for a list of similar entities, showing how to use templates and variables for scalable dashboards (Issue #51).
- Template Objects with JavaScript:
- Dynamically generate cards using JavaScript and entity attributes for advanced, data-driven dashboards (Issue #39).
- Conditional JavaScript Styling:
- Use the
_javascriptsuffix for dynamic styling and animations based on entity state (Issue #38).
- Use the
Each example includes the YAML code, an explanation of its use, and highlights interesting implementation details.
-
Organizing Templates:
- Keep related templates together in the same file
- Use clear, descriptive template names
- Comment your templates to explain what they do
-
Variables:
- Use descriptive variable names
- Set default values for commonly used variables
- Keep variable names consistent across related templates
-
JavaScript Usage:
- Use JavaScript for dynamic content only when needed
- Test your JavaScript expressions thoroughly
- Keep the code simple and readable
-
Performance:
- Don't overuse JavaScript expressions
- Avoid complex calculations in templates
- Use appropriate card types for your needs
If you're having issues:
-
Card Not Showing Up:
- Clear your browser cache
- Check that the resource is properly loaded
- Check your browser's console for errors
-
Template Not Working:
- Verify your template syntax
- Check that all required variables are provided
- Look for YAML formatting errors
-
JavaScript Errors:
- Check your browser's console for error messages
- Verify that your entities exist
- Test your JavaScript code separately
We welcome contributions to make Streamline Card better! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
[!IMPORTANT] > Please submit pull requests with a single feature or fix at a time. This makes it easier to review, test, and merge your contributions. If you have multiple improvements, please create separate pull requests for each one.
Before you start contributing, make sure you have the following installed:
-
Fork and Clone the Repository:
git clone https://github.com/brunosabot/streamline-card.git cd streamline-card -
Install Dependencies:
pnpm install
-
Configure Environment Variables (Optional):
You can create
.env.development.localor.env.production.localfiles to customize your build output:# .env.development.local TARGET_DIRECTORY=/path/to/your/homeassistant/www/streamline-cardTARGET_DIRECTORY: Specifies where the built files should be output- If not set, files will be built to the
dist/directory by default .env.*.localfiles are gitignored and won't be committed
-
Start Development Mode:
pnpm dev
This will watch for file changes and automatically rebuild the card. If you set
TARGET_DIRECTORY, the files will be output directly to your Home Assistant instance for live testing. -
Build for Production:
pnpm build
Creates an optimized build in the
dist/directory (or your configuredTARGET_DIRECTORY).
Before submitting your changes, ensure your code meets our quality standards:
-
Run Linting:
pnpm run audit:lint # Check for linting issues pnpm run fix:lint # Auto-fix linting issues
-
Run Formatting:
pnpm run audit:format # Check formatting pnpm run fix:format # Auto-fix formatting
-
Run Tests:
pnpm test:unit # Run tests in watch mode pnpm test:coverage # Run tests with coverage report
-
Write Tests:
- Add test files alongside the JavaScript files they test (e.g.,
myfile.js→myfile.test.js) - The
src/tests/directory is reserved for regression tests for GitHub issues - Follow the existing test patterns using Vitest
- Ensure all tests pass before submitting
- Add test files alongside the JavaScript files they test (e.g.,
-
Test in Home Assistant:
- Use the development build to test your changes in a real Home Assistant environment
- Verify that your changes work with different configurations
- Check the browser console for any errors
-
Create a Branch:
git checkout -b feature/your-feature-name # or git checkout -b fix/your-bug-fix -
Make Your Changes:
- Write clean, readable code
- Follow the existing code style
- Add comments for complex logic
- Update documentation if needed
-
Commit Your Changes:
git add . git commit -m "feat: add new feature" # or "fix: resolve bug"
-
Push and Create a Pull Request:
git push origin feature/your-feature-name
Then open a pull request on GitHub with a clear description of your changes.
- Report Bugs: Open an issue with detailed steps to reproduce
- Suggest Features: Share your ideas for improvements
- Fix Issues: Look for open issues and submit fixes
- Improve Documentation: Help make the docs clearer and more comprehensive
- Share Templates: Contribute example templates to help others
Your contributions help make this card better for everyone!
