Sharing and publishing
By default a page is private to your workspace. This page covers what "private" means, how to make a page publicly readable, what the public URL looks like, what visitors can do on a public page, and how to control branding and visibility settings.
Workspace-visible Pages
Every page you create starts as private. In this state:
- Only authenticated users who are members of your workspace can read or edit the page.
- The page is not reachable from any public URL.
- Even if someone guesses the page's
alias_id, unauthenticated requests return a 404.
Project membership does not affect visibility. A page's visibility is set at the page level, regardless of which project it belongs to.
Sharing with specific people
Targeted sharing (inviting specific people by email or generating per-person access tokens) is not yet implemented. The share model is currently all-or-nothing: either workspace-private or world-readable.
If you need to share a page with someone outside your workspace today:
- Invite them to the workspace and grant member access, or
- Toggle the page public (see below) and share the link.
Public publishing
Make any page publicly readable in two steps:
- Open the page in the workspace panel.
- Click Share in the action bar (bottom of the panel) or the Share icon in the panel header.
The Share dialog opens. Click the PRIVATE toggle to switch it to PUBLIC. The change takes effect immediately — anyone with the URL can read the page without signing in.
The shareable URL has the format:
https://<your-origin>/<workspaceAliasId>/p/<pageAliasId>
Both alias segments are 12-character opaque tokens automatically generated from the underlying UUIDs (for example NWY5YjJhMDE_). They are stable: they are set once at creation and never change.
Copy the link with the copy button, or open it in a new tab with the external-link button. To make the page private again, click the PUBLIC toggle to switch back to PRIVATE.
What visitors see
On a public page, visitors get a clean reader view:
- Your workspace name and icon at the top (optional — see Branding below).
- The page's cover image if you've set one (optional).
- The page icon, title, and description.
- The full page body, read-only — no editing toolbar, no slash menu.
- A "Built with Onnie · Create a free workspace" footer at the bottom (optional on paid plans).
Every block type — headings, lists, callouts, code blocks, images, two-column layouts — renders the way you'd expect. Embeds are where the public surface gets interesting.
Embeds on a public page
The six embed types all render on the public surface with appropriate behavior:
- Table embeds show the same row data the workspace view does, server-rendered into the page so they're visible to search engines and load instantly.
- Record embeds are visible read-only. Clicking the card opens a signup CTA so visitors can sign up before drilling in.
- Gallery embeds route to other public pages directly via in-app links. Tiles pointing at private pages open the signup CTA — no link leakage.
- Export embeds download the page as PDF or Markdown, same as in the workspace.
- Routine embeds — see Public routine runs below.
- Form embeds — see Public form submissions below.
Public form submissions
A form embed on a public page accepts submissions from anyone who can read the page. The visitor flow is:
- Fill in the configured fields.
- (If the form doesn't include an email column, an extra "your email" row is auto-added so we can attribute the submission.)
- Solve a Cloudflare Turnstile challenge — invisible most of the time, occasionally a checkbox.
- Click submit.
On success, the visitor sees your custom success message (or a default "Thanks for your submission" if you didn't set one), and a new record lands in the target table. The visitor's email is stored on the record's submitted_by_email field, and a separate audit row captures the submission with hashed IP and user-agent.
Workspace admins see every submission in a SUBMISSIONS tab on the table panel. Click OPEN ↗ to jump to the resulting record.
The submit endpoint enforces a public-safe column whitelist. Formula, computed, AI-generated, and reference columns are blocked at insertion time and also rejected server-side. Email-typed columns are validated against a standard regex.
Public routine runs
A routine embed on a public page lets visitors trigger the routine after providing their email. The flow:
- Click the routine button. A popover opens.
- Enter your email (and optionally your name).
- Solve the Turnstile challenge.
- Click Run.
The popover transitions through Queued… → Running… → Done. While it runs, the popover polls a status endpoint every two seconds. When the routine completes, the popover shows the output (or a generic "Done — you'll receive an email shortly" if the routine has no return value).
The run is debited from your (the workspace owner's) credits — same as a routine run triggered from inside the workspace. There's an audit trail in public_routine_runs capturing the email, hashed IP/UA, page, and embed node.
Rate limiting protects against abuse:
- 5 runs per hour across the same IP or email.
- 20 runs per day across the same IP or email.
Hitting either limit returns a generic "try again later" message; subsequent legitimate visitors are unaffected.
There's no per-routine kill switch yet. If a public routine starts seeing abuse, the immediate remedy is to toggle the page is_public = false, which severs all public access including the routine button.
Branding
The Share dialog shows a Public appearance section when the page is public, with these controls:
| Control | What it does |
|---|---|
| Font | Switch the public-page typography between Sans, Serif, or Mono. |
| Accent color | Pick a color for the conversion footer's background. Six presets (green, sky, purple, amber, red, ink) cover most brand palettes. |
| Show workspace header | Toggles the workspace name/icon strip at the top of the public page. Useful when you want the page to feel like its own site instead of an Onnie-branded space. |
| Show cover | Toggles the cover image at the top of the article. |
| Show footer | Toggles the "Built with Onnie" conversion footer. Available on Pro+ workspaces — free workspaces always show the footer. |
| Indexable by search engines | Controls the <meta name="robots"> tag. On (default) → indexable; off → noindex, nofollow. |
Changes save instantly. Refresh the public URL to see the result.
SEO
Public pages set proper metadata automatically:
- Title —
{page title} · {workspace name} - Description — the page description, or absent if you haven't set one
- OpenGraph — title, description, cover image (when set),
type=article - Twitter card —
summary_large_imagewhen a cover is set, otherwisesummary - robots — controlled by the Indexable toggle in the Share dialog
The public URL is locale-prefixed (/en/<wsAlias>/p/<pageAlias>, /pt-BR/<wsAlias>/p/<pageAlias>, etc.). The page content itself is whatever you wrote — there's no auto-translation. The locale prefix only affects the chrome (footer copy, sign-up CTA copy).
The alias is opaque (12-character base64). For now there's no SEO-friendly slug — when you share a public-page URL, the URL won't read like a marketing slug. A future release may add an optional custom slug.
Reverting to private
Click the PUBLIC toggle back to PRIVATE to revoke public access. The page becomes a 404 to anyone hitting the public URL after that — including any open tab a visitor might already have.
Embed-resolved data is server-side at request time, so flipping a page private also pulls the rug from all table/record/routine embeds it contained — public visitors don't get to see cached embed data.
If you'd already shared the URL widely, anyone who saved a screenshot still has that. Toggling private only protects the live document.