OmniCon 2.0.185 — Forms, invitations, custom layouts, 301 redirects, and a much faster API
May 28, 2026
Forty-one versions since 2.0.144. Drop a form on any page and collect submissions, invite teammates by email, design channel templates with Handlebars, mark moved content with a 301, upload custom web fonts, bring your own domain in one click, and the article-read API is now an order of magnitude faster after a deep performance pass. Plus MCP tokens that survive deploys and a long tail of editor polish.
2.0.185 is forty-one versions on from 2.0.144. Seven things stand out: Form blocks on any page, team invitations, custom Handlebars layouts with rollback, 301 redirects for moved articles and pages, web font uploads, a much faster article API, and MCP tokens that survive restarts.
Forms on any page
Build a form inside a custom layout, embed it on any page, and collect submissions without writing a backend.
- Form block in the page editor. Add fields, set required/optional, mark which one is the reply-to email — all from the block inline editor.
- reCAPTCHA built in. Configure a site key once per channel under Integrations; every form on that channel uses it automatically.
- AJAX submit. Visitors stay on the page; the form posts to
/forms/submitand shows your success message inline. - Per-form email template. Dedicated editor lets you customize the auto-reply and the admin notification separately for each form.
- Submissions dashboard. Every submission lands under Channel → Form Submissions with a list view + detail view — searchable, with the original field values preserved.
Invite your team
Real multi-user workflows for an organization.
- Invite by email. From the Organization page, send an invitation to anyone — they get a magic link in their inbox.
- Pre-filled signup. The invite link takes new users to a Register page with the email already filled. One click in, no copy-paste mistakes.
- Auto-redeem on signup. Accepting the invite happens transparently as part of registration — no separate "starter workspace" step to skip.
- Manage pending invites. The org detail page lists who's been invited but hasn't joined, with controls to remove or change role before they accept.
- Welcome message. Invited users land on a brief welcome instead of the generic empty dashboard.
Custom Handlebars layouts
Layouts and partials are now first-class — design top pages, list pages, and detail pages from scratch, not just tweak the built-in templates.
- Layout CRUD over the API and MCP. Create, update, and bind layouts programmatically. Useful when you're managing a fleet of channels and want them in sync without clicking through each dashboard.
- One-deep rollback. Each layout keeps its previous version on save, so undoing a bad change is one click — no git required.
- SearchResults page block. Surface keyword search results inside any custom layout, so search-driven landing pages don't need a separate template.
- Block editor ↔ Raw HTML toggle. Pages can be built with the block builder or hand-written HTML, and you can flip between modes per page.
- Layout binding via MCP. Pin a specific layout to a channel surface (list / detail / top page) from the conversational interface.
301 redirects for moved content
Mark an article or page as moved, type the new URL, and the public site responds with a permanent redirect instead of serving the old content. SEO-safe migrations without a server config change.
- Tick "This article has moved" in the editor. A URL input un-hides; save and the public URL becomes a 301 to your new home.
- Same UX for pages. The page block editor exposes the same controls — works for both articles and static pages.
- Drivable by MCP. The
create_article,update_article, andupdate_article_metadatatools all acceptisMoved+redirectUrl— tell Claude "mark this article as moved to example.com/new" and it does. - API consumers see it too. The
/articleresponse includesisMovedandredirectUrlso headless apps can honour the move themselves.
Bring your own domain
Custom domains are now a portal flow, not a support ticket.
- One-click registration. Add a custom domain in the channel settings; OmniCon registers it with Azure Front Door automatically.
- Apex domains supported. Both
example.comandwww.example.comwork — the apex case used to require manual setup. - Verification through Front Door. The TXT-record verification step is handled inline with clearer UX and faster feedback.
- Recovers from collisions. If a domain registration runs into a Front Door 409 ("already exists"), the flow now resolves it rather than failing.
- Edge-cache hardening. Headers tuned so Front Door serves the right content per culture / per channel without bleed.
Web fonts
Upload .woff2, .woff, .ttf, and .otf files alongside the rest of your channel media. Use them in a @font-face rule in a custom layout or asset to ship a fully branded site.
- Drag-and-drop into the Documents space. Fonts pass the same allowlist and quota checks as other documents.
- Browsers don't always tell us the type. An extension-based fallback maps
.woff2→font/woff2when the browser sendsapplication/octet-stream, so uploads succeed and the blob is stored with the right Content-Type — browsers actually render the font from its URL. - Reachable by MCP too.
upload_fileacceptscontentType: 'font/woff2'for AI-driven setup.
A much faster article API
The article-read endpoints were customer-reported at 12–24 seconds. After this release they're under 500 ms on a warm cache, well under 1 second cold.
- Parallel internal fetches. Author, channel, and blob-body reads now run concurrently inside
GetArticleViewinstead of one after the other. - Point-read lookups. Article-by-ID is a direct table point read, not a filtered scan.
- Response cache on the list endpoints. A 15-second body-aware OutputCache absorbs burst traffic on
/articlesand/articles-stats. - Background-queued analytics. Impression logging and search-keyword recording moved off the request thread to a hosted background worker.
- Search-keyword history is cached. The popular-searches sidebar used to scan an entire partition on every list call; now it's read-through cached for 5 minutes.
- Table provisioning at startup. The 570 ms of
CreateIfNotExistsoverhead that used to run on every request now happens once when the process boots. - Redis resilience. The cache layer is now genuinely non-load-bearing — 200 ms operation timeouts plus a circuit breaker mean a Redis hiccup costs ~600 ms total, not 10+ seconds.
MCP that stays logged in
Until now, every App Service restart silently invalidated all active MCP access and refresh tokens — Claude and other MCP clients had to re-OAuth on the next request. That's gone.
- Persistent signing & encryption keys. OpenIddict now reads its keys from configuration (either X.509 certificates or base64-encoded PEMs in App Settings) instead of regenerating ephemerals on each boot.
- 24h access / 90d refresh lifetimes. Same shape as GitHub or Slack personal tokens — quarterly re-auth at most, not per-deploy.
- Cross-service validation via JWKS. apiCms validates MCP-issued JWTs by fetching the public key from MCP's
/.well-known/jwks.json— true stateless cross-service auth. - RFC 9728 protected-resource metadata. MCP clients can now auto-discover the auth server when they hit a 401, so the OAuth flow starts itself.
Also in this release
- Voice tags now interpret in rcr.la audio. The reading-script generator emits ElevenLabs v3 inline tags (
<emphasis>,[laughs],<break time="..." />); we now pinmodel: "v3"on the rcr.la/speakcall so the tags become audio cues instead of being read out as plain text. - Article bodies bigger than 64 KB now spill to blob storage transparently. Reads hydrate the body so consumers see the full article without knowing about the blob.
- Media: SVG & AVIF. SVGs are sanitized on upload; AVIF is accepted alongside JPEG/PNG/WebP. The document picker also accepts a broader range of office formats.
- Channel theme: layout + custom CSS. Toggle content-layout style per channel and inject your own CSS without touching the layout templates.
- File detail page. The blob URL now sits in a copyable input next to a "copy to clipboard" button.
- Pages list redesigned. Now uses the same card layout as the Articles list — whole row is clickable, no per-row action buttons. Delete moved to the editor header.
- Faster public channel pages. Same caching pass as the article API extended to
ChannelsControllerIndex/Details — public reads served from cache when safe. - Usr area: shared layout polish. Breadcrumb is now centralized in the shared layout so every page renders it the same way.
- Bug fix: article-impression IDs. The impression table was truncating long article IDs at 36 chars; widened to 120 so every read is counted.
- Bug fix: "Channel field is required" on asset save. Creating a new CSS asset failed with a validation error pointing at a field that wasn't on the form. The view model's
Channelproperty now skips validation so the save goes through. - Bug fix: "Headers are read-only" in public pages. The Cache-Control middleware that ensures Front Door doesn't cache error pages was throwing when a controller had already started streaming the response. Moved into
Response.OnStartingso the header sets at the right point in the pipeline. - mcpCms hardening. Startup now fails fast on an empty SQL connection string instead of erroring deep inside OpenIddict; the 401 response includes RFC 9728
resource_metadataso MCP clients can auto-discover the auth server.
Form blocks and team invitations are the headline features for end users; 301 redirects and web fonts unblock long-running content moves and brand-tight sites; the rest is invisible-but-welcome polish. If you'd like a hand wiring up forms, designing a custom layout, marking a redirect, or building on the much-faster API, drop us a note.