[{"data":1,"prerenderedAt":704},["ShallowReactive",2],{"navigation_docs":3,"-getting-started-introduction":191,"-getting-started-introduction-surround":701},[4,31,67,103,129,155,175],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":30},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20,25],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick start","\u002Fgetting-started\u002Fquick-start","1.getting-started\u002F3.quick-start","i-lucide-play",{"title":26,"path":27,"stem":28,"icon":29},"Agent Skill","\u002Fgetting-started\u002Fagent-skill","1.getting-started\u002F4.agent-skill","i-lucide-sparkles",false,{"title":32,"icon":33,"path":34,"stem":35,"children":36,"page":30},"Authoring","i-lucide-pen-line","\u002Fauthoring","2.authoring",[37,42,47,52,57,62],{"title":38,"path":39,"stem":40,"icon":41},"Comark syntax","\u002Fauthoring\u002Fcomark-syntax","2.authoring\u002F1.comark-syntax","i-lucide-file-code",{"title":43,"path":44,"stem":45,"icon":46},"Frontmatter","\u002Fauthoring\u002Ffrontmatter","2.authoring\u002F2.frontmatter","i-lucide-heading",{"title":48,"path":49,"stem":50,"icon":51},"Modules","\u002Fauthoring\u002Fmodules","2.authoring\u002F3.modules","i-lucide-blocks",{"title":53,"path":54,"stem":55,"icon":56},"Merge tags and bindings","\u002Fauthoring\u002Fmerge-tags-and-bindings","2.authoring\u002F4.merge-tags-and-bindings","i-lucide-braces",{"title":58,"path":59,"stem":60,"icon":61},"Actions and spans","\u002Fauthoring\u002Factions-and-spans","2.authoring\u002F5.actions-and-spans","i-lucide-mouse-pointer-click",{"title":63,"path":64,"stem":65,"icon":66},"Compile errors","\u002Fauthoring\u002Fcompile-errors","2.authoring\u002F6.compile-errors","i-lucide-circle-alert",{"title":68,"icon":69,"path":70,"stem":71,"children":72,"page":30},"Rendering","i-lucide-layout-template","\u002Frendering","3.rendering",[73,78,83,88,93,98],{"title":74,"path":75,"stem":76,"icon":77},"Families and streams","\u002Frendering\u002Ffamilies-and-streams","3.rendering\u002F1.families-and-streams","i-lucide-users",{"title":79,"path":80,"stem":81,"icon":82},"Themes","\u002Frendering\u002Fthemes","3.rendering\u002F2.themes","i-lucide-palette",{"title":84,"path":85,"stem":86,"icon":87},"Config and the renderer","\u002Frendering\u002Fconfig-and-renderer","3.rendering\u002F3.config-and-renderer","i-lucide-settings",{"title":89,"path":90,"stem":91,"icon":92},"Layout and spacing","\u002Frendering\u002Flayout-and-spacing","3.rendering\u002F4.layout-and-spacing","i-lucide-ruler",{"title":94,"path":95,"stem":96,"icon":97},"HTML output","\u002Frendering\u002Fhtml-output","3.rendering\u002F5.html-output","i-lucide-code-xml",{"title":99,"path":100,"stem":101,"icon":102},"Plain text","\u002Frendering\u002Fplain-text","3.rendering\u002F6.plain-text","i-lucide-file-text",{"title":104,"icon":105,"path":106,"stem":107,"children":108,"page":30},"Sending","i-lucide-send","\u002Fsending","4.sending",[109,114,119,124],{"title":110,"path":111,"stem":112,"icon":113},"Message and MIME","\u002Fsending\u002Fmessage-and-mime","4.sending\u002F1.message-and-mime","i-lucide-mail",{"title":115,"path":116,"stem":117,"icon":118},"Router and streams","\u002Fsending\u002Frouter-and-streams","4.sending\u002F2.router-and-streams","i-lucide-route",{"title":120,"path":121,"stem":122,"icon":123},"SMTP","\u002Fsending\u002Fsmtp","4.sending\u002F3.smtp","i-lucide-server",{"title":125,"path":126,"stem":127,"icon":128},"Maps","\u002Fsending\u002Fmaps","4.sending\u002F4.maps","i-lucide-map",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":30},"Tooling","i-lucide-wrench","\u002Ftooling","5.tooling",[135,140,145,150],{"title":136,"path":137,"stem":138,"icon":139},"The lttr CLI","\u002Ftooling\u002Fcli","5.tooling\u002F1.cli","i-lucide-terminal",{"title":141,"path":142,"stem":143,"icon":144},"Live preview","\u002Ftooling\u002Flive-preview","5.tooling\u002F2.live-preview","i-lucide-eye",{"title":146,"path":147,"stem":148,"icon":149},"Screenshots","\u002Ftooling\u002Fscreenshots","5.tooling\u002F3.screenshots","i-lucide-camera",{"title":151,"path":152,"stem":153,"icon":154},"Goldens and testing","\u002Ftooling\u002Fgoldens-and-testing","5.tooling\u002F4.goldens-and-testing","i-lucide-flask-conical",{"title":156,"icon":157,"path":158,"stem":159,"children":160,"page":30},"Guides","i-lucide-book-open","\u002Fguides","6.guides",[161,166,170],{"title":162,"path":163,"stem":164,"icon":165},"The Quiet example","\u002Fguides\u002Fthe-quiet-example","6.guides\u002F1.the-quiet-example","i-lucide-mail-open",{"title":167,"path":168,"stem":169,"icon":82},"Your own family and theme","\u002Fguides\u002Fyour-own-family-and-theme","6.guides\u002F2.your-own-family-and-theme",{"title":171,"path":172,"stem":173,"icon":174},"Releasing","\u002Fguides\u002Freleasing","6.guides\u002F3.releasing","i-lucide-tag",{"title":176,"icon":177,"path":178,"stem":179,"children":180,"page":30},"Reference","i-lucide-library","\u002Freference","7.reference",[181,186],{"title":182,"path":183,"stem":184,"icon":185},"API reference","\u002Freference\u002Fapi-reference","7.reference\u002F1.api-reference","i-lucide-list-tree",{"title":187,"path":188,"stem":189,"icon":190},"Gallery","\u002Freference\u002Fgallery","7.reference\u002F2.gallery","i-lucide-images",{"id":192,"title":11,"body":193,"description":694,"extension":695,"links":696,"meta":697,"navigation":698,"path":12,"seo":699,"stem":13,"__hash__":700},"docs\u002F1.getting-started\u002F1.introduction.md",{"type":194,"value":195,"toc":687},"minimark",[196,233,240,245,378,381,445,453,457,460,583,600,604,645,649,656,660,683],[197,198,199,200,207,208,212,213,216,217,220,221,224,225,228,229,232],"p",{},"lttr is a Go library for email templates. Authors write each email in ",[201,202,206],"a",{"href":203,"rel":204},"https:\u002F\u002Fcomark.dev",[205],"nofollow","Comark",": Markdown plus components such as ",[209,210,211],"code",{},"::statement",", ",[209,214,215],{},"::receipt"," and ",[209,218,219],{},":button",". You give the template a Go data type. ",[209,222,223],{},"lttr.Compile"," checks the template against that type once, at startup, and ",[209,226,227],{},"Render"," fills in the data and returns a ",[209,230,231],{},"*lttr.Message"," with Outlook-safe HTML, a plain-text part and an envelope, ready to send as MIME.",[197,234,235,236,239],{},"The library is brand-neutral. It holds no colours, fonts, logo, senders or footer copy of its own; you supply them as a ",[209,237,238],{},"Theme"," and a set of families. The only English it writes is a handful of generic defaults, such as the sign-off \"Thanks,\" and the tile link \"Read\".",[241,242,244],"h2",{"id":243},"follow-a-template-through-lttr","Follow a template through lttr",[246,247,253],"pre",{"className":248,"code":249,"filename":250,"language":251,"meta":252,"style":252},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","var orderShipped = lttr.MustCompile[OrderShipped](families, \"order.shipped\", src)\n\nmsg, err := orderShipped.Render(renderer, recipient, OrderShipped{OrderID: \"A-1042\"})\n","main.go","go","",[209,254,255,315,322],{"__ignoreMap":252},[256,257,260,264,268,271,274,277,281,284,288,291,294,297,300,304,307,309,312],"span",{"class":258,"line":259},"line",1,[256,261,263],{"class":262},"sMK4o","var",[256,265,267],{"class":266},"sTEyZ"," orderShipped ",[256,269,270],{"class":262},"=",[256,272,273],{"class":266}," lttr",[256,275,276],{"class":262},".",[256,278,280],{"class":279},"s2Zo4","MustCompile",[256,282,283],{"class":262},"[",[256,285,287],{"class":286},"sBMFI","OrderShipped",[256,289,290],{"class":262},"](",[256,292,293],{"class":266},"families",[256,295,296],{"class":262},",",[256,298,299],{"class":262}," \"",[256,301,303],{"class":302},"sfazB","order.shipped",[256,305,306],{"class":262},"\"",[256,308,296],{"class":262},[256,310,311],{"class":266}," src",[256,313,314],{"class":262},")\n",[256,316,318],{"class":258,"line":317},2,[256,319,321],{"emptyLinePlaceholder":320},true,"\n",[256,323,325,328,330,333,336,339,341,343,346,349,351,354,356,359,362,365,368,370,373,375],{"class":258,"line":324},3,[256,326,327],{"class":266},"msg",[256,329,296],{"class":262},[256,331,332],{"class":266}," err ",[256,334,335],{"class":262},":=",[256,337,338],{"class":266}," orderShipped",[256,340,276],{"class":262},[256,342,227],{"class":279},[256,344,345],{"class":262},"(",[256,347,348],{"class":266},"renderer",[256,350,296],{"class":262},[256,352,353],{"class":266}," recipient",[256,355,296],{"class":262},[256,357,358],{"class":286}," OrderShipped",[256,360,361],{"class":262},"{",[256,363,364],{"class":266},"OrderID",[256,366,367],{"class":262},":",[256,369,299],{"class":262},[256,371,372],{"class":302},"A-1042",[256,374,306],{"class":262},[256,376,377],{"class":262},"})\n",[197,379,380],{},"Three things meet in these two lines:",[382,383,384,400,414],"ul",{},[385,386,387,391,392,395,396,399],"li",{},[388,389,390],"strong",{},"The template"," is Markdown with YAML frontmatter. The frontmatter names the template and its family and holds the subject and preheader. The body is a stack of modules, and loose Markdown becomes a letter module. Merge tags (",[209,393,394],{},"{{order_id}}",") and bindings (",[209,397,398],{},":order=\"order\"",") refer to fields of your type.",[385,401,402,405,406,409,410,413],{},[388,403,404],{},"The family"," is a kind of email you send, such as order updates or password resets. It fixes the sender, the sending stream, the header and footer, the footer copy, the modules its templates may not use and whether opens and clicks may be tracked. You collect families in a ",[209,407,408],{},"Registry",", and ",[209,411,412],{},"Compile"," applies their rules.",[385,415,416,419,420,212,423,212,426,212,429,432,433,436,437,440,441,444],{},[388,417,418],{},"The stream"," is how the family's mail is sent: ",[209,421,422],{},"Transactional",[209,424,425],{},"Security",[209,427,428],{},"Marketing",[209,430,431],{},"Outreach"," or ",[209,434,435],{},"Internal",". A ",[209,438,439],{},"Router"," sends each stream through its own ",[209,442,443],{},"Sender",", so marketing mail and password resets can go out through different senders and keep separate reputations.",[197,446,447,449,450,452],{},[209,448,412],{}," does everything that does not depend on data, and ",[209,451,227],{}," does the rest. A misspelt merge tag, an unknown module attribute or a module the family forbids is a compile error. A merge tag with no value and no fallback, an invalid URL or an empty subject is a render error. Render never returns a partial message.",[241,454,456],{"id":455},"see-the-pipeline","See the pipeline",[197,458,459],{},"Each stage is its own package, and each one builds on the stages before it:",[461,462,463,482],"table",{},[464,465,466],"thead",{},[467,468,469,473,476,479],"tr",{},[470,471,472],"th",{},"Stage",[470,474,475],{},"Package",[470,477,478],{},"When",[470,480,481],{},"What it does",[483,484,485,503,520,537,557],"tbody",{},[467,486,487,491,496,500],{},[488,489,490],"td",{},"Parse",[488,492,493],{},[209,494,495],{},"comark",[488,497,498],{},[209,499,412],{},[488,501,502],{},"Reads the Markdown, components, attributes and merge tags into an AST with line and column positions.",[467,504,505,508,513,517],{},[488,506,507],{},"Check",[488,509,510],{},[209,511,512],{},"ir",[488,514,515],{},[209,516,412],{},[488,518,519],{},"Turns the AST into typed modules, applies the module rules, and resolves every merge tag and binding against your type.",[467,521,522,525,530,534],{},[488,523,524],{},"Arrange",[488,526,527],{},[209,528,529],{},"layout",[488,531,532],{},[209,533,227],{},[488,535,536],{},"Adds the family's header and footer and sets the spacing between modules.",[467,538,539,542,550,554],{},[488,540,541],{},"Draw",[488,543,544,212,547],{},[209,545,546],{},"render\u002Fhtml",[209,548,549],{},"render\u002Ftext",[488,551,552],{},[209,553,227],{},[488,555,556],{},"Writes the table-based HTML and the plain-text part from the same arranged document.",[467,558,559,561,566,573],{},[488,560,475],{},[488,562,563],{},[209,564,565],{},"lttr",[488,567,568,212,570],{},[209,569,227],{},[209,571,572],{},"MIME",[488,574,575,576,579,580,276],{},"Builds the ",[209,577,578],{},"Message"," with its envelope and headers, and serialises it as ",[209,581,582],{},"multipart\u002Falternative",[197,584,585,588,589,592,593,212,596,599],{},[209,586,587],{},"theme"," (palettes, fonts, the brand mark) and ",[209,590,591],{},"data"," (",[209,594,595],{},"Money",[209,597,598],{},"Receipt"," and the other typed values) sit beside the pipeline, and every stage may use them.",[241,601,603],{"id":602},"know-what-lttr-does-not-do","Know what lttr does not do",[382,605,606,619,629,639],{},[385,607,608,611,612,615,616,618],{},[388,609,610],{},"No provider SDKs."," lttr sends over SMTP, or gives you the raw MIME bytes with ",[209,613,614],{},"Message.MIME",". SES, Postmark or anything else is a ",[209,617,443],{}," you write, or an SMTP relay you point at.",[385,620,621,624,625,628],{},[388,622,623],{},"No web fonts."," Your theme names three CSS font stacks (serif, sans, mono). lttr writes no ",[209,626,627],{},"@font-face"," rule or font link, so the stacks should name fonts the recipient already has.",[385,630,631,634,635,638],{},[388,632,633],{},"No visual editor."," Templates are text files in your repository, reviewed and ",[201,636,637],{"href":152},"tested"," like code.",[385,640,641,644],{},[388,642,643],{},"No layout control in templates."," Templates choose modules. The layout decides the spacing, the family decides the header and footer, and colours come from the theme, so a template never sets a margin.",[241,646,648],{"id":647},"learn-where-it-came-from","Learn where it came from",[197,650,651,652,655],{},"lttr was built at SULV for CaribHubs, its first consumer; ",[201,653,654],{"href":163},"the Quiet example"," is the design it was built to reproduce.",[241,657,659],{"id":658},"go-further","Go further",[661,662,663,667,670,673,676,679],"card-group",{},[664,665,666],"card",{"icon":19,"title":16,"to":17},"Add the module and the CLI.",[664,668,669],{"icon":24,"title":21,"to":22},"One file: a type, a template, a family, a render and a send.",[664,671,672],{"icon":41,"title":38,"to":39},"Components, spans, attributes and merge tags.",[664,674,675],{"icon":51,"title":48,"to":49},"The catalogue of modules a template can use.",[664,677,678],{"icon":77,"title":74,"to":75},"Senders, streams, chrome and footer copy.",[664,680,682],{"icon":29,"title":681,"to":27},"Agent skill","Teach your coding agent to write lttr templates.",[684,685,686],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":252,"searchDepth":317,"depth":317,"links":688},[689,690,691,692,693],{"id":243,"depth":317,"text":244},{"id":455,"depth":317,"text":456},{"id":602,"depth":317,"text":603},{"id":647,"depth":317,"text":648},{"id":658,"depth":317,"text":659},"What lttr is, how a template becomes a message, and what the library leaves to you.","md",null,{},{"icon":14},{"title":11,"description":694},"tQzxbnX7ztyfb-E-LEPoy0gmjkCQrWpVLo0BbmOvyZs",[696,702],{"title":16,"path":17,"stem":18,"description":703,"icon":19,"children":-1},"Add lttr to a Go module, set up access to the private repository, and install the CLI.",1790309825446]