Tokens are placeholders you type into text, written as {name}. Muninn fills each one from the photo, the album, the campaign or you, so one template can caption a thousand photos and each caption reads as if it were written for that frame.
| Place | How to get there | Notes |
|---|---|---|
| Caption templates | Settings, Social, Caption templates | Reusable shapes for Share to social and the composer. Click Tokens for the list and a live preview against one of your photos. |
| Drip campaigns | The Caption template field in the campaign editor | Album, folder and loose-photo campaigns alike. The preview under the field shows the first post rendered. For folder campaigns, {caption} is the manifest's own caption for that post, so a template of {caption} keeps every caption and signs it. |
| Photo comments | The Comment field in the photo inspector | Rendered on the web album, in the slideshow and on the detail overlay. The inspector shows the rendered line with the template in small type beneath it. |
Anywhere {comment} lands | A template that carries {comment} | The comment is inserted as written, then the whole caption is rendered, so tokens inside a comment work inside a template too. |
{name}: the token by itself. Names are camelCase and case sensitive: {cameraModel}, not {cameramodel}.{name:argument}: a token with an argument after a colon. {number:03}, {date:MMM d}, {mention:Harbor and Pine}, {random:Morning.|Evening.}.{location} as nothing at all.{people} or {comment} on its own disappears when the token is empty, so a template can carry optional lines without leaving blanks. A line with its own words stays: Shot on {cameraModel} keeps "Shot on" even without a camera, which is your cue to fix the template or the metadata. Doubled spaces and runs of blank lines are tidied.{camera} is not a token, so it renders as {camera} and the typo shows in the preview instead of vanishing.{handle}, {platform} and {mention:} differ by destination, so a post that uses them carries one shared caption plus a copy per platform, filled in automatically. Nothing to set up.| Token | Gives | Example | Notes |
|---|---|---|---|
{number} | The photo's number in the album, assigned once and never reused | From the Vault #12 | Shuffle-proof. Numbers are handed out in the album's order the first time they are needed (custom order first), and a photo keeps its number through re-saves, reorders and shuffles. A photo removed from the album retires its number; a photo added later gets the next one. {number:03} pads to 012. |
{index} | The photo's position in the album's order when the campaign was saved | 7 | Changes if the order changes. {index:03} pads. |
{count} | How many photos the album has | 48 | |
{slot} | The post's position in the campaign's schedule | 3 | Posts only. {slot:02} pads. |
{total} | How many posts the campaign has | 24 | Posts only. |
| Token | Gives | Example | Notes |
|---|---|---|---|
{caption} | The caption from a folder manifest | Folder campaigns only; empty elsewhere. | |
{comment} | The photo's Comment from the inspector | Such a cozy place for a night cap | A comment can itself carry tokens. |
{fileName} | The file name without its extension | DSCF0412 | |
{shoot} | The Shoot tag | Leavenworth Winter | The frame's own shoot name first, else the folder it came from. |
{people} | The named people detected in the frame | Ada and Grace | As a list: "Ada", "Ada and Grace", "Ada, Grace and Lin". Only people you have named in People. |
{tags} | The photo's content tags | snow, cabin, dusk | Comma separated. |
{hashtags} | The content tags as hashtags | #snow #cabin #dusk | Lowercased, punctuation stripped. |
{location} | The place name | Posthotel, Leavenworth, Washington, United States | From GPS or the location you assigned. |
{city} | The city part of the place name | Leavenworth | Taken from the comma-separated place name (third part from the end), so it depends on how the place was named. |
{country} | The country part of the place name | United States | The last part of the place name. |
| Token | Gives | Example |
|---|---|---|
{cameraModel} | Camera model from EXIF | X-T5 |
{cameraMake} | Camera make from EXIF | FUJIFILM |
{lens} | Lens model from EXIF | XF23mmF1.4 R LM WR |
{focalLength} | Focal length, as shot | 23mm |
{aperture} | Aperture | f/8 or f/1.4 |
{shutter} | Shutter speed | 1/250 |
{iso} | Sensitivity | ISO 400 |
{filmSimulation} | The film simulation the frame was shot with | Classic Chrome |
{recipe} | The recipe the frame was shot with | Kodachrome 64, or the film simulation when the frame carries no recipe |
{whiteBalance} | White balance, as the camera recorded it | Daylight |
{exposureComp} | Exposure compensation | +0.7, -1, 0 |
Folder campaigns read these from each file's own EXIF; the photo does not have to be in your library.
These come from the record a frame carries when it has been through Huginn and Valkyrie: which shoot, which shot, which light, which recipe. Muninn reads it at import (and once, for the photos already in your library). A frame that never went through them has none of these, and the tokens simply vanish.
| Token | Gives | Example | Notes |
|---|---|---|---|
{shot} | The planned shot the frame was taken for | Boats at rest | |
{set} | The set within the shoot | Pier | |
{lightWindow} | The light the frame was shot in | Morning golden hour | One of: Morning blue hour, Morning golden hour, Daylight, Evening golden hour, Evening blue hour, Dark. |
{place} | The place the shoot was planned at, by name | Harbor and Pine | The plan's name for the place. {location} is the map's name from GPS; they can differ. |
{mood} | The mood the shoot was planned with | quiet | |
{creator} | Who published the recipe the frame was shot with | Elin Marsh | The name a recipe was published under in Huginn. When the frame does not carry it, Muninn asks Huginn once by the recipe's identity. |
{creatorHandle} | The recipe creator's handle | @elinmarsh | Same source. |
{recipeCode} | The recipe's share code | HGN3-… | A reader can type it into Huginn to install the look. Absent for a sealed recipe. |
{palette} | The palette the recipe belongs to | Autumn | |
{cameraSlot} | The custom slot the frame was shot on | C3 | |
{creatorUrl} | A link to the recipe creator's page in Huginn | https://huginnfilm.app/c/theforge | |
{recipeUrl} | A link to the recipe's own page | https://huginnfilm.app/r/kodachrome-64 | Where a reader can install the look. |
{shoot} (under The photo) and {recipe} (under The camera) read the same record first.
A name cannot carry a link. A token becomes plain text, and no social platform lets the words you see differ from the address they point at. So {creator} writes the name and {creatorUrl} writes the address, and a caption that wants both says so: "Recipe by {creator}" on one line, {recipeUrl} on the next. Two places do render a real link, and neither needs a token for it: the photo inspector, where the recipe and its creator are clickable, and your published gallery, where the photo info panel credits the look and links it into Huginn.
| Token | Gives | Example | Notes |
|---|---|---|---|
{date} | Capture date | March 12, 2026 | {date:FORMAT} for a format of your own; see the format table. |
{year} | Capture year | 2026 | |
{monthName} | Capture month | March | |
{day} | Capture day of the month | 12 | |
{weekday} | Capture weekday | Thursday | |
{time} | Capture time | 6:42 PM | |
{season} | The season | winter | By the capture month, flipped for the southern hemisphere when the photo has GPS. |
{ago} | How long ago it was shot, against the day the post goes out | 3 years ago today | "today", "yesterday", "5 days ago", "2 months ago", "3 years ago", and "3 years ago today" when the post lands on the anniversary. In a comment or a preview, "today" means now. |
{postDate} | The day the post goes out | March 12, 2026 | {postDate:EEEE} gives the weekday. In a comment, the day it is rendered. |
Date formats use the standard pattern letters:
| Pattern | Renders | Pattern | Renders |
|---|---|---|---|
yyyy | 2026 | EEEE | Thursday |
yy | 26 | EEE | Thu |
MMMM | March | h:mm a | 6:42 PM |
MMM | Mar | HH:mm | 18:42 |
MM | 03 | d | 12 |
M | 3 | dd | 12 |
Text inside single quotes is kept as is: {date:'Shot' MMM d, yyyy} renders "Shot Mar 12, 2026".
| Token | Gives | Example | Notes |
|---|---|---|---|
{albumName} | The album's name | Leavenworth Winter | |
{albumDescription} | The album's description | ||
{albumUrl} | The album's published gallery link | https://photos.example.com/leavenworth-winter | On your own domain when you have one; empty until the album is published. |
{displayName} | Your publisher name | Elin Marsh | The identity the post or album belongs to. |
{signature} | Your signature line | Shot on Fuji. Sent from Muninn. | Set at Settings, Social, Signature. One per identity. Multi-line is fine. |
{handle} | Your handle | @northlightstudio | On a post: your handle on the platform the post goes to. In a comment or where there is no platform: your suite handle, the @name on your gallery address. |
{platform} | The platform the post goes to | Instagram | Posts only. |
| Token | Gives | Example | Notes |
|---|---|---|---|
{mention:Name} | A Directory contact's handle on the platform the post goes to | @harborandpine | Matches the contact by name. Where the contact has no handle for that platform, their display name is written instead. An unknown name stays as typed. |
{random:a|b|c} | One of the options | Morning. | Chosen per photo and kept on re-save, so a long campaign does not open every caption the same way, and editing the campaign does not reshuffle it. Change the options and the picks change. |
A comment is rendered wherever it is shown: the published web album, the slideshow's caption layer and the detail view's overlay. The Comment field keeps what you typed, so you can always edit the template; the inspector shows the rendered line and, when they differ, the template beneath it.
In a comment there is no post, so {slot}, {total}, {platform} and {mention:} are empty, {index} and {count} are filled in only at publish, {postDate} and {ago} count from the day the comment is rendered, and {handle} is your suite handle. {number} counts within the album the photo is published in; on the detail view and in the slideshow it uses the first album that holds the photo.
A vault series on shuffle. Template: From the Vault #{number}. Every photo keeps its number no matter how the campaign is shuffled or re-saved; photos with a comment get their line, the rest do not; the signature closes every post.\n\n{comment}\n\n{signature}
A spec line. {cameraModel} · {lens} · {focalLength} · {aperture} · {shutter} · {iso} renders X-T5 · XF23mmF1.4 R LM WR · 23mm · f/1.4 · 1/250 · ISO 400. On a frame missing the lens, that field simply drops out.
An anniversary. {location}, {ago}. renders "Posthotel, Leavenworth, Washington, United States, 3 years ago today." on the day, and "3 years ago" on any other day.
A per-platform greeting. {random:Good morning|Hello|Hi}, {platform}. {comment} gives each platform its own copy, and the greeting is fixed per photo so an edit does not reshuffle it.
A comment that signs itself. In the inspector's Comment field: {filmSimulation}, {season} {year}. {handle} renders "Classic Chrome, winter 2026. @elinmarsh" on the web album and in the slideshow.
{number} does not match the photo's position. By design. Numbers are permanent; {index} follows the current order.{handle} is my suite handle, not my Instagram. Handles resolve per platform only on a post going to that platform. In a comment there is no platform.