Introducing PSJinja: Jinja2 Templates for PowerShell
Move beyond simple string interpolation. PSJinja brings full Jinja2 templating to PowerShell — with variables, conditionals, loops, and filters for …
Read more →A PowerShell module that brings Jinja2 templating to your scripts — render dynamic content with variables, conditionals, loops, and filters.
PSJinja is a PowerShell module that brings the power of Jinja2 templating to your scripts. Unlike logic-less Mustache templates, Jinja2 supports a rich set of control structures — conditionals, loops, filters, and macros — making it the go-to templating language for complex dynamic content generation.
Use PSJinja anywhere you need expressive, data-driven text output: infrastructure-as-code configs, deployment manifests, HTML reports, email bodies, and more.
Install from the PowerShell Gallery:
# Install for current user
Install-Module -Name PSJinja -Scope CurrentUser
# Install system-wide (requires elevation)
Install-Module -Name PSJinja
# Import after installation
Import-Module PSJinja
Import-Module PSJinja
# Define a Jinja2 template string
$template = "Hello, {{ name }}! You have {{ count }} new messages."
# Provide data as a hashtable
$data = @{
name = "Alice"
count = 5
}
# Render the template
$result = Invoke-PSJinjaTemplate -Template $template -Data $data
# Output: "Hello, Alice! You have 5 new messages."
Write-Host $result
# template.j2
# Dear {{ recipient }},
# Your order #{{ order_id }} has been {{ status }}.
$data = @{
recipient = "Bob Smith"
order_id = "ORD-9821"
status = "shipped"
}
$result = Invoke-PSJinjaTemplate -TemplatePath "template.j2" -Data $data
Write-Output $result
Invoke-PSJinjaTemplateRenders a Jinja2 template with the provided data.
| Parameter | Type | Description |
|---|---|---|
-Template | string | Template content as a string |
-TemplatePath | string | Path to a .j2 or other template file |
-Data | hashtable | Variables to pass into the template |
-TemplateDir | string | Directory to search for included/extended templates |
{{ variable }}
{{ user.name }}
{{ items[0] }}
Apply transformations to values using the pipe | operator:
| Filter | Example | Description |
|---|---|---|
upper | `{{ name | upper }}` |
lower | `{{ name | lower }}` |
default | `{{ value | default(‘N/A’) }}` |
length | `{{ items | length }}` |
join | `{{ list | join(’, ‘) }}` |
replace | `{{ text | replace(‘old’, ’new’) }}` |
trim | `{{ text | trim }}` |
{% if environment == "production" %}
Log level: Warning
{% elif environment == "staging" %}
Log level: Info
{% else %}
Log level: Debug
{% endif %}
{% for server in servers %}
- {{ server.name }}: {{ server.ip }}
{% endfor %}
{# This is a comment and will not appear in the output #}
Import-Module PSJinja
$template = @"
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ app_name }}-config
namespace: {{ namespace }}
data:
{% for key, value in config.items() %}
{{ key }}: "{{ value }}"
{% endfor %}
"@
$data = @{
app_name = "my-api"
namespace = "production"
config = @{
DB_HOST = "prod-db.internal"
DB_PORT = "5432"
LOG_LEVEL = "warning"
CACHE_TTL = "3600"
}
}
$result = Invoke-PSJinjaTemplate -Template $template -Data $data
$result | Out-File "configmap.yaml" -Encoding utf8
# appsettings.j2
# {
# "ConnectionStrings": {
# "Default": "Server={{ db_server }};Database={{ db_name }}"
# },
# "Logging": {
# "LogLevel": {
# "Default": "{{ log_level }}"
# }
# },
# "FeatureFlags": {
# {% for flag, enabled in features.items() %}
# "{{ flag }}": {{ enabled | lower }}{% if not loop.last %},{% endif %}
# {% endfor %}
# }
# }
$data = @{
db_server = "prod-sql.company.com"
db_name = "AppDatabase"
log_level = "Warning"
features = @{
DarkMode = $true
BetaFeatures = $false
Analytics = $true
}
}
Invoke-PSJinjaTemplate -TemplatePath "appsettings.j2" -Data $data |
Out-File "appsettings.json" -Encoding utf8
$template = @"
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<h1>{{ title }}</h1>
<p>Generated: {{ generated_at }}</p>
<table>
<tr><th>Server</th><th>Status</th><th>CPU %</th></tr>
{% for server in servers %}
<tr class="{{ 'ok' if server.online else 'error' }}">
<td>{{ server.name }}</td>
<td>{{ 'Online' if server.online else 'Offline' }}</td>
<td>{{ server.cpu }}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
"@
$data = @{
title = "Server Status Report"
generated_at = (Get-Date -Format "yyyy-MM-dd HH:mm")
servers = @(
@{ name = "WEB-01"; online = $true; cpu = 45 }
@{ name = "WEB-02"; online = $true; cpu = 62 }
@{ name = "DB-01"; online = $false; cpu = 0 }
)
}
Invoke-PSJinjaTemplate -Template $template -Data $data | Out-File "report.html"
Contributions are welcome! See the GitHub repository for details.
PSJinja is released under the MIT License.