Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

home source realm

Package home is the realm behind [https://gno.land/u/clockwork](https://gno.land/u/clockwork).

Readme View source

home

The realm behind the profile page at /u/<namespace>. gnoweb calls Render("") on the realm at exactly /r/<namespace>/home, so this path is permanent and everything that may change lives behind it:

  • Content is slots: named markdown fragments, one Set transaction each.
  • Layout is the slot named layout, a template filled from :slug: placeholders.
  • Style is slots under style. that the theme reads.
  • Rendering is a theme: a realm under home/theme/vN that registers itself when deployed and goes live when the authority runs Accept. Rollback reverts. The slots never move.

The upgrade machinery is p/<namespace>/upgradeable/v0.

Views

path what
:slots slot index
:slots/<slug> one slot, raw
:edit, :edit/<slug> forms that build the Set and Delete commands
:system authority, live theme, candidates, history, operations
:manifest slug⇥rev⇥bytes⇥sha256 per slot, for tooling

These four are served by this realm directly and never go through a theme, so a theme that panics can be rolled back from :system. Every other path is the theme's.

Writes

Restricted to the authority: Set, Append, Delete; Accept, Withdraw, Rollback, Forget, Freeze, TransferAuthority. A slug is 1 to 64 bytes of [a-z0-9._-]; the computed placeholders chainid height owner realm rev slots theme updated are reserved.

Overview

Package home is the realm behind https://gno.land/u/clockwork.

gnoweb builds a user profile page by calling Render("") on the realm at the exact path /r/<username>/home (gno.land/pkg/gnoweb/handler_http.go, GetUserView). That lookup does no version resolution, so this path is the interface with gnoweb and can never carry a /vN suffix. Everything that might want to change therefore lives behind the path, in four layers:

  1. CONTENT is data. The page is assembled from SLOTS: named markdown fragments in an avl tree, each written by its own Set call. Updating one paragraph is one small transaction.
  2. LAYOUT is data. The slot named "layout" is the page template; every :slug: placeholder in it is filled from the slot of that name.
  3. STYLE is data. Slots under the "style." prefix are knobs (colors, header mode) that the theme reads. Changing the accent color is a Set.
  4. RENDERING is code, but replaceable. A THEME is a separate realm nested under this one that implements Theme and registers itself from its own init. The authority accepts it through p/clockwork/upgradeable and can roll it back. The slots never move: an upgrade replaces the code that reads them, not the data. When no theme is live the built-in renderer in render.gno serves the page, and the operator views (system, slots, edit, manifest) are always served by this realm, so a theme that panics can be rolled back from the page it cannot break.

This realm holds state and forwards. It is deliberately small, because it is the one piece that can never be redeployed: it is importable by its themes, so it cannot be private, so AddPackage refuses a second deploy.

Constants 2

const LayoutSlug, StylePrefix, maxSlugLen

 1const (
 2	// LayoutSlug names the slot used as the page template.
 3	LayoutSlug = "layout"
 4
 5	// StylePrefix marks slots that are style knobs rather than content.
 6	// Style("accent", ...) reads the slot "style.accent".
 7	StylePrefix = "style."
 8
 9	// maxSlugLen bounds a slot name so an index row stays readable.
10	maxSlugLen = 64
11)
source

const Admin

1const Admin = address("g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm")
source

Admin is the initial authority: the only address that may write slots and accept, roll back or freeze a theme. It is a constant so a reviewer can read who controls the page without decoding chain state; TransferAuthority moves it afterwards.

The value here is the standard test1 account, so the gnodev walkthrough in the README works unedited. `make build ADMIN=g1...` rewrites it for a real deployment.

Functions 30

func Accept

crossing Action
1func Accept(cur realm, pkgPath string)
source

Accept makes the candidate at pkgPath the live theme. Authority only.

func Append

crossing Action
1func Append(cur realm, slug, body string)
source

Append adds to the end of a slot, creating it when absent. It exists for a body too large for one transaction: Set the first chunk, Append the rest.

func Authority

Action
1func Authority() string
source

Authority returns a human-readable description of who may write and upgrade.

func Delete

crossing Action
1func Delete(cur realm, slug string)
source

Delete removes a slot. Deleting the layout slot restores the theme's default layout.

func Each

Action
1func Each(fn func(slug string, s Slot) bool)
source

Each visits every slot in name order until fn returns true.

func Fallback

Action
1func Fallback(path string) string
source

Fallback is the built-in renderer. Render routes the operator views here directly, and themes delegate to it for every other path they do not draw themselves, so these views exist under any theme:

Example
1""             the assembled page: the layout slot filled from the slots
2"slots"        the slot index: name, size, revision, height of last write
3"slots/<slug>" one slot's raw markdown, fenced
4"edit"         forms that write slots (they build the gnokey command)
5"edit/<slug>"  the same, prefilled with one slot
6"system"       who may write, which theme is live, pending, history
7"manifest"     Manifest() as plain text, for scripts

func Forget

crossing Action
1func Forget(cur realm)
source

Forget drops the rollback history and the storage it holds. Authority only.

func Freeze

crossing Action
1func Freeze(cur realm)
source

Freeze ends theme upgrades permanently. Slots stay editable. Authority only, and there is no way back.

func Get

Action
1func Get(slug string) string
source

Get returns a slot body, or "" when the slot does not exist.

func Has

Action
1func Has(slug string) bool
source

Has reports whether a slot exists, empty or not.

func HistoryPaths

Action
1func HistoryPaths() []string
source

HistoryPaths returns the themes this realm has already served, oldest first, excluding the live one.

func LastHeight

Action
1func LastHeight() int64
source

LastHeight returns the block height of the most recent write, or 0.

func Layout

Action
1func Layout() string
source

Layout returns the layout slot, or "" when none has been set. Themes substitute their own default in that case.

func LivePath

Action
1func LivePath() string
source

LivePath returns the realm path of the theme currently serving, or "".

func Manifest

Action
1func Manifest() string
source

Manifest returns one tab-separated line per slot:

Example
1<slug>\t<rev>\t<bytes>\t<sha256 of body, hex>

It is the diff surface scripts/sync.sh reads: one query tells it exactly which local file is out of date, without downloading any body.

func Path

Action
1func Path() string
source

Path returns this realm's package path, e.g. "gno.land/r/g1lnkytfqcjwllws63gvf0mv9yt04aswy4y9amhm/home".

func PendingPaths

Action
1func PendingPaths() []string
source

PendingPaths returns the candidate theme paths awaiting acceptance.

func Register

crossing Action
1func Register(cur realm, t Theme)
source

Register records the calling realm's theme as a candidate. The path filed is read off the crossing frame, never taken as an argument, so a candidate cannot claim to live somewhere it does not. Only realms nested under this one are admitted; a direct user call is refused.

func Render

1func Render(path string) string
source

Render is what gnoweb calls.

The operator views (system, slots, edit, manifest) are always served here, never through the theme: a panic inside a foreign realm's code aborts the whole call and cannot be recovered from this side, so a theme that panics takes the page down until it is rolled back. These views are what the rollback is done from, and the routing keeps them out of the theme's reach. Every other path, the page itself included, goes to the live theme, or to the built-in renderer when none is accepted.

func Revision

Action
1func Revision() int
source

Revision returns the total number of writes this realm has accepted. It changes on every mutation, so a client can cheaply tell "nothing moved".

func Rollback

crossing Action
1func Rollback(cur realm)
source

Rollback restores the previous theme and returns the current one to the pending set. Authority only.

func Set

crossing Action
1func Set(cur realm, slug, body string)
source

Set creates or replaces the slot named slug. This is the ordinary update: one slot, one transaction. An empty body keeps the slot but empties it; use Delete to remove it.

func Style

Action
1func Style(key, fallback string) string
source

Style returns the style knob named key (the slot "style."+key), or fallback when it is absent or empty.

func TransferAuthority

crossing Action
1func TransferAuthority(cur realm, to address)
source

TransferAuthority hands both editing and upgrading to another address.

func Withdraw

crossing Action
1func Withdraw(cur realm, pkgPath string)
source

Withdraw drops a candidate. Authority only, except that a theme realm may always drop its own.

func NewFiller

Action
1func NewFiller() *Filler
source

NewFiller returns a Filler with every slot and every computed placeholder registered. A theme adds its own widgets with Add before calling Fill.

func Lookup

Action
1func Lookup(slug string) (Slot, bool)
source

Lookup returns a copy of a slot and whether it exists.

Types 3

type Filler

struct
1type Filler struct {
2	names []string
3	fns   map[string]func() string
4}
source

Filler substitutes :name: placeholders in a layout. It is lazy: a callback runs only when its placeholder occurs in the layout, so an unused slot is never even read. Substitution is single-pass and non-recursive, so a placeholder inside a slot body is left alone and no slot can expand into another. Names never contain ':', so no placeholder is a prefix of another and the result does not depend on registration order. A placeholder that nothing claims survives into the output verbatim: a missing section should be visible, not silently blank.

Methods on Filler

func Add

method on Filler
1func (f *Filler) Add(name string, fn func() string)
source

Add registers the callback for :name:. A later Add for the same name wins, which is how a theme widget overrides a slot of the same name.

func Fill

method on Filler
1func (f *Filler) Fill(layout string) string
source

Fill returns layout with every present placeholder replaced.

type Slot

struct
1type Slot struct {
2	Body   string
3	Rev    int   // Revision() at the time of the last write to this slot
4	Height int64 // block height of that write
5}
source

Slot is one named fragment of the page.

type Theme

interface
1type Theme interface {
2	Render(path string) string
3}
source

Theme is what a renderer realm promises. It is declared here, in the file that can never change, so every theme version agrees on one type identity.

Render receives the render path ("" is the profile page) and returns markdown. The operator views (system, slots, edit, manifest) never reach a theme; for any other path it does not draw itself, a theme should return Fallback(path). A panic here aborts the query: there is no recovering a foreign realm's panic, so a broken theme shows an error until Rollback.

Imports 7

Source Files 7