[{"data":1,"prerenderedAt":903},["ShallowReactive",2],{"mdc-o8y00b-key":3,"\u002Fblog\u002Fseo-in-kirby":45},{"data":4,"body":5},{},{"type":6,"children":7},"root",[8],{"type":9,"tag":10,"props":11,"children":12},"element","p",{},[13,16,25,27,34,36,43],{"type":14,"value":15},"text","Kirby Tools is built on ",{"type":9,"tag":17,"props":18,"children":22},"a",{"href":19,"rel":20},"https:\u002F\u002Fgetkirby.com",[21],"nofollow",[23],{"type":14,"value":24},"Kirby",{"type":14,"value":26}," – with gratitude to the team and community who make it. Help me improve the plugins: share feedback in ",{"type":9,"tag":17,"props":28,"children":31},{"href":29,"rel":30},"https:\u002F\u002Fgithub.com\u002Fkirby-tools\u002Fcommunity\u002Fdiscussions",[21],[32],{"type":14,"value":33},"Discussions",{"type":14,"value":35}," or report bugs via ",{"type":9,"tag":17,"props":37,"children":40},{"href":38,"rel":39},"https:\u002F\u002Fgithub.com\u002Fkirby-tools\u002Fcommunity\u002Fissues",[21],[41],{"type":14,"value":42},"Issues",{"type":14,"value":44},".",{"id":46,"title":47,"body":48,"date":894,"description":761,"extension":895,"image":896,"meta":897,"navigation":898,"path":899,"product":896,"seo":900,"stem":901,"__hash__":902},"posts\u002Fblog\u002Fseo-in-kirby.md","SEO in Kirby CMS: A Practical Guide",{"type":49,"value":50,"toc":886},"minimark",[51,59,62,67,78,248,252,255,316,319,326,391,413,417,427,623,629,640,646,705,712,715,725,729,752,766,769,773,781,795,808,840,855,859,871,882],[10,52,53,54,58],{},"If you're setting up SEO on a Kirby site, there's no settings page to start from. Kirby fills in no title tag, writes no sitemap, and adds no hreflang. A page's ",[55,56,57],"code",{},"\u003Chead>"," holds whatever your template puts there, and nothing else.",[10,60,61],{},"I like that: nothing ends up in the head by accident. But it makes SEO on a Kirby site two jobs – template code you write once, and the titles and descriptions editors type in the Panel for every page. My plugins help with the second.",[63,64,66],"h2",{"id":65},"write-the-meta-tags-in-one-head-snippet","Write the Meta Tags in One Head Snippet",[10,68,69,70,73,74,77],{},"I'd keep the head in one snippet that every template includes. It reads the ",[55,71,72],{},"metaTitle"," and ",[55,75,76],{},"metaDescription"," fields from your blueprints. Where an editor leaves them empty, it falls back to the page title followed by the site title, and to the site's meta description. The canonical URL points at the page itself:",[79,80,86],"pre",{"className":81,"code":82,"filename":83,"language":84,"meta":85,"style":85},"language-php shiki shiki-themes github-light github-light github-dark","\u003Ctitle>\u003C?= $page->metaTitle()->or($page->title() . ' – ' . $site->title())->esc() ?>\u003C\u002Ftitle>\n\u003Cmeta name=\"description\" content=\"\u003C?= $page->metaDescription()->or($site->metaDescription())->esc('attr') ?>\">\n\u003Clink rel=\"canonical\" href=\"\u003C?= $page->url() ?>\">\n","site\u002Fsnippets\u002Fhead.php","php","",[55,87,88,166,213],{"__ignoreMap":85},[89,90,93,97,101,104,108,111,114,117,119,122,125,127,129,132,134,138,141,144,146,148,151,153,156,158,161,163],"span",{"class":91,"line":92},"line",1,[89,94,96],{"class":95},"s8jYJ","\u003C",[89,98,100],{"class":99},"sBjJW","title",[89,102,103],{"class":95},">\u003C?=",[89,105,107],{"class":106},"sxrX7"," $page",[89,109,110],{"class":95},"->",[89,112,72],{"class":113},"snPdu",[89,115,116],{"class":106},"()",[89,118,110],{"class":95},[89,120,121],{"class":113},"or",[89,123,124],{"class":106},"($page",[89,126,110],{"class":95},[89,128,100],{"class":113},[89,130,131],{"class":106},"() ",[89,133,44],{"class":95},[89,135,137],{"class":136},"sIIMD"," ' – '",[89,139,140],{"class":95}," .",[89,142,143],{"class":106}," $site",[89,145,110],{"class":95},[89,147,100],{"class":113},[89,149,150],{"class":106},"())",[89,152,110],{"class":95},[89,154,155],{"class":113},"esc",[89,157,131],{"class":106},[89,159,160],{"class":95},"?>\u003C\u002F",[89,162,100],{"class":99},[89,164,165],{"class":95},">\n",[89,167,169,171,174,177,180,183,186,188,191,194,196,198,201,204,206,208,211],{"class":91,"line":168},2,[89,170,96],{"class":95},[89,172,173],{"class":99},"meta",[89,175,176],{"class":99}," name",[89,178,179],{"class":95},"=",[89,181,182],{"class":136},"\"description\"",[89,184,185],{"class":99}," content",[89,187,179],{"class":95},[89,189,190],{"class":136},"\"\u003C?= ",[89,192,193],{"class":106},"$page",[89,195,110],{"class":95},[89,197,76],{"class":106},[89,199,200],{"class":136},"()->or(",[89,202,203],{"class":106},"$site",[89,205,110],{"class":95},[89,207,76],{"class":106},[89,209,210],{"class":136},"())->esc('attr') ?>\"",[89,212,165],{"class":95},[89,214,216,218,221,224,226,229,232,234,236,238,240,243,246],{"class":91,"line":215},3,[89,217,96],{"class":95},[89,219,220],{"class":99},"link",[89,222,223],{"class":99}," rel",[89,225,179],{"class":95},[89,227,228],{"class":136},"\"canonical\"",[89,230,231],{"class":99}," href",[89,233,179],{"class":95},[89,235,190],{"class":136},[89,237,193],{"class":106},[89,239,110],{"class":95},[89,241,242],{"class":106},"url",[89,244,245],{"class":136},"() ?>\"",[89,247,165],{"class":95},[63,249,251],{"id":250},"decide-which-urls-get-indexed","Decide Which URLs Get Indexed",[10,253,254],{},"Kirby answers more URLs than your navigation links to. These are the four I'd check before a launch:",[256,257,258,281,297,310],"ul",{},[259,260,261,265,266,269,270,273,274,277,278,44],"li",{},[262,263,264],"strong",{},"The home page."," On a single-language site, ",[55,267,268],{},"\u002Fhome"," redirects to ",[55,271,272],{},"\u002F",". On a multi-language site, ",[55,275,276],{},"\u002Fen\u002Fhome"," renders the same page as ",[55,279,280],{},"\u002Fen",[259,282,283,286,287,290,291,293,294,296],{},[262,284,285],{},"The language prefix."," Every language, the default one included, gets its code as a URL prefix (",[55,288,289],{},"\u002Fen\u002Fabout","), unless you set a different ",[55,292,242],{}," in that language's config file. ",[55,295,272],{}," and paths without a prefix redirect to the prefixed URL, with a temporary 302.",[259,298,299,302,303,73,306,309],{},[262,300,301],{},"Translated slugs."," If a page has a German slug, the English one still works under the German prefix: ",[55,304,305],{},"\u002Fde\u002Fabout",[55,307,308],{},"\u002Fde\u002Fueber-uns"," render the same page.",[259,311,312,315],{},[262,313,314],{},"Unlisted pages."," Unlisted pages are only left out of listings like your menu. Anyone with the URL can open them; only drafts stay private.",[10,317,318],{},"You don't have to block the duplicates: where Kirby renders a page under a second URL, the canonical tag from the head snippet names its main URL, so search engines know which one to index.",[10,320,321,322,325],{},"The canonical tag doesn't hide unlisted pages, and Kirby adds ",[55,323,324],{},"noindex"," only to the Panel, never to your pages. If your unlisted pages shouldn't show up in search, I'd add one to the head snippet:",[79,327,329],{"className":81,"code":328,"filename":83,"language":84,"meta":85,"style":85},"\u003C?php if ($page->isUnlisted()): ?>\n  \u003Cmeta name=\"robots\" content=\"noindex\">\n\u003C?php endif ?>\n",[55,330,331,357,380],{"__ignoreMap":85},[89,332,333,336,338,341,344,346,349,351,354],{"class":91,"line":92},[89,334,335],{"class":95},"\u003C?",[89,337,84],{"class":99},[89,339,340],{"class":95}," if",[89,342,343],{"class":106}," ($page",[89,345,110],{"class":95},[89,347,348],{"class":113},"isUnlisted",[89,350,150],{"class":106},[89,352,353],{"class":95},":",[89,355,356],{"class":95}," ?>\n",[89,358,359,362,364,366,368,371,373,375,378],{"class":91,"line":168},[89,360,361],{"class":95},"  \u003C",[89,363,173],{"class":99},[89,365,176],{"class":99},[89,367,179],{"class":95},[89,369,370],{"class":136},"\"robots\"",[89,372,185],{"class":99},[89,374,179],{"class":95},[89,376,377],{"class":136},"\"noindex\"",[89,379,165],{"class":95},[89,381,382,384,386,389],{"class":91,"line":215},[89,383,335],{"class":95},[89,385,84],{"class":99},[89,387,388],{"class":95}," endif",[89,390,356],{"class":95},[10,392,393,394,399,400,403,404,408,409,412],{},"For the sitemap, the ",[17,395,398],{"href":396,"rel":397},"https:\u002F\u002Fgetkirby.com\u002Fdocs\u002Fcookbook\u002Fnavigation\u002Fsitemap",[21],"recipe in the Kirby cookbook"," builds one from a route and a snippet. It lists every page, unlisted ones included, so I'd add the ones you don't want found to its ",[55,401,402],{},"sitemap.ignore"," option. If you'd rather not build it yourself, ",[17,405,407],{"href":406},"\u002Fdocs\u002Fhelpers\u002Fsitemap","Kirby Helpers"," serves a sitemap that lists each page's existing translations as ",[55,410,411],{},"hreflang"," alternates.",[63,414,416],{"id":415},"add-hreflang-only-for-translations-that-exist","Add hreflang Only for Translations That Exist",[10,418,419,420,73,423,426],{},"On a multi-language site, each page also lists its versions in the other languages. Kirby has the parts – ",[55,421,422],{},"$kirby->languages()",[55,424,425],{},"$page->url()"," with a language code – and leaves the markup to you:",[79,428,430],{"className":81,"code":429,"filename":83,"language":84,"meta":85,"style":85},"\u003C?php foreach ($kirby->languages() as $language): ?>\n  \u003C?php if ($page->translation($language->code())->exists()): ?>\n    \u003Clink rel=\"alternate\" hreflang=\"\u003C?= $language->code() ?>\" href=\"\u003C?= $page->url($language->code()) ?>\">\n  \u003C?php endif ?>\n\u003C?php endforeach ?>\n\u003Clink rel=\"alternate\" hreflang=\"x-default\" href=\"\u003C?= $page->url($kirby->defaultLanguage()->code()) ?>\">\n",[55,431,432,461,497,553,564,576],{"__ignoreMap":85},[89,433,434,436,438,441,444,446,449,451,454,457,459],{"class":91,"line":92},[89,435,335],{"class":95},[89,437,84],{"class":99},[89,439,440],{"class":95}," foreach",[89,442,443],{"class":106}," ($kirby",[89,445,110],{"class":95},[89,447,448],{"class":113},"languages",[89,450,131],{"class":106},[89,452,453],{"class":95},"as",[89,455,456],{"class":106}," $language)",[89,458,353],{"class":95},[89,460,356],{"class":95},[89,462,463,466,468,470,472,474,477,480,482,484,486,488,491,493,495],{"class":91,"line":168},[89,464,465],{"class":95},"  \u003C?",[89,467,84],{"class":99},[89,469,340],{"class":95},[89,471,343],{"class":106},[89,473,110],{"class":95},[89,475,476],{"class":113},"translation",[89,478,479],{"class":106},"($language",[89,481,110],{"class":95},[89,483,55],{"class":113},[89,485,150],{"class":106},[89,487,110],{"class":95},[89,489,490],{"class":113},"exists",[89,492,150],{"class":106},[89,494,353],{"class":95},[89,496,356],{"class":95},[89,498,499,502,504,506,508,511,514,516,518,521,523,525,527,529,531,533,535,537,539,542,544,546,548,551],{"class":91,"line":215},[89,500,501],{"class":95},"    \u003C",[89,503,220],{"class":99},[89,505,223],{"class":99},[89,507,179],{"class":95},[89,509,510],{"class":136},"\"alternate\"",[89,512,513],{"class":99}," hreflang",[89,515,179],{"class":95},[89,517,190],{"class":136},[89,519,520],{"class":106},"$language",[89,522,110],{"class":95},[89,524,55],{"class":106},[89,526,245],{"class":136},[89,528,231],{"class":99},[89,530,179],{"class":95},[89,532,190],{"class":136},[89,534,193],{"class":106},[89,536,110],{"class":95},[89,538,242],{"class":106},[89,540,541],{"class":136},"(",[89,543,520],{"class":106},[89,545,110],{"class":95},[89,547,55],{"class":106},[89,549,550],{"class":136},"()) ?>\"",[89,552,165],{"class":95},[89,554,556,558,560,562],{"class":91,"line":555},4,[89,557,465],{"class":95},[89,559,84],{"class":99},[89,561,388],{"class":95},[89,563,356],{"class":95},[89,565,567,569,571,574],{"class":91,"line":566},5,[89,568,335],{"class":95},[89,570,84],{"class":99},[89,572,573],{"class":95}," endforeach",[89,575,356],{"class":95},[89,577,579,581,583,585,587,589,591,593,596,598,600,602,604,606,608,610,613,615,618,621],{"class":91,"line":578},6,[89,580,96],{"class":95},[89,582,220],{"class":99},[89,584,223],{"class":99},[89,586,179],{"class":95},[89,588,510],{"class":136},[89,590,513],{"class":99},[89,592,179],{"class":95},[89,594,595],{"class":136},"\"x-default\"",[89,597,231],{"class":99},[89,599,179],{"class":95},[89,601,190],{"class":136},[89,603,193],{"class":106},[89,605,110],{"class":95},[89,607,242],{"class":106},[89,609,541],{"class":136},[89,611,612],{"class":106},"$kirby",[89,614,110],{"class":95},[89,616,617],{"class":106},"defaultLanguage",[89,619,620],{"class":136},"()->code()) ?>\"",[89,622,165],{"class":95},[10,624,625,628],{},[55,626,627],{},"x-default"," names the URL for every visitor whose language isn't on the list – here, the default language's.",[10,630,631,632,635,636,639],{},"Kirby renders every page in every language, translated or not. Without a German translation, ",[55,633,634],{},"\u002Fde\u002F…"," shows the English text with a normal 200 response. The ",[55,637,638],{},"exists()"," check keeps those pages out of the hreflang list.",[10,641,642,643,645],{},"Those pages still answer, though, and the canonical tag from the head snippet names their own ",[55,644,634],{}," URL. I'd point it at the default language wherever the translation is missing, in place of the canonical line above:",[79,647,649],{"className":81,"code":648,"filename":83,"language":84,"meta":85,"style":85},"\u003Clink rel=\"canonical\" href=\"\u003C?= $page->translation()->exists() ? $page->url() : $page->url($kirby->defaultLanguage()->code()) ?>\">\n",[55,650,651],{"__ignoreMap":85},[89,652,653,655,657,659,661,663,665,667,669,671,673,675,678,680,682,684,687,689,691,693,695,697,699,701,703],{"class":91,"line":92},[89,654,96],{"class":95},[89,656,220],{"class":99},[89,658,223],{"class":99},[89,660,179],{"class":95},[89,662,228],{"class":136},[89,664,231],{"class":99},[89,666,179],{"class":95},[89,668,190],{"class":136},[89,670,193],{"class":106},[89,672,110],{"class":95},[89,674,476],{"class":106},[89,676,677],{"class":136},"()->exists() ? ",[89,679,193],{"class":106},[89,681,110],{"class":95},[89,683,242],{"class":106},[89,685,686],{"class":136},"() : ",[89,688,193],{"class":106},[89,690,110],{"class":95},[89,692,242],{"class":106},[89,694,541],{"class":136},[89,696,612],{"class":106},[89,698,110],{"class":95},[89,700,617],{"class":106},[89,702,620],{"class":136},[89,704,165],{"class":95},[10,706,707,708,711],{},"A translation can also be half there: fields nobody translated show the default language's text, and fields saved empty stay empty. I built Translation Coverage into Content Translator so you don't have to find those by hand. It lists, per language, the pages without a translation and the fields a translation leaves empty, in the ",[262,709,710],{},"Languages"," view:",[713,714],"product-translator-coverage",{},[10,716,717,718,724],{},"Content Translator can translate slugs too: with ",[17,719,721],{"href":720},"\u002Fdocs\u002Fcontent-translator\u002Fconfiguration\u002Flocal#slug",[55,722,723],{},"slug: true",", it translates the title, and Kirby builds the slug from it with the target language's rules.",[63,726,728],{"id":727},"preview-the-google-result-in-the-panel","Preview the Google Result in the Panel",[10,730,731,732,734,735,739,740,73,743,746,747,73,749,751],{},"The meta fields get filled in on every page, by editors who never see the ",[55,733,57],{},". ",[17,736,738],{"href":737},"\u002Fserp-preview","SERP Preview"," is a Panel section, and its ",[55,741,742],{},"titleContentKey",[55,744,745],{},"descriptionContentKey"," options point it at the same ",[55,748,72],{},[55,750,76],{}," fields. It draws the page as a Google result while the editor types, and clamps the title to one line and the description to two, as Google does:",[753,754,755],"panel-mock",{},[756,757,758],"panel-section",{"label":738},[759,760],"panel-serp-preview-snippet",{"description":761,"faviconUrl":762,"siteTitle":763,"siteUrl":764,"title":765},"Kirby leaves meta tags, canonical URLs, hreflang, and the sitemap to you. Here's what your templates need to output, and where the Panel helps editors.","\u002Ffavicon.ico","Kirby Tools","https:\u002F\u002Fkirby.tools\u002Fblog\u002Fseo-in-kirby","SEO in Kirby CMS: A Practical Guide – Kirby Tools",[10,767,768],{},"It's free, and it never writes to the page: the snippet comes from the form as it stands, unsaved changes included.",[63,770,772],{"id":771},"audit-the-rendered-page","Audit the Rendered Page",[10,774,775,776,780],{},"SERP Preview shows what the fields say. ",[17,777,779],{"href":778},"\u002Fseo-audit","SEO Audit"," checks what the page says: it fetches the page's preview URL, unsaved changes included, and runs the Yoast analysis and its own checks on the rendered HTML in the editor's browser. It reads the title and meta description your head snippet produced and the content the editor just wrote, so the report flags template mistakes, like a second H1, next to writing problems:",[753,782,783],{},[784,785,787],"panel-dialog",{"size":786},"large",[788,789],"panel-seo-audit-result",{":isDialog":790,":ratings":791,":results":792,":timestamp":793,"version":794},"true","{\"seo\":{\"rating\":\"ok\"},\"readability\":{\"rating\":\"good\"}}","{\"seo\":[{\"rating\":\"bad\",\"text\":\"Single H1: The text contains multiple H1 tags. Rethink your heading structure!\"},{\"rating\":\"good\",\"text\":\"\u003Ca href=\\\"https:\u002F\u002Fyoa.st\u002F34h\\\">SEO title width\u003C\u002Fa>: Good job.\"}],\"readability\":[{\"rating\":\"good\",\"text\":\"\u003Ca href=\\\"https:\u002F\u002Fyoa.st\u002F35d\\\">Paragraph length\u003C\u002Fa>: There are no paragraphs that are too long. Great job.\"},{\"rating\":\"good\",\"text\":\"\u003Ca href=\\\"https:\u002F\u002Fyoa.st\u002F34v\\\">Sentence length\u003C\u002Fa>: Great.\"}]}","1791446400000","changes",[10,796,797,798,801,802,805,806,353],{},"SEO Audit picks its language rules from the ",[55,799,800],{},"lang"," attribute on ",[55,803,804],{},"\u003Chtml>",". Without one, the analysis assumes English, so I'd set it from the current language wherever your templates open ",[55,807,804],{},[79,809,812],{"className":81,"code":810,"filename":811,"language":84,"meta":85,"style":85},"\u003Chtml lang=\"\u003C?= $kirby->language()?->code() ?? 'en' ?>\">\n","site\u002Fsnippets\u002Fheader.php",[55,813,814],{"__ignoreMap":85},[89,815,816,818,821,824,826,828,830,832,835,838],{"class":91,"line":92},[89,817,96],{"class":95},[89,819,820],{"class":99},"html",[89,822,823],{"class":99}," lang",[89,825,179],{"class":95},[89,827,190],{"class":136},[89,829,612],{"class":106},[89,831,110],{"class":95},[89,833,834],{"class":106},"language",[89,836,837],{"class":136},"()?->code() ?? 'en' ?>\"",[89,839,165],{"class":95},[10,841,842,843,846,847,850,851,854],{},"On a single-language site, ",[55,844,845],{},"$kirby->language()"," is ",[55,848,849],{},"null",", so replace ",[55,852,853],{},"en"," with your site's language.",[63,856,858],{"id":857},"the-plugins-output-no-tags","The Plugins Output No Tags",[10,860,861,862,864,865,870],{},"SERP Preview and SEO Audit read what your templates render and what your editors type, Content Translator fills in the translations, and the ",[55,863,57],{}," stays in your templates. If you'd rather not write the template half yourself, the ",[17,866,869],{"href":867,"rel":868},"https:\u002F\u002Fplugins.getkirby.com\u002Ftopics\u002Fseo",[21],"SEO topic in the Kirby plugin directory"," lists plugins that take it over.",[10,872,873,877,878],{},[17,874,876],{"href":875},"\u002Fdocs\u002Fserp-preview","Get started with SERP Preview"," or ",[17,879,881],{"href":880},"\u002Fdocs\u002Fseo-audit\u002Fgetting-started","get started with SEO Audit",[883,884,885],"style",{},"html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}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":85,"searchDepth":168,"depth":168,"links":887},[888,889,890,891,892,893],{"id":65,"depth":168,"text":66},{"id":250,"depth":168,"text":251},{"id":415,"depth":168,"text":416},{"id":727,"depth":168,"text":728},{"id":771,"depth":168,"text":772},{"id":857,"depth":168,"text":858},"2026-10-08","md",null,{},true,"\u002Fblog\u002Fseo-in-kirby",{"title":47,"description":761},"blog\u002Fseo-in-kirby","rR43pNKJklAhup9366sodOtnxpyk9r5x3RDR3E_DS4k",1791534954976]