GitHub composite action that generates an RSS 2.0 feed (rss.xml) from any PostgREST/Supabase relation and writes it into your repository, so it can be committed or deployed with your static site.
jobs:
generate-rss:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: AFischbeck/supabase-rss-action@v1
with:
supabase-url: ${{ secrets.SUPABASE_URL }}
supabase-key: ${{ secrets.SUPABASE_KEY }}
base-url: https://your-site.com
output-dir: public
table: posts
filter: is_public=eq.true
order: created_at.desc
feed-title: Your Site
feed-description: Latest posts from your-site.com
feed-entries: '[{"path": "/post/{slug}", "title": "title", "pubdate": "created_at", "description": "body"}]'| Input | Required | Default | Description |
|---|---|---|---|
supabase-url |
no* | — | Supabase project URL |
supabase-key |
no* | — | Supabase API key (anon or service role) |
base-url |
yes | — | Base URL of the site |
table |
no* | — | PostgREST relation (table or view) to fetch rows from; required when feed-entries is set |
feed-title |
yes | — | Channel <title> |
feed-description |
yes | — | Channel <description> |
feed-link |
no | base-url/ |
Channel <link> |
feed-language |
no | en |
Channel <language> |
feed-entries |
no | [] |
JSON array of row-route objects (see below); empty means a metadata-only feed and no API call is made |
select |
no | derived | Comma-separated columns to fetch; defaults to all columns referenced by feed-entries |
filter |
no | — | PostgREST predicate(s), e.g. is_public=eq.true. &-separated predicates are supported. |
order |
no | — | PostgREST order expression(s), e.g. created_at.desc |
api-path |
no | /rest/v1 |
PostgREST API path |
limit |
no | — | Maximum number of rows to fetch (PostgREST caps results, so set this if you have many rows) |
output-dir |
no | public |
Directory to write rss.xml into |
* table, supabase-url, and supabase-key are only needed when feed-entries is set; a metadata-only feed runs without them.
Each feed-entries entry produces RSS items from the fetched rows — one item per row, deduplicated by absolute link across entries:
{"path": "/post/{slug}", "title": "title", "pubdate": "created_at", "description": "body"}| Field | Required | Description |
|---|---|---|
path |
yes | URL template with {column} placeholders; used for both <link> and <guid> (guid = absolute link) |
title |
yes | Column name for <title> |
pubdate |
no | Column name (ISO timestamp) for <pubDate>, formatted RFC 822; omitted if unparseable |
description |
no | Column name (markdown) for <description> |
description-length |
no | Truncation length in chars (default 500) |
strip-markdown |
no | Strip markdown from the description (default true) |
Rows missing title or any path placeholder column (or containing empty values) are skipped. <description> is always emitted, empty when the column is unset or the value is empty.
MIT