pg_render

Render HTML in SQL

Overview

PackageVersionCategoryLicenseLanguage
pg_render0.1.3UTILMITRust
IDExtensionBinLibLoadCreateTrustRelocSchema
4290pg_renderNoYesNoYesNoNo-
Relatedpg_html5_email_address pg_readme gzip bzip zstd http pg_net pg_curl

manual updated pgrx by Vonng

Version

TypeRepoVersionPG VerPackageDeps
EXTPIGSTY0.1.31817161514pg_render-
RPMPIGSTY0.1.31817161514pg_render_$v-
DEBPIGSTY0.1.31817161514postgresql-$v-pg-render-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
d13.x86_64
d13.aarch64
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
u22.x86_64
u22.aarch64
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
u24.x86_64
u24.aarch64
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3
PIGSTY 0.1.3

Build

You can build the RPM / DEB packages for pg_render using pig build:

pig build pkg pg_render         # build RPM / DEB packages

Install

You can install pg_render directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install pg_render;          # Install for current active PG version
pig ext install -y pg_render -v 18  # PG 18
pig ext install -y pg_render -v 17  # PG 17
pig ext install -y pg_render -v 16  # PG 16
pig ext install -y pg_render -v 15  # PG 15
pig ext install -y pg_render -v 14  # PG 14
dnf install -y pg_render_18       # PG 18
dnf install -y pg_render_17       # PG 17
dnf install -y pg_render_16       # PG 16
dnf install -y pg_render_15       # PG 15
dnf install -y pg_render_14       # PG 14
apt install -y postgresql-18-pg-render   # PG 18
apt install -y postgresql-17-pg-render   # PG 17
apt install -y postgresql-16-pg-render   # PG 16
apt install -y postgresql-15-pg-render   # PG 15
apt install -y postgresql-14-pg-render   # PG 14

Create Extension:

CREATE EXTENSION pg_render;

Usage

pg_render: Liquid template rendering for PostgreSQL

render(template text, input json|array|value)

Render a template with query results using Liquid syntax:

-- Single value
SELECT render('Total: {{ value }}', (SELECT count(*) FROM posts));

-- Multiple columns from one row
SELECT render(
    '<h1>{{ title }}</h1><p>{{ text }}</p>',
    (SELECT to_json(r) FROM (SELECT title, text FROM posts WHERE id = 1) r)
);

-- Loop over an array
SELECT render(
    '{% for v in values %} {{ v }} {% endfor %}',
    (SELECT array(SELECT title FROM posts))
);

-- Loop over multiple rows with multiple columns
SELECT render(
    '{% for row in rows %} {{ row.title }} - {{ row.author }} {% endfor %}',
    json_agg(to_json(posts.*))
) FROM posts;

render_agg(template text, input record|json|value)

Aggregate render function – renders a template for each row:

-- Render each row from a derived table
SELECT render_agg('{{ title }} {{ text }}', props)
FROM (SELECT title, text FROM posts) AS props;

-- Render using json_build_object
SELECT render_agg(
    '<article><h1>{{ title }}</h1></article>',
    json_build_object('title', title)
) FROM posts;

Using Stored Templates

SELECT render(
    (SELECT template FROM templates WHERE id = 'my_tpl'),
    (SELECT to_json(r) FROM (SELECT title, text FROM posts WHERE id = 1) r)
);

PostgREST Integration

CREATE FUNCTION api.index() RETURNS "text/html" AS $$
SELECT render(
    '<html><body><h1>{{ title }}</h1></body></html>',
    (SELECT to_json(r) FROM (SELECT title FROM posts WHERE id = 1) r)
) $$;

Last Modified 2026-03-12: add pg extension catalog (95749bf)