The utPLSQL website is generated using MkDocs and material theme Mike is used for versioning of documentation see also this page
Announcements are published with the Material blog plugin.
- Create a new post file in the docs/announcements/posts directory, in the subfolder for the year (e.g.
2026/), with the file name ofYYYY-MM-DD-Blog-Post-Name.md. This file will be a standard Markdown file which can be edited with any text editor. - Start the file with front matter:
--- title: "utPLSQL v3.2.3 released" date: created: 2026-07-10 categories: - "releases" - "utplsql-core" description: "Optional one-line summary shown on the home page card and in search results." pin: false ---
- Put
<!-- more -->after the first paragraph - everything above it is shown as the excerpt on the Announcements page. - Commit and push changes to the
mainbranch.
The post URL is built from the title (announcements/<slugified-title>.html), not from the file name or folder, so posts can be moved between folders without breaking links.
Relative links inside a post (e.g. to images in docs/assets) are relative to the post file, so they need adjusting when a post is moved.
There is no need to update mkdocs.yml or index.md - the post appears on the Announcements page and on the home page automatically.
The "Latest News" cards on the home page are generated by a custom MkDocs hook: hooks/latest_posts.py. The Material blog plugin has no built-in way to list posts on other pages, so the hook fills that gap.
How it works:
-
On every build, the hook replaces the
<!-- latest-posts -->placeholder in docs/index.md with Material grid cards for the most recent posts. -
Posts come from the blog plugin (
config.plugins["material/blog"].blog.posts), in the same order as on the Announcements page: pinned posts first, then newest first. Draft posts are skipped. -
Each card shows an icon based on the post category, the title, the date and categories, a short summary and a "Read more" link. The whole card is clickable.
-
The summary is, in order of preference:
- the
description:from the post front matter, - the first paragraph before the first list - e.g. an intro sentence written above
## What's Changedin the GitHub release notes, - the list items of the release notes, joined with
·and without author, PR and issue references (by @user in #123,Fixed in ...,resolves ...), e.g.Fix issue with UT_TAP_REPORTER on Oracle 23.26 · Fixed support for camelCase ... · +4 more.
Headings,
**Full Changelog**: ...lines, link-only lines (e.g.[Download ...](...)) and bare URLs are never used. The summary is trimmed to about 180 characters. - the
-
Posts without a
description:also get the generated summary as their<meta name="description">, used by search engines. -
Release announcements generated by the release pipeline need no changes - the summary is built from the release notes automatically.
Controlling what is shown:
- To keep a post on the home page, add
pin: trueto its front matter. Its card is shown first with the same pin badge as on the Announcements page, and the post also stays at the top of the Announcements page. Pinned posts count towardsCOUNT. Remove the flag when it should drop off. - To control the card text, add a
description:to the post front matter. - The number of cards (
COUNT), summary length (SUMMARY_LENGTH) and category icons (ICONS) are set at the top of hooks/latest_posts.py. Icons use the Material icon shortcode syntax.
Related configuration:
hooks:in mkdocs.yml registers the hook.- The
attr_list,md_in_htmlandpymdownx.emojiMarkdown extensions in mkdocs.yml are required for the cards and icons. - The
.latest-postsstyles in docs/stylesheets/extra.css make the whole card clickable and style the date line and "Read more" link.
The hook is plain Python run by MkDocs itself - no extra package needs to be installed. Note that it relies on MkDocs hooks and on internals of the Material blog plugin, so it needs to be revisited when upgrading Material or migrating to Zensical.
Announcements are published as RSS and JSON feeds by the mkdocs-rss-plugin, configured under rss: in mkdocs.yml:
- feed_rss_created.xml - newest posts first (the one to subscribe to),
- feed_rss_updated.xml - most recently updated posts first,
feed_json_created.jsonandfeed_json_updated.json- the same as JSON Feed.
Only posts under docs/announcements/posts/ are included (match_path), up to 20 newest.
Dates come from date.created / date.updated in the post front matter (git history is used when date.updated is missing), and categories become RSS categories.
The item description is the post description: or the summary generated by hooks/latest_posts.py - the same text as on the home page card.
The feeds are linked from the home page, the Announcements page and the RSS icon in the footer, and Material adds <link rel="alternate" type="application/rss+xml"> to every page, so feed readers find them automatically.
If you want to generate and preview the website locally, you will need to have python and pip installed)
To install mkdocs required components, you need to execute the below commands from command line:
pip install mkdocs-material
pip install mkdocs-git-revision-date-localized-plugin
pip install mkdocs-include-markdown-plugin
pip install mkdocs-git-committers-plugin-2
pip install mkdocs-rss-plugin
pip install mike
Once installed you can use following commands from command line:
mkdocs serve - will stat a local server, so you can see the web page generated locally and tet real-time updates to documentation
The pages are automatically generated on every commit to the main branch.
If however you would need to generate pages manually from your local copy, use the command:
mkdocs gh-deploy.
The generated web pages are hen visible at utplsql.org.
Individual project documentation pages are deployed separately from the main organization page. Each corresponding project repository needs to have its own gh-pages branch.
utPLSQL-framework repository uses mike to deploy documentation for specific project version.
Example commands to use are:
mike deploy develop- to deploy documentation for develop branchmike deploy -p develop- to deploy and push documentation for develop branchmike deploy -p -u v3.1.12 latest- to deploy and push documentation for version v3.1.12 and update thelatestalias to point to that version
Public pages: docs/sponsorship.md (become a sponsor: tiers, routes, FAQ) and docs/sponsors.md (Our sponsors: the list).
Permanent archive of sponsors: SPONSORS.md in the utPLSQL framework repository.
- Receive logo and link. Accept SVG (preferred, with text converted to outlines), or a PNG with transparent background, tightly cropped, at least 256 px high or 768 px wide (2x the large box); 1152 x 384 px (3x) is ideal. Light/dark variants if needed. If only a lockup is supplied at the 64 px (small) size, ask for the wordmark or use the name as text.
- Store the logo in the
utPLSQL/.githubrepository (the organization repository), in.github/assets/sponsors/, namedsponsor-<name>.pngorsponsor-<name>.svg(lowercase, hyphens; for light/dark variantssponsor-<name>-light.svgandsponsor-<name>-dark.svg). This follows the layout of the Material for MkDocs repository. All surfaces reference the file by its raw URL,https://raw.githubusercontent.com/utPLSQL/.github/main/.github/assets/sponsors/sponsor-<name>.<ext>. Do not hotlink the sponsor's own site. - Add the entry to the matching grid in
docs/sponsors.md. For 500 EUR and commercial sponsors also add it to the framework README, the organization profile README (.github/profile/README.md) and the landing page block indocs/index.md(markersponsors-landing). 250 EUR sponsors: organization profile only. - Add the name and start year to
SPONSORS.md. - 500 EUR and commercial sponsors: announce on LinkedIn, X and Bluesky.
- At the end of the paid period plus 30 days, remove the logo from the framework README, the organization profile and the landing page.
- If the sponsor qualifies (3 months or a commercial agreement), move the entry to the Past sponsors grid in
docs/sponsors.md. Otherwise delete it. - Update
SPONSORS.md(end year).
Doing this by hand across four repositories drifts. Once there is a first paying sponsor, generate all blocks from one sponsors.yml (fields: name, url, logo, tier, start, end, status current or past) with a scheduled GitHub Action.
| State | When | Where the sponsor appears |
|---|---|---|
| Current | from the first payment (GitHub Sponsors) or from receipt of the invoice payment (direct invoice) until the end of the paid period | per tier, see the recognition table in docs/sponsorship.md |
| Grace | 30 days after the end of the paid period (failed card payments, late renewals) | unchanged |
| Past | after the grace period, only if the sponsor paid for at least 3 months, or had a commercial support agreement | docs/sponsors.md "Past sponsors" only, as a faded logo with no details. Removed from the GitHub organization profile, framework README and utplsql.org landing page. |
| Lapsed | after the grace period, sponsored for less than 3 months and no commercial agreement | removed everywhere except the archive (SPONSORS.md in the utPLSQL framework repository) |
| Archive | always | SPONSORS.md: name and year(s) only, kept permanently |
Other rules:
- A past sponsor is removed from the Past sponsors section on request, the same day. The archive entry is also removed if they ask.
- Individuals are not listed on utplsql.org. GitHub shows public individual sponsors on the GitHub Sponsors page.
- Release notes carry a link to
https://www.utplsql.org/sponsors.html, never a list of names. - Commercial support never ends up in the recognition tiers by accident: someone who paid through GitHub gets recognition only, no support. Move them to a commercial agreement instead (see the channel separation in the sponsorship notes).
- The user-facing wording of these rules is the FAQ "What happens when we stop sponsoring?" in
docs/sponsorship.md. Change both together.
Every sponsor is a clickable logo (or a text link for 100 EUR sponsors) inside a grid. No tables. All organization tiers include a backlink to the sponsor's website: every logo (company name only as a tooltip via the standard Markdown image title, , and as the alt text for accessibility; never printed next to the logo) and every 100 EUR name is a link to the URL supplied at onboarding, opened in a new tab with rel="noopener sponsored" (sponsored marks paid placements for search engines). In READMEs use a plain Markdown link.
| Group | Section on the page | Grid class | Logo |
|---|---|---|---|
| Commercial support | "Commercial support sponsors" | sponsor-grid sponsor-grid--large |
128 px high, max 384 px wide (3:1), 32 px clear space |
| 500 EUR | "Organization sponsors", first | sponsor-grid sponsor-grid--large |
128 px, as above |
| 250 EUR | "Organization sponsors", second | sponsor-grid sponsor-grid--small |
64 px high, max 192 px wide (3:1), 16 px clear space |
| 100 EUR | "Organization sponsors", last | sponsor-grid sponsor-grid--text |
company name as a text link |
| Past | "Past sponsors" | sponsor-grid sponsor-grid--past |
64 px high, max 192 px wide, grayscale, 55% opacity, logo only |
Order inside a group: by start date, oldest first. Commercial support is listed above the recognition tiers.
Entry format (one blank-line-separated item per sponsor; markdown attribute is required on the div):
<div class="sponsor-grid sponsor-grid--large" markdown>
[](https://company.example){ target=_blank rel="noopener sponsored" }
</div>For sponsors that supply separate light and dark logos, add two images with the classes { .logo-light } and { .logo-dark }.
Put each group between its marker comments (<!-- sponsors-commercial --> ... <!-- /sponsors-commercial -->, <!-- sponsors-organizations --> ... <!-- /sponsors-organizations -->) and delete the "There are currently no ..." sentence when the first entry is added.