author
.uverse.addressauthor is the only address allowed to write. Deliberately a constant rather than transferable ownership: this is one person's blog, and the same address is the only one the chain lets redeploy the realm anyway, so a second owner could publish posts it could never restore after a wipe.
Value
<gnolang.StringValue>
realmPath
untyped stringrealmPath is this realm's own path, used to build the links Render emits.
Value
"gno.land/r/moul/blog"
maxSlugLen
untyped bigintmaxSlugLen bounds a slug so a permalink stays typable and a key stays cheap.
Value
(64 <untyped> bigint)
excerptLen
untyped bigintexcerptLen is how much of a post body the index shows.
Value
(200 <untyped> bigint)
introKey
untyped stringintroKey is the manifest key of the index header. It starts with '!', which validSlug rejects, so it can never collide with a post.
Value
"!intro"
introSlug
untyped stringintroSlug is refused as a post slug. Not because this realm needs it: the intro lives in its own variable. It is refused so that the local half stays representable, where a post is \<slug>.md and the header is intro.md. A post published at this slug by a hand-written transaction would have no file it could live in, and tools/gnoblog would report it as an extra forever.
Value
"intro"
post
typeValue
blog.post
posts
*v0.Tree// slug -> \*post
- OID
- 0214cf…221c:4
posts details
order
*v0.Tree// "\<date>/\<slug>" -> \*post
- OID
- 0214cf…221c:7
order details
intro
string// markdown shown above the index
Value
"# moul's blog\n\nNotes on gno.land, from someone building on it. Short, specific, mostly about\nthings I made for myself and then found out other people wanted too.\n\nNothing here is official. It is one person's working notes."
rev
int// total writes accepted, bumped by every mutation
Value
3
assertAuthor
func()- OID
- 0214cf…221c:11
assertAuthor details
validSlug
func(slug string) boolvalidSlug reports whether slug is a legal permalink: 1..maxSlugLen bytes of \[a-z0-9.\_-]. The character set excludes ':' and '/' so a slug can never break out of its own render path, and excludes uppercase so a post has exactly one URL.
- OID
- 0214cf…221c:13
validSlug details
validDate
func(date string) boolvalidDate reports whether date is exactly YYYY-MM-DD. The format is not cosmetic: \`order\` relies on lexical order being chronological order, so a date of any other shape would silently sort into the wrong place.
- OID
- 0214cf…221c:14
validDate details
orderKey
func(date string, slug string) stringorderKey is the key a post takes in \`order\`. The slug is appended so two posts published on the same day do not collide.
- OID
- 0214cf…221c:15
orderKey details
splitTags
func(tags string) []stringsplitTags normalizes a comma-separated tag list: trimmed, lowercased, deduplicated, empties dropped. It returns the canonical string that gets stored, so the hash a client computes locally matches the one on chain.
- OID
- 0214cf…221c:16
splitTags details
joinTags
func(tags []string) string- OID
- 0214cf…221c:17
joinTags details
record
func(title string, date string, tags string, body string) stringrecord is the canonical serialization a post hashes to. Both this realm and tools/gnoblog build it the same way, which is what lets one Manifest() read decide whether a local file needs a transaction at all.
- OID
- 0214cf…221c:18
record details
hashOf
func(s string) string- OID
- 0214cf…221c:19
hashOf details
Set
func(slug string, title string, date string, tags string, body string)Set creates or replaces the post at slug. This is the ordinary publish: one post, one transaction, idempotent. Changing the date moves the post in the index, so the old order entry is removed before the new one is written.
- OID
- 0214cf…221c:20
Set details
Append
func(slug string, body string)Append adds to the end of a post's body. It exists for a body too large to fit in one transaction: Set the first chunk, Append the rest. An ordinary edit uses Set, which is idempotent and therefore safe to retry.
- OID
- 0214cf…221c:21
Append details
Delete
func(slug string)Delete removes a post and its index entry.
- OID
- 0214cf…221c:22
Delete details
SetIntro
func(body string)SetIntro replaces the markdown shown above the index. Passing "" restores the built-in header.
- OID
- 0214cf…221c:23
SetIntro details
Get
func(slug string) stringGet returns a post's raw markdown body, or "" when there is no such post.
- OID
- 0214cf…221c:24
Get details
Count
func() intCount returns the number of published posts.
- OID
- 0214cf…221c:25
Count details
Revision
func() intRevision returns the total number of writes this realm has accepted. It changes on every mutation, so a client can cheaply tell "nothing moved".
- OID
- 0214cf…221c:26
Revision details
Manifest
func() stringManifest returns one tab-separated line per post, plus one for the intro: <slug>\t<rev>\t<date>\t<len of body>\t<sha256 of the canonical record> It is the diff surface tools/gnoblog reads with a single vm/qeval: the hash covers the title, date, tags and body together, so one read says exactly which local file needs a transaction without downloading a single body. The intro is reported under the key "!intro" with an empty date. '!' is not a legal slug character, so that row can never be confused with a post.
- OID
- 0214cf…221c:27
Manifest details
linkPrefix
untyped stringlinkPrefix is what a permalink starts with. gnoweb addresses a realm's render path with ':' after the package path, so this is realmPath with the leading "gno.land" dropped and the separator appended.
Value
"/r/moul/blog:"
defaultIntro
untyped stringdefaultIntro is the header shown before SetIntro has ever been called, i.e. right after the first deploy or after a redeploy wiped the state.
Value
"# moul's blog\n\nNotes on gno.land, from the person building on it.\n"
Render
func(path string) stringRender serves three views: "" the index, newest first "<slug>" one post "t/<tag>" every post carrying a tag
- OID
- 0214cf…221c:28
Render details
header
func() string- OID
- 0214cf…221c:30
header details
renderIndex
func() string- OID
- 0214cf…221c:31
renderIndex details
renderTag
func(tag string) string- OID
- 0214cf…221c:32
renderTag details
renderPost
func(slug string) string- OID
- 0214cf…221c:33
renderPost details
entry
func(p *blog.post) stringentry is one row of a listing: linked title, byline, excerpt.
- OID
- 0214cf…221c:34
entry details
byline
func(p *blog.post) stringbyline is the date plus the post's tags as links, on one line.
- OID
- 0214cf…221c:35
byline details
hasTag
func(p *blog.post, tag string) bool- OID
- 0214cf…221c:36
hasTag details
firstLine
func(body string) stringfirstLine returns the first non-empty, non-heading line of a body, which is what an excerpt should show: a post that opens with "## Something" would otherwise preview its own heading.
- OID
- 0214cf…221c:37