app.zeens.portfolio
Configuration for a user's public Portfolio site (e.g. alice.zeens.app). One per user, keyed 'self'. A portfolio is a curated list of the user's COLLECTIONS, displayed beautifully: it holds the subdomain, a theme + layout/columns/gap applied to every collection, the ordered list of collection AT-URIs to show, and an optional home collection. Collections own their own title/subtitle/description/photos/slug, which the portfolio reuses; the site header comes from the user's profile. Stored on the user's own PDS so the site is portable and user-owned; PocketBase only mirrors {subdomain -> did} for host routing + uniqueness. Rendered publicly only when `enabled` is true.
Details · record, key literal:self
| Kind | record |
|---|---|
| Record key | literal:self |
| Authority | zeens.app |
| Indexed |
Record
record · key literal:selfProperties
about
refOptional About page (alice.zeens.app/about). Absent, or present with enabled=false, means the portfolio has no About page and no About entry in its rail.
app.zeens.v
integerZeens marker so the firehose / lua filters can identify our records.
appearance
stringLight/dark appearance. 'auto' (default) follows the visitor's system preference; 'light'/'dark' force the theme's respective palette.
knownValues: auto | light | dark
collections
arrayOrdered list of the collections shown in the portfolio menu. Each entry references an app.zeens.collection record on the same repo. Array order is the menu order.
maxLength: 50
columns
integerColumn count for grid/masonry layouts. Allowed 2-4. Default 3.
minimum: 2maximum: 4
Whether the public site is live. When false, the subdomain 404s even if reserved.
featured
refHand-picked photos under a heading the owner chooses, shown on the home page below the hero. Independent of any collection. Absent means no section.
gap
integerGap in pixels between photos. Allowed 0, 4, 8, 16, 24, 32. Default 8.
minimum: 0maximum: 32
hero
refThe home page's hero — the owner's own photos across the top. ABSENT DOES NOT MEAN NO HERO: the render path falls back to the owner's 6 most-liked photos as a square grid, so a portfolio has a hero without its owner picking one. Present means they chose the photos themselves.
home
refOptional plain-text heading + paragraph shown ABOVE the home page's existing content (the collection card grid, or homeCollection's photos when one is set). Absent means the home page renders exactly as it did before this field existed, so no portfolio changes without its owner acting.
homeCollection
string · at-uriDEPRECATED. AT-URI of a collection rendered inline as the portfolio's home page. Superseded by the portfolio's own home page (see `home`): the editor no longer offers this, and new records should not set it. Still honoured on read so existing sites don't change appearance, and the editor lets an owner who has it set turn it off.
layout
stringPhoto layout applied to every collection shown in the portfolio. 'single' = one full-width column; 'grid' = uniform columns; 'masonry' = variable-height columns.
knownValues: single | grid | masonry
palette
stringId of the chosen color palette (each has a light+dark variant, defined app-side, e.g. 'mono'). Independent of typography. Unknown/absent falls back to the default at render time. (Legacy records may carry a bundled 'theme' field instead; read paths migrate it.)
maxLength: 64
socials
refWhich of the owner's profile social links the public site shows. ABSENT MEANS SHOW ALL — every portfolio created before this field keeps showing every link with no migration.
subdomain
stringThe chosen subdomain slug (the 'alice' in alice.zeens.app). Lowercase DNS-safe label; uniqueness + reserved-word validation happen at write time and are mirrored into the PB portfolio_slugs table. Absent until the user picks one.
maxLength: 63
tagline
stringOne-line tagline for the site. Mirrored onto site.standard.publication.description, since the portfolio IS the publication — this is the line other standard.site readers show under the name.
maxLength: 2000maxGraphemes: 200
title
stringCustom site title shown in the portfolio rail (free text, e.g. 'Ro', 'Alice Photography'). Falls back to the user's profile display name when absent.
maxLength: 120
typography
stringId of the chosen typography pairing (font choice, defined app-side, e.g. 'space-grotesk'). Independent of palette. Unknown/absent falls back to the default at render time.
maxLength: 64
#aboutLink
objectOne titled external link on the About page. Readers MUST re-validate `url` and accept only https: the record lives on the owner's PDS and any client can write it, so the value reaches an href untrusted. Writers upgrade a typed http:// to https:// rather than storing insecure links.
#aboutPage
objectThe portfolio's About page. Plain text, like #homePage. The owner's portrait is NOT stored here: `useProfileAvatar` is a flag and the avatar is resolved from the profile at render time, so it tracks their Zeens avatar with no copy to go stale.
Properties
body
stringAbout text, rendered with preserved line breaks.
maxLength: 4000
Whether the About page exists and appears in the rail.
heading
stringPage heading, also used as the rail's label for it. Defaults to 'About' when absent.
maxLength: 120
links
arrayTitled external links shown as one horizontal row above the About photo grid (e.g. 'Buy prints', 'My Instagram'). Distinct from the profile socials in the rail: those are platform accounts, these are anything the owner wants to point at.
maxLength: 8
photos
arrayPhotos chosen from the owner's own posts, in display order. Rendered as a grid below the About text: one photo full width, two side by side, three or more in three columns (six fills a 3x2 grid). Only the first image of a multi-image post is shown.
maxLength: 6
useProfileAvatar
booleanShow the owner's live profile avatar as the portrait. Opt-in: absent means false, so a portrait never appears on the public page unless the owner asked for it.
#aboutPhoto
objectA reference to one of the owner's own posts, used wherever a block stores picked photos — the About page, page heroes, and Featured Work. Named for its first use; kept under that name because renaming a def would orphan the records already pointing at it.
#collectionRef
objectA reference to one of the user's collections, in menu order.
Properties
AT-URI of an app.zeens.collection record on the owner's repo.
#featuredBlock
objectFeatured work: photos picked directly rather than through a collection. The heading is the owner's own — 'Featured Work' is one gallery's word for it and 'Selected' or 'Latest' is another's.
Properties
Photos chosen from the owner's own posts, in display order.
maxLength: 12
title
stringSection heading. ABSENT MEANS 'Featured Work' — the default lives in the render path, so it is not frozen into every record.
maxLength: 60
#heroBlock
objectA page hero: the owner's photos across the top of a page. One def serves all three arrangements because they are the same data seen differently. A hero with no photos is dropped on write rather than stored empty — an absent hero falls back to the owner's most-liked photos, which is a better empty state than a blank band.
Properties
'single' = one full-width photo; 'carousel' = a swipeable run of them; 'grid' = all of them as a grid. Unknown/absent reads as 'single'.
knownValues: single | carousel | grid
Photos chosen from the owner's own posts, in display order. Only the first image of a multi-image post is used.
maxLength: 6
#homePage
objectPlain-text intro shown at the top of the portfolio home page. Deliberately NOT rich text: it renders into a public page, so a markup format would need sanitising and carry XSS surface. Mirrors how collections store their description.
#socialsVisibility
objectControls which profile social links the public portfolio shows. Filtering is applied server-side AFTER the Bluesky link is synthesised from the owner's handle, so hiding Bluesky works even though it is not stored on the profile record.
Similar lexicons
semantic matchLexicons whose schemas describe something close to this one. Check them before publishing a new one that overlaps.
-
app.zeens.collection
recordA user-curated collection (folder) of Zeens posts and articles. Visibility controls whether anyone other than the owner can see it via the AppView. The cover is the owner's chosen `coverPhoto` when set, otherwise the most recently added item, resolved at render time.
-
page.mooring.site
recordConfiguration for a Mooring site. The record at rkey 'self' is the owner's default site; other rkeys are reserved for possible future multi-site support.
-
site.mochott.layout
recordA block-based page layout. Renders the home of a mochott profile or of a minisite.
-
app.zeens.zeen
recordA zeen: a sequence of 1:1.414 pages (ISO A-series proportion) mixing photographs and writing, published as a readable object. Pages may draw photos from a collection, from individual posts, or from the author's own uploads — a zeen is a standalone document, not a view of a collection. The AUTHORED PAGES are the artifact: layout is recomputed from them at read time, so a layout improvement reaches every existing zeen. Replaces an earlier record of this NSID that described a print-ready PDF; that
mode
requiredstring'all' (also the meaning of an absent socials field) shows every link; 'selected' shows only the platforms in `shown`; 'none' hides the block entirely, website included.
knownValues: all | selected | none