[{"data":1,"prerenderedAt":1722},["ShallowReactive",2],{"navigation":3,"content-listing-author-hlassiege-page-1":73},[4,25,45,61,65,69],{"title":5,"path":6,"stem":5,"children":7,"page":24},"2024","\u002F2024",[8,12,16,20],{"title":9,"path":10,"stem":11},"Analytics in Bloggrify: Measuring Your Audience Without Tracking Them","\u002F2024\u002Fanalytics","2024\u002Fanalytics",{"title":13,"path":14,"stem":15},"Announcing KaTeX Support: Easily Embed Mathematical Formulas in Bloggrify","\u002F2024\u002Fkatex","2024\u002Fkatex",{"title":17,"path":18,"stem":19},"Announcing Bloggrify 1.0: A New Static Blog Generator Built on Nuxt","\u002F2024\u002Flaunching","2024\u002Flaunching",{"title":21,"path":22,"stem":23},"Writing in Bloggrify: Beyond Basic Markdown","\u002F2024\u002Fmarkdown","2024\u002Fmarkdown",false,{"title":26,"path":27,"stem":26,"children":28,"page":24},"2025","\u002F2025",[29,33,37,41],{"title":30,"path":31,"stem":32},"Introducing a new custom component: listing page","\u002F2025\u002Fnew-custom-component","2025\u002Fnew-custom-component",{"title":34,"path":35,"stem":36},"Announcing Bloggrify 2.0: Enhanced SEO, Analytics, and Developer Experience","\u002F2025\u002Fversion-2-0","2025\u002Fversion-2-0",{"title":38,"path":39,"stem":40},"Announcing Bloggrify 2.1: More Shortcodes and Analytics Integration","\u002F2025\u002Fversion-2-1","2025\u002Fversion-2-1",{"title":42,"path":43,"stem":44},"Announcing Bloggrify 3.0: CLI tools, Nuxt UI integration, and more","\u002F2025\u002Fversion-3-0","2025\u002Fversion-3-0",{"title":46,"path":47,"stem":46,"children":48,"page":24},"2026","\u002F2026",[49,53,57],{"title":50,"path":51,"stem":52},"Should you block AI crawlers on your blog? And does it even work?","\u002F2026\u002Fai-crawlers-and-llms-txt","2026\u002Fai-crawlers-and-llms-txt",{"title":54,"path":55,"stem":56},"The Search Box That Downloaded Itself on Every Page","\u002F2026\u002Floading-search-only-when-readers-need-it","2026\u002Floading-search-only-when-readers-need-it",{"title":58,"path":59,"stem":60},"Announcing Bloggrify 3.2: redesigned minimalist theme, AI crawler controls, and faster pages","\u002F2026\u002Fversion-3-2","2026\u002Fversion-3-2",{"title":62,"path":63,"stem":64},"About","\u002Fabout","about",{"title":66,"path":67,"stem":68},"Bloggrify","\u002F","index",{"title":70,"path":71,"stem":72},"SEO in Bloggrify: How Your Blog Gets Found","\u002Fseo","seo",[74,349,966,1347,1440],{"id":75,"title":58,"alternates":76,"author":77,"body":78,"categories":76,"comments":24,"cover":76,"date":333,"description":334,"draft":24,"extension":335,"hidden":24,"language":76,"layout":76,"links":76,"listed":24,"meta":336,"navigation":337,"nocomments":24,"notoc":24,"pageid":338,"path":59,"readingTime":339,"redirect_to_domain":76,"redirect_to_full_url":76,"robots":76,"schemaOrg":76,"seo":344,"sitemap":345,"stem":60,"table_of_contents":337,"tags":346,"__hash__":348},"page\u002F2026\u002Fversion-3-2.md",null,"hlassiege",{"type":79,"value":80,"toc":320},"minimark",[81,85,90,93,121,124,128,138,146,150,153,167,173,177,184,188,191,203,207,210,234,241,245,276,280,295,299,309],[82,83,84],"p",{},"Bloggrify 3.2.0 is out. This release redesigns the default minimalist theme, adds a set of SEO controls aimed at AI crawlers, makes pages lighter for the average reader, and fixes a number of correctness issues around drafts, authors and error pages.",[86,87,89],"h2",{"id":88},"a-redesigned-minimalist-theme","A redesigned minimalist theme",[82,91,92],{},"The minimalist theme, the one Bloggrify ships with, has been rebuilt after the Nuxt UI blog template. It is no longer just a list of posts:",[94,95,96,110,115],"ul",{},[97,98,99,100,104,105,109],"li",{},"a ",[101,102,103],"strong",{},"table of contents"," on posts, which you can hide per post with the ",[106,107,108],"code",{},"notoc"," frontmatter",[97,111,99,112],{},[101,113,114],{},"newsletter signup form",[97,116,117,120],{},[101,118,119],{},"social share buttons"," on articles",[82,122,123],{},"The redesign leans on Nuxt UI components throughout, so it stays consistent with the rest of the stack and inherits its dark mode.",[86,125,127],{"id":126},"controls-for-ai-crawlers-and-llmstxt","Controls for AI crawlers and llms.txt",[82,129,130,131,133,134,137],{},"A new ",[106,132,72],{}," config key lets you decide how AI tools interact with your blog, without touching your search engine indexing. Blocking the major AI crawlers is one line, and publishing an ",[106,135,136],{},"llms.txt"," index is another. Both default to leaving your blog exactly as it is today.",[82,139,140,141,145],{},"We wrote a full post on what these switches do, what they actually protect, and whether they are worth turning on: ",[142,143,144],"a",{"href":51},"Should you block AI crawlers on your blog?",".",[86,147,149],{"id":148},"lighter-pages-by-default","Lighter pages by default",[82,151,152],{},"Two changes move cost off the readers who were paying for features they did not use:",[94,154,155,161],{},[97,156,157,160],{},[101,158,159],{},"Article images are served as WebP",", which are smaller than the equivalent JPEG or PNG.",[97,162,163,166],{},[101,164,165],{},"The search index loads on first search intent only."," Until now every page quietly downloaded the search engine and content database, even for readers who never searched. It now loads when a reader hovers the search button or opens it with ⌘K.",[82,168,169,170,145],{},"The search change turned out to be more subtle than flipping a flag, so it also has its own write-up: ",[142,171,172],{"href":55},"The search box that downloaded itself on every page",[86,174,176],{"id":175},"a-new-comment-provider-hakanai-connect","A new comment provider: Hakanai Connect",[82,178,179,180,183],{},"Bloggrify gains ",[101,181,182],{},"Hakanai Connect"," as an alternative to Hyvor Talk for comments. It is now the provider running on the official Bloggrify blog. Hyvor remains supported, so switching is a config choice, not a migration you are forced into.",[86,185,187],{"id":186},"more-analytics-providers","More analytics providers",[82,189,190],{},"Two providers join the existing options, and analytics config is now fully optional:",[94,192,193,198],{},[97,194,195],{},[101,196,197],{},"OpenPanel",[97,199,200],{},[101,201,202],{},"Hakanai Pulse",[86,204,206],{"id":205},"authors-and-error-pages","Authors and error pages",[82,208,209],{},"Author handling gets more predictable:",[94,211,212,218,224,231],{},[97,213,214,215],{},"an ",[101,216,217],{},"opt-in authors directory page",[97,219,220,221],{},"the post author is now part of the ",[101,222,223],{},"SEO metadata",[97,225,226,227,230],{},"Bloggrify ",[101,228,229],{},"warns in dev"," when a post references an author you never defined",[97,232,233],{},"posts without an explicit author show up on the default author page instead of disappearing",[82,235,236,237,240],{},"Themes can now ship ",[101,238,239],{},"their own error pages",", with a per-theme override and a sensible fallback when a theme does not provide one.",[86,242,244],{"id":243},"correctness-fixes-worth-calling-out","Correctness fixes worth calling out",[94,246,247,253,259,266],{},[97,248,249,250],{},"drafts and unlisted pages ",[101,251,252],{},"no longer leak into the RSS feed",[97,254,255,256],{},"unknown URLs and pages with no matching layout return a proper ",[101,257,258],{},"404 instead of a 500",[97,260,261,262,265],{},"previous\u002Fnext article navigation is now ordered ",[101,263,264],{},"by date"," rather than by file path",[97,267,268,271,272,275],{},[106,269,270],{},"draft"," and ",[106,273,274],{},"listed"," frontmatter behave as the documentation describes",[86,277,279],{"id":278},"under-the-hood","Under the hood",[82,281,282,283,286,287,290,291,294],{},"Bloggrify 3.2 moves to ",[101,284,285],{},"Nuxt 4.4.8"," and upgrades the Nuxt SEO modules (sitemap v8, robots v6, schema-org v6). Lucide icons are now bundled locally with ",[106,288,289],{},"@iconify-json\u002Flucide",", and ",[106,292,293],{},"nuxt-og-image"," was upgraded to v6 to restore OG image generation.",[86,296,298],{"id":297},"contribute","Contribute",[82,300,301,302,308],{},"Bloggrify is open source. ",[142,303,307],{"href":304,"rel":305},"https:\u002F\u002Fgithub.com\u002Fbloggrify\u002Fbloggrify",[306],"nofollow","Help us on GitHub",":",[94,310,311,314,317],{},[97,312,313],{},"Report issues",[97,315,316],{},"Submit PRs",[97,318,319],{},"Join discussions",{"title":321,"searchDepth":322,"depth":322,"links":323},"",2,[324,325,326,327,328,329,330,331,332],{"id":88,"depth":322,"text":89},{"id":126,"depth":322,"text":127},{"id":148,"depth":322,"text":149},{"id":175,"depth":322,"text":176},{"id":186,"depth":322,"text":187},{"id":205,"depth":322,"text":206},{"id":243,"depth":322,"text":244},{"id":278,"depth":322,"text":279},{"id":297,"depth":322,"text":298},"2026-07-18","The default theme gets a full redesign with table of contents, newsletter and share buttons, alongside new SEO controls for AI crawlers, WebP images and on-demand search.","md",{},true,"15",{"text":340,"minutes":341,"time":342,"words":343},"3 min read",2.555,153300,511,{"title":58,"description":334},{"loc":59},[347],"release","zwGWQHp-71ktUSXiO4t6qy_Zj8h3Ga8FW3dM450alNQ",{"id":350,"title":54,"alternates":76,"author":77,"body":351,"categories":76,"comments":24,"cover":76,"date":951,"description":952,"draft":24,"extension":335,"hidden":24,"language":76,"layout":76,"links":76,"listed":24,"meta":953,"navigation":337,"nocomments":24,"notoc":24,"pageid":954,"path":55,"readingTime":955,"redirect_to_domain":76,"redirect_to_full_url":76,"robots":76,"schemaOrg":76,"seo":960,"sitemap":961,"stem":56,"table_of_contents":337,"tags":962,"__hash__":965},"page\u002F2026\u002Floading-search-only-when-readers-need-it.md",{"type":79,"value":352,"toc":943},[353,356,360,363,366,369,373,376,492,507,510,514,517,613,623,626,629,633,636,639,691,694,697,787,793,796,877,886,890,893,912,922,926,929,939],[82,354,355],{},"Bloggrify ships an instant, fuzzy search: hit ⌘K, start typing, and results appear as you go. It feels free. It was not: the download that powers it was being paid by every reader, including the majority who never search. This post looks at why, and how we changed it so the cost falls only on the readers who actually use it.",[86,357,359],{"id":358},"how-search-works-when-there-is-no-server","How search works when there is no server",[82,361,362],{},"Bloggrify blogs are static. There is no backend, no database sitting behind an API, nothing to send a query to. So when a reader searches, the searching has to happen in their browser.",[82,364,365],{},"That is a lovely property. It also has a consequence: if the browser is going to do the searching, the browser needs the thing to search. Nuxt Content builds that \"thing\" for you, and under the hood it is not small. To run queries client-side, it loads a WebAssembly build of SQLite and a dump of your content database. The browser boots a tiny database engine and asks it questions locally.",[82,367,368],{},"That is what makes the search feel instant once it is running. It is also a real download, and downloads are never free.",[86,370,372],{"id":371},"the-catch-everyone-paid-whether-they-searched-or-not","The catch: everyone paid, whether they searched or not",[82,374,375],{},"Here is the code we started from, roughly:",[377,378,382],"pre",{"className":379,"code":380,"language":381,"meta":321,"style":321},"language-typescript shiki shiki-themes material-theme-lighter catppuccin-frappe github-dark","const { data: files } = useLazyAsyncData(\n  'search',\n  () => queryCollectionSearchSections('page'),\n  { server: false }\n)\n","typescript",[106,383,384,422,438,466,486],{"__ignoreMap":321},[385,386,389,393,397,401,403,407,410,414,418],"span",{"class":387,"line":388},"line",1,[385,390,392],{"class":391},"skPWg","const",[385,394,396],{"class":395},"sdvfp"," {",[385,398,400],{"class":399},"sCl4M"," data",[385,402,308],{"class":395},[385,404,406],{"class":405},"sdtVv"," files",[385,408,409],{"class":395}," }",[385,411,413],{"class":412},"srEZA"," =",[385,415,417],{"class":416},"srxfx"," useLazyAsyncData",[385,419,421],{"class":420},"s8bja","(\n",[385,423,424,428,432,435],{"class":387,"line":322},[385,425,427],{"class":426},"srOHQ","  '",[385,429,431],{"class":430},"sw2QF","search",[385,433,434],{"class":426},"'",[385,436,437],{"class":395},",\n",[385,439,441,444,448,451,454,456,459,461,464],{"class":387,"line":440},3,[385,442,443],{"class":395},"  ()",[385,445,447],{"class":446},"sG1e1"," =>",[385,449,450],{"class":416}," queryCollectionSearchSections",[385,452,453],{"class":420},"(",[385,455,434],{"class":426},[385,457,458],{"class":430},"page",[385,460,434],{"class":426},[385,462,463],{"class":420},")",[385,465,437],{"class":395},[385,467,469,472,476,479,483],{"class":387,"line":468},4,[385,470,471],{"class":395},"  {",[385,473,475],{"class":474},"sHJOX"," server",[385,477,308],{"class":478},"s1BmC",[385,480,482],{"class":481},"sbhg_"," false",[385,484,485],{"class":395}," }\n",[385,487,489],{"class":387,"line":488},5,[385,490,491],{"class":420},")\n",[82,493,494,495,498,499,502,503,506],{},"Read that carefully. ",[106,496,497],{},"server: false"," says \"do not run this during the static build, run it in the browser\". Sensible: the search index is only useful client-side. But ",[106,500,501],{},"useLazyAsyncData"," fetches ",[101,504,505],{},"immediately"," on mount by default. And the search component lives in the navigation bar, which is on every single page.",[82,508,509],{},"So the chain was: every page mount, on every visit, quietly kicked off the fetch of the WASM engine and the database dump. For a reader who lands on one post, reads it, and leaves, that is a download of the entire search machinery to power a feature they never touched. Most readers never search. We were charging all of them for the few who do.",[86,511,513],{"id":512},"why-you-cannot-just-load-it-later","Why you cannot just \"load it later\"",[82,515,516],{},"The obvious fix is to stop loading it eagerly. Nuxt gives you exactly that switch:",[377,518,520],{"className":379,"code":519,"language":381,"meta":321,"style":321},"const { data: files, status, execute: loadSearchIndex } = useLazyAsyncData(\n  'search',\n  () => queryCollectionSearchSections('page'),\n  { server: false, immediate: false }\n)\n",[106,521,522,558,568,588,609],{"__ignoreMap":321},[385,523,524,526,528,530,532,534,537,540,542,545,547,550,552,554,556],{"class":387,"line":388},[385,525,392],{"class":391},[385,527,396],{"class":395},[385,529,400],{"class":399},[385,531,308],{"class":395},[385,533,406],{"class":405},[385,535,536],{"class":395},",",[385,538,539],{"class":405}," status",[385,541,536],{"class":395},[385,543,544],{"class":399}," execute",[385,546,308],{"class":395},[385,548,549],{"class":405}," loadSearchIndex",[385,551,409],{"class":395},[385,553,413],{"class":412},[385,555,417],{"class":416},[385,557,421],{"class":420},[385,559,560,562,564,566],{"class":387,"line":322},[385,561,427],{"class":426},[385,563,431],{"class":430},[385,565,434],{"class":426},[385,567,437],{"class":395},[385,569,570,572,574,576,578,580,582,584,586],{"class":387,"line":440},[385,571,443],{"class":395},[385,573,447],{"class":446},[385,575,450],{"class":416},[385,577,453],{"class":420},[385,579,434],{"class":426},[385,581,458],{"class":430},[385,583,434],{"class":426},[385,585,463],{"class":420},[385,587,437],{"class":395},[385,589,590,592,594,596,598,600,603,605,607],{"class":387,"line":468},[385,591,471],{"class":395},[385,593,475],{"class":474},[385,595,308],{"class":478},[385,597,482],{"class":481},[385,599,536],{"class":395},[385,601,602],{"class":474}," immediate",[385,604,308],{"class":478},[385,606,482],{"class":481},[385,608,485],{"class":395},[385,610,611],{"class":387,"line":488},[385,612,491],{"class":420},[82,614,615,618,619,622],{},[106,616,617],{},"immediate: false"," means nothing is fetched until you call ",[106,620,621],{},"execute()"," yourself. Now the reader who never searches downloads nothing. Good.",[82,624,625],{},"But this is where the interesting part starts, because the naive version of \"load it later\" is worse than the problem it solves. If you wait until the reader clicks the search button to start the download, they open the box, see an empty field, and wait. The engine and the dump have to arrive before they can get a single result. You have taken a feature that felt instant and made it stutter for the exact people who wanted to use it.",[82,627,628],{},"The index needs to be there the moment they want it, and not a moment before they show they want it. The whole trick is reading that intent early enough.",[86,630,632],{"id":631},"reading-intent-from-two-directions","Reading intent, from two directions",[82,634,635],{},"The challenge is that there are two completely different ways to open search, and they give you different amounts of warning.",[82,637,638],{},"The mouse is generous. Nobody clicks a button without first moving the pointer to it, and hovering is a near-certain signal that a click is coming. That gap of a few hundred milliseconds between hover and click is exactly enough to start the download early. So we prefetch on hover and on keyboard focus:",[377,640,644],{"className":641,"code":642,"language":643,"meta":321,"style":321},"language-html shiki shiki-themes material-theme-lighter catppuccin-frappe github-dark","\u003CUContentSearchButton\n  @pointerenter=\"ensureSearchIndex\"\n  @focus=\"ensureSearchIndex\"\n\u002F>\n","html",[106,645,646,655,673,686],{"__ignoreMap":321},[385,647,648,651],{"class":387,"line":388},[385,649,650],{"class":478},"\u003C",[385,652,654],{"class":653},"sGLM_","UContentSearchButton\n",[385,656,657,661,664,667,670],{"class":387,"line":322},[385,658,660],{"class":659},"s3uge","  @pointerenter",[385,662,663],{"class":478},"=",[385,665,666],{"class":426},"\"",[385,668,669],{"class":430},"ensureSearchIndex",[385,671,672],{"class":426},"\"\n",[385,674,675,678,680,682,684],{"class":387,"line":440},[385,676,677],{"class":659},"  @focus",[385,679,663],{"class":478},[385,681,666],{"class":426},[385,683,669],{"class":430},[385,685,672],{"class":426},[385,687,688],{"class":387,"line":468},[385,689,690],{"class":478},"\u002F>\n",[82,692,693],{},"By the time the click lands, the index is usually already on its way, often already there.",[82,695,696],{},"The keyboard shortcut is the opposite. ⌘K gives no warning at all: intent and action are the same instant. There is no hover to catch. So we cover it from the other side, by watching the state that actually represents \"search is open\", whichever path opened it:",[377,698,700],{"className":379,"code":699,"language":381,"meta":321,"style":321},"const { open } = useContentSearch()\n\nwatch(open, (isOpen) => {\n  if (isOpen) {\n    ensureSearchIndex()\n  }\n})\n",[106,701,702,721,726,750,766,773,779],{"__ignoreMap":321},[385,703,704,706,708,711,713,715,718],{"class":387,"line":388},[385,705,392],{"class":391},[385,707,396],{"class":395},[385,709,710],{"class":405}," open",[385,712,409],{"class":395},[385,714,413],{"class":412},[385,716,717],{"class":416}," useContentSearch",[385,719,720],{"class":420},"()\n",[385,722,723],{"class":387,"line":322},[385,724,725],{"emptyLinePlaceholder":337},"\n",[385,727,728,731,734,736,739,743,745,747],{"class":387,"line":440},[385,729,730],{"class":416},"watch",[385,732,733],{"class":420},"(open",[385,735,536],{"class":395},[385,737,738],{"class":395}," (",[385,740,742],{"class":741},"sd0zt","isOpen",[385,744,463],{"class":395},[385,746,447],{"class":446},[385,748,749],{"class":395}," {\n",[385,751,752,756,758,760,763],{"class":387,"line":468},[385,753,755],{"class":754},"sHqub","  if",[385,757,738],{"class":474},[385,759,742],{"class":420},[385,761,762],{"class":474},") ",[385,764,765],{"class":395},"{\n",[385,767,768,771],{"class":387,"line":488},[385,769,770],{"class":416},"    ensureSearchIndex",[385,772,720],{"class":474},[385,774,776],{"class":387,"line":775},6,[385,777,778],{"class":395},"  }\n",[385,780,782,785],{"class":387,"line":781},7,[385,783,784],{"class":395},"}",[385,786,491],{"class":420},[82,788,789,792],{},[106,790,791],{},"open"," is a shared piece of state toggled by the button and by the shortcut alike. Watching it means we do not have to enumerate every possible trigger. Anything that opens search, present or future, flows through here.",[82,794,795],{},"Finally, all of these paths funnel through one small guard so the index is fetched once and not on every hover:",[377,797,799],{"className":379,"code":798,"language":381,"meta":321,"style":321},"function ensureSearchIndex() {\n  if (status.value === 'idle' || status.value === 'error') {\n    loadSearchIndex()\n  }\n}\n",[106,800,801,814,861,868,872],{"__ignoreMap":321},[385,802,803,806,809,812],{"class":387,"line":388},[385,804,805],{"class":391},"function",[385,807,808],{"class":416}," ensureSearchIndex",[385,810,811],{"class":395},"()",[385,813,749],{"class":395},[385,815,816,818,820,823,825,828,831,834,837,839,842,844,846,848,850,852,855,857,859],{"class":387,"line":322},[385,817,755],{"class":754},[385,819,738],{"class":474},[385,821,822],{"class":420},"status",[385,824,145],{"class":478},[385,826,827],{"class":420},"value",[385,829,830],{"class":412}," ===",[385,832,833],{"class":426}," '",[385,835,836],{"class":430},"idle",[385,838,434],{"class":426},[385,840,841],{"class":412}," ||",[385,843,539],{"class":420},[385,845,145],{"class":478},[385,847,827],{"class":420},[385,849,830],{"class":412},[385,851,833],{"class":426},[385,853,854],{"class":430},"error",[385,856,434],{"class":426},[385,858,762],{"class":474},[385,860,765],{"class":395},[385,862,863,866],{"class":387,"line":440},[385,864,865],{"class":416},"    loadSearchIndex",[385,867,720],{"class":474},[385,869,870],{"class":387,"line":468},[385,871,778],{"class":395},[385,873,874],{"class":387,"line":488},[385,875,876],{"class":395},"}\n",[82,878,879,880,882,883,885],{},"It loads when nothing has happened yet (",[106,881,836],{},"), and it retries if a previous attempt failed (",[106,884,854],{},"), but it stays out of the way while a fetch is in flight or already done. The reader can wave the pointer over the button ten times and only the first one does anything.",[86,887,889],{"id":888},"a-small-tuning-while-we-were-here","A small tuning while we were here",[82,891,892],{},"Once search actually loads on demand, it is worth making sure the results are good. Fuzzy matching is handled by Fuse.js, and its defaults are tuned for short strings, not blog content. Two options made a real difference:",[377,894,896],{"className":379,"code":895,"language":381,"meta":321,"style":321},":fuse=\"{ resultLimit: 42, fuseOptions: { threshold: 0.3, ignoreLocation: true } }\"\n",[106,897,898],{"__ignoreMap":321},[385,899,900,903,905,907,910],{"class":387,"line":388},[385,901,902],{"class":420},":fuse",[385,904,663],{"class":412},[385,906,666],{"class":426},[385,908,909],{"class":430},"{ resultLimit: 42, fuseOptions: { threshold: 0.3, ignoreLocation: true } }",[385,911,672],{"class":426},[82,913,914,917,918,921],{},[106,915,916],{},"ignoreLocation"," tells Fuse to stop caring where in the text a match occurs. By default it favours matches near the start of a field, which makes sense for names and titles but punishes a term that appears in the middle of a paragraph. ",[106,919,920],{},"threshold: 0.3"," tightens how fuzzy a match is allowed to be, so a search returns things that are genuinely relevant rather than everything vaguely alike.",[86,923,925],{"id":924},"what-changed-concretely","What changed, concretely",[82,927,928],{},"Nothing about the experience got slower, and for most visitors a good chunk of every page load simply disappeared. A reader who never searches now downloads none of the search machinery. A reader who does gets it warmed up before they have finished reaching for it, whether by mouse or by keyboard.",[82,930,931,932,935,936,938],{},"This pattern is not specific to search. Eager data fetching is the comfortable default, and it is very often the wrong one. ",[106,933,934],{},"useAsyncData"," will happily load everything the moment a component mounts, and that convenience quietly adds up when the component is everywhere and the data is heavy. Flipping to ",[106,937,617],{}," and spending a little effort on reading intent is not much code. Here it moved a cost off every reader who was never going to use it.",[940,941,942],"style",{},"html pre.shiki code .skPWg, html code.shiki .skPWg{--shiki-light:#9C3EDA;--shiki-default:#CA9EE6;--shiki-dark:#F97583}html pre.shiki code .sdvfp, html code.shiki .sdvfp{--shiki-light:#39ADB5;--shiki-default:#949CBB;--shiki-dark:#E1E4E8}html pre.shiki code .sCl4M, html code.shiki .sCl4M{--shiki-light:#E53935;--shiki-default:#C6D0F5;--shiki-dark:#FFAB70}html pre.shiki code .sdtVv, html code.shiki .sdtVv{--shiki-light:#90A4AE;--shiki-default:#C6D0F5;--shiki-dark:#79B8FF}html pre.shiki code .srEZA, html code.shiki .srEZA{--shiki-light:#39ADB5;--shiki-default:#81C8BE;--shiki-dark:#F97583}html pre.shiki code .srxfx, html code.shiki .srxfx{--shiki-light:#6182B8;--shiki-light-font-style:inherit;--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit}html pre.shiki code .s8bja, html code.shiki .s8bja{--shiki-light:#90A4AE;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .srOHQ, html code.shiki .srOHQ{--shiki-light:#39ADB5;--shiki-default:#A6D189;--shiki-dark:#9ECBFF}html pre.shiki code .sw2QF, html code.shiki .sw2QF{--shiki-light:#91B859;--shiki-default:#A6D189;--shiki-dark:#9ECBFF}html pre.shiki code .sG1e1, html code.shiki .sG1e1{--shiki-light:#9C3EDA;--shiki-default:#81C8BE;--shiki-dark:#F97583}html pre.shiki code .sHJOX, html code.shiki .sHJOX{--shiki-light:#E53935;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .s1BmC, html code.shiki .s1BmC{--shiki-light:#39ADB5;--shiki-default:#81C8BE;--shiki-dark:#E1E4E8}html pre.shiki code .sbhg_, html code.shiki .sbhg_{--shiki-light:#FF5370;--shiki-default:#EF9F76;--shiki-dark:#79B8FF}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);}html pre.shiki code .sGLM_, html code.shiki .sGLM_{--shiki-light:#E53935;--shiki-light-font-style:inherit;--shiki-default:#8CAAEE;--shiki-default-font-style:inherit;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .s3uge, html code.shiki .s3uge{--shiki-light:#9C3EDA;--shiki-default:#E5C890;--shiki-dark:#B392F0}html pre.shiki code .sd0zt, html code.shiki .sd0zt{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EA999C;--shiki-default-font-style:italic;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sHqub, html code.shiki .sHqub{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#CA9EE6;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}",{"title":321,"searchDepth":322,"depth":322,"links":944},[945,946,947,948,949,950],{"id":358,"depth":322,"text":359},{"id":371,"depth":322,"text":372},{"id":512,"depth":322,"text":513},{"id":631,"depth":322,"text":632},{"id":888,"depth":322,"text":889},{"id":924,"depth":322,"text":925},"2026-07-17","How Bloggrify's instant search worked, why it was quietly costing every reader a download they never used, and how we made it load only on intent.",{},"14",{"text":956,"minutes":957,"time":958,"words":959},"6 min read",5.125,307500,1025,{"title":54,"description":952},{"loc":55},[963,964],"performance","nuxt","sLAXHiEnoWs1xEOexwzN9ffNH6b-1lXN1r1ipDjfLEE",{"id":967,"title":50,"alternates":76,"author":77,"body":968,"categories":76,"comments":24,"cover":76,"date":1334,"description":1335,"draft":24,"extension":335,"hidden":24,"language":76,"layout":76,"links":76,"listed":24,"meta":1336,"navigation":337,"nocomments":24,"notoc":24,"pageid":1337,"path":51,"readingTime":1338,"redirect_to_domain":76,"redirect_to_full_url":76,"robots":76,"schemaOrg":76,"seo":1342,"sitemap":1343,"stem":52,"table_of_contents":337,"tags":1344,"__hash__":1346},"page\u002F2026\u002Fai-crawlers-and-llms-txt.md",{"type":79,"value":969,"toc":1327},[970,972,975,978,981,984,987,990,1012,1021,1025,1030,1036,1042,1107,1123,1126,1135,1141,1144,1148,1153,1166,1169,1228,1242,1247,1250,1255,1265,1268,1272,1275,1305,1317,1324],[82,971,144],{},[82,973,974],{},"It is a real question for a lot of writers online right now. Should we let LLMs feed off our content? Is there a risk to our visibility if, tomorrow, readers get their answers straight from ChatGPT?",[82,976,977],{},"Some articles are indeed alarmed by the fairly broad drop in traffic across sites.",[82,979,980],{},"Or the other way round: by becoming invisible to the LLMs, are we not cutting ourselves off from a potential source of traffic?",[82,982,983],{},"For my part, I tend to think that we, as readers, are changing the way we browse and search, and that this drop in traffic is unavoidable. So the question is whether to block the crawlers entirely to slow the trend down, or instead to try to be part of this new ecosystem. You be the judge.",[82,985,986],{},"Say you pick one path or the other. How do you go about it? How do you block the crawlers, or encourage them to read your blog? And does it actually work?",[82,988,989],{},"Before we start, it helps to separate two things that often get mixed up:",[991,992,993,1003],"ol",{},[97,994,995,998,999,1002],{},[101,996,997],{},"Do you want AI crawlers to use your content at all?"," That is a ",[106,1000,1001],{},"robots.txt"," question",[97,1004,1005,1008,1009,1011],{},[101,1006,1007],{},"Do you want to make your content easy for AI tools to read?"," That is what ",[106,1010,136],{}," is for",[82,1013,1014,1015,1017,1018,1020],{},"They are independent. You can block crawlers and skip ",[106,1016,136],{},", publish ",[106,1019,136],{}," and welcome crawlers, or do neither. What does not make sense is answering \"no\" to the first and \"yes\" to the second, and we will come back to that.",[86,1022,1024],{"id":1023},"do-you-want-ai-to-read-your-blog","Do you want AI to read your blog?",[82,1026,1027,1028,145],{},"First thing first: the major AI crawlers do respect ",[106,1029,1001],{},[82,1031,1032,1033,1035],{},"OpenAI, Anthropic, Google, Perplexity and the rest publish the names of their crawlers, and they document that those crawlers honour ",[106,1034,1001],{}," directives. This is not a folk belief, it is written policy. So if you decide you would rather not feed your writing into a training set or an answer engine, you can say so, and the well-behaved bots will listen.",[82,1037,1038,1039,308],{},"In Bloggrify that decision is one line in your ",[106,1040,1041],{},"app.config.ts",[377,1043,1045],{"className":379,"code":1044,"filename":1041,"language":381,"meta":321,"style":321},"export default defineAppConfig({\n  seo: {\n    ai: {\n      allowCrawlers: false,\n    },\n  },\n})\n",[106,1046,1047,1062,1071,1080,1091,1096,1101],{"__ignoreMap":321},[385,1048,1049,1052,1055,1058,1060],{"class":387,"line":388},[385,1050,1051],{"class":754},"export",[385,1053,1054],{"class":754}," default",[385,1056,1057],{"class":416}," defineAppConfig",[385,1059,453],{"class":420},[385,1061,765],{"class":395},[385,1063,1064,1067,1069],{"class":387,"line":322},[385,1065,1066],{"class":474},"  seo",[385,1068,308],{"class":478},[385,1070,749],{"class":395},[385,1072,1073,1076,1078],{"class":387,"line":440},[385,1074,1075],{"class":474},"    ai",[385,1077,308],{"class":478},[385,1079,749],{"class":395},[385,1081,1082,1085,1087,1089],{"class":387,"line":468},[385,1083,1084],{"class":474},"      allowCrawlers",[385,1086,308],{"class":478},[385,1088,482],{"class":481},[385,1090,437],{"class":395},[385,1092,1093],{"class":387,"line":488},[385,1094,1095],{"class":395},"    },\n",[385,1097,1098],{"class":387,"line":775},[385,1099,1100],{"class":395},"  },\n",[385,1102,1103,1105],{"class":387,"line":781},[385,1104,784],{"class":395},[385,1106,491],{"class":420},[82,1108,1109,1110,1113,1114,1116,1117,1122],{},"That adds a ",[106,1111,1112],{},"Disallow: \u002F"," group to your generated ",[106,1115,1001],{}," covering the AI crawlers of the major vendors. Your blog stays perfectly indexed in Google and Bing, because search crawlers are deliberately left alone: you refuse the AI training agents without breaking the features you actually want. If you would like the full details of what gets blocked and what does not, the ",[142,1118,1121],{"href":1119,"rel":1120},"https:\u002F\u002Fbloggrify.com\u002Freference\u002Fai",[306],"AI crawlers reference"," spells it out.",[82,1124,1125],{},"Two things are worth being clear about.",[82,1127,1128,1131,1132,1134],{},[101,1129,1130],{},"It is a request, not a wall."," ",[106,1133,1001],{}," is voluntary by design. Most crawlers honour it, some have been caught ignoring it, and anything you publish on a public static blog can ultimately be copied by someone who does not care about the rules. If you need real enforcement, you block at the network level, for example with your host's \"block AI scrapers\" feature. That happens outside Bloggrify, at your CDN or hosting provider.",[82,1136,1137,1140],{},[101,1138,1139],{},"Doing nothing is a valid answer too."," If you do not mind AI tools reading your posts, you change nothing. That is the default. Your content stays open, and the crawlers come and go as they always have. Not every blogger wants to fight this, and that is completely fine.",[82,1142,1143],{},"The point is simply that it is your content and your call. Bloggrify gives you the switch so the choice is yours to make, not one made for you by omission.",[86,1145,1147],{"id":1146},"making-your-blog-easy-to-read-llmstxt","Making your blog easy to read: llms.txt",[82,1149,1150,1151,145],{},"If you land on the \"sure, AI can read my blog\" side, there is a second, gentler thing you can offer: ",[106,1152,136],{},[82,1154,1155,1157,1158,1160,1161,145],{},[106,1156,136],{}," was proposed by Jeremy Howard, co-founder of Answer.AI, in September 2024. The idea is small and reasonable. A web page is full of navigation, scripts and markup that an AI has to wade through to find the actual content. ",[106,1159,136],{}," is a single markdown file at the root of your site that hands over a clean, structured index instead: a title, a short description, and a link for each post. You can read the full specification at ",[142,1162,1165],{"href":1163,"rel":1164},"https:\u002F\u002Fllmstxt.org",[306],"llmstxt.org",[82,1167,1168],{},"Turning it on is, again, one line:",[377,1170,1172],{"className":379,"code":1171,"filename":1041,"language":381,"meta":321,"style":321},"export default defineAppConfig({\n  seo: {\n    ai: {\n      llms: true,\n    },\n  },\n})\n",[106,1173,1174,1186,1194,1202,1214,1218,1222],{"__ignoreMap":321},[385,1175,1176,1178,1180,1182,1184],{"class":387,"line":388},[385,1177,1051],{"class":754},[385,1179,1054],{"class":754},[385,1181,1057],{"class":416},[385,1183,453],{"class":420},[385,1185,765],{"class":395},[385,1187,1188,1190,1192],{"class":387,"line":322},[385,1189,1066],{"class":474},[385,1191,308],{"class":478},[385,1193,749],{"class":395},[385,1195,1196,1198,1200],{"class":387,"line":440},[385,1197,1075],{"class":474},[385,1199,308],{"class":478},[385,1201,749],{"class":395},[385,1203,1204,1207,1209,1212],{"class":387,"line":468},[385,1205,1206],{"class":474},"      llms",[385,1208,308],{"class":478},[385,1210,1211],{"class":481}," true",[385,1213,437],{"class":395},[385,1215,1216],{"class":387,"line":488},[385,1217,1095],{"class":395},[385,1219,1220],{"class":387,"line":775},[385,1221,1100],{"class":395},[385,1223,1224,1226],{"class":387,"line":781},[385,1225,784],{"class":395},[385,1227,491],{"class":420},[82,1229,1230,1231,1234,1235,271,1238,1241],{},"Bloggrify then generates a ",[106,1232,1233],{},"\u002Fllms.txt"," route at build time, right next to your ",[106,1236,1237],{},"sitemap.xml",[106,1239,1240],{},"rss.xml",". Drafts and hidden posts are excluded, and when the option is off, which is the default, the file is not generated at all.",[1243,1244,1246],"h3",{"id":1245},"should-you-bother","Should you bother?",[82,1248,1249],{},"Here I want to be straight with you rather than sell it.",[82,1251,1252,1254],{},[106,1253,136],{}," is an invitation, not an instruction. It does not tell anyone what they may or may not do with your content, it only makes the content easier to consume. That is exactly why enabling it while also blocking AI crawlers is contradictory, and Bloggrify prints a warning at build time if you try to do both.",[82,1256,1257,1258,1260,1261,1264],{},"The format has picked up real momentum, and you will find it on plenty of sites, especially documentation. But its actual usefulness today is still speculative. No major AI provider has confirmed that its crawlers read ",[106,1259,136],{},", and Google has publicly compared it to the old ",[106,1262,1263],{},"keywords"," meta tag, which is not a flattering comparison. The one case that genuinely works is a human pasting your URL into a chat: the tool fetches the page, and clean markdown beats a page full of navigation every time.",[82,1266,1267],{},"For a documentation site, where structure is everything, that is a clear win. For a blog, where each post is already a clean, focused page, the gain is smaller. It costs you one tiny file. So enable it if the idea appeals to you, but do not expect traffic to appear because of it. It is proposed, it is standardised, and everyone gets to do what they like with it. Bloggrify simply gives you the switch.",[86,1269,1271],{"id":1270},"you-decide","You decide",[82,1273,1274],{},"None of this is Bloggrify taking a side in the AI debate. It is two independent switches with defaults that respect you:",[94,1276,1277,1291],{},[97,1278,1279,1282,1283,1286,1287,1290],{},[101,1280,1281],{},"Crawlers are allowed by default."," Flip ",[106,1284,1285],{},"allowCrawlers"," to ",[106,1288,1289],{},"false"," the day you decide otherwise, and the major vendors will honour it.",[97,1292,1293,1282,1298,1286,1301,1304],{},[101,1294,1295,1297],{},[106,1296,136],{}," is off by default.",[106,1299,1300],{},"llms",[106,1302,1303],{},"true"," if you want to publish a clean index, knowing it is an offer, not a guarantee.",[82,1306,1307,1308,1311,1312,145],{},"If you want to go deeper, both are documented in the ",[142,1309,1121],{"href":1119,"rel":1310},[306],", and indexing in search engines, which is a separate topic again, lives in the ",[142,1313,1316],{"href":1314,"rel":1315},"https:\u002F\u002Fbloggrify.com\u002Freference\u002Frobots",[306],"robots.txt reference",[82,1318,1319,1320,145],{},"Bloggrify is open source. You can find the project ",[142,1321,1323],{"href":304,"rel":1322},[306],"on GitHub",[940,1325,1326],{},"html pre.shiki code .sHqub, html code.shiki .sHqub{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#CA9EE6;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .srxfx, html code.shiki .srxfx{--shiki-light:#6182B8;--shiki-light-font-style:inherit;--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit}html pre.shiki code .s8bja, html code.shiki .s8bja{--shiki-light:#90A4AE;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .sdvfp, html code.shiki .sdvfp{--shiki-light:#39ADB5;--shiki-default:#949CBB;--shiki-dark:#E1E4E8}html pre.shiki code .sHJOX, html code.shiki .sHJOX{--shiki-light:#E53935;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .s1BmC, html code.shiki .s1BmC{--shiki-light:#39ADB5;--shiki-default:#81C8BE;--shiki-dark:#E1E4E8}html pre.shiki code .sbhg_, html code.shiki .sbhg_{--shiki-light:#FF5370;--shiki-default:#EF9F76;--shiki-dark:#79B8FF}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":321,"searchDepth":322,"depth":322,"links":1328},[1329,1330,1333],{"id":1023,"depth":322,"text":1024},{"id":1146,"depth":322,"text":1147,"children":1331},[1332],{"id":1245,"depth":440,"text":1246},{"id":1270,"depth":322,"text":1271},"2026-07-16","The major AI crawlers honour robots.txt, so blocking them is one line in Bloggrify. Whether you should, and what it actually protects, is another question.",{},"13",{"text":956,"minutes":1339,"time":1340,"words":1341},5.26,315600,1052,{"title":50,"description":1335},{"loc":51},[72,1345],"ai","PJpue7xrdDkLMBZt2kJY1h9V8c6xGcPeWfjmHWXVsM0",{"id":1348,"title":42,"alternates":76,"author":77,"body":1349,"categories":76,"comments":24,"cover":76,"date":1427,"description":1428,"draft":24,"extension":335,"hidden":24,"language":76,"layout":76,"links":76,"listed":24,"meta":1429,"navigation":337,"nocomments":24,"notoc":24,"pageid":1430,"path":43,"readingTime":1431,"redirect_to_domain":76,"redirect_to_full_url":76,"robots":76,"schemaOrg":76,"seo":1436,"sitemap":1437,"stem":44,"table_of_contents":24,"tags":1438,"__hash__":1439},"page\u002F2025\u002Fversion-3-0.md",{"type":79,"value":1350,"toc":1418},[1351,1354,1358,1362,1365,1369,1372,1376,1379,1383,1386,1389,1403,1405,1410],[82,1352,1353],{},"We're excited to announce the release of Bloggrify 3.0.0! This major release brings a CLI to manage your blog, a Nuxt UI integration, and moves the whole stack to Nuxt 4 and Nuxt Content 3.",[86,1355,1357],{"id":1356},"whats-new-in-300","What's New in 3.0.0",[1243,1359,1361],{"id":1360},"_1-cli-tools","1. CLI tools",[82,1363,1364],{},"Bloggrify now comes with a CLI tool to help you manage your blog. You can use it to create new posts, update existing ones, and more.",[1243,1366,1368],{"id":1367},"_2-nuxt-ui-integration","2. Nuxt UI integration",[82,1370,1371],{},"Bloggrify now comes with a Nuxt UI integration to help you create beautiful and modern UI for your blog.",[1243,1373,1375],{"id":1374},"_3-nuxt-4-and-nuxt-content-3-support","3. Nuxt 4 and Nuxt-Content 3 support",[82,1377,1378],{},"Bloggrify now comes with a Nuxt 4 and Nuxt-Content 3 support.",[1243,1380,1382],{"id":1381},"_4-author-pages","4. Author pages",[82,1384,1385],{},"Author pages are automatically generated based on the authors you define in your app.config.ts file.",[82,1387,1388],{},"And more...",[94,1390,1391,1394,1397,1400],{},[97,1392,1393],{},"Automatic og:image generation when cover is not provided",[97,1395,1396],{},"Use Search feature from nuxt-ui and Nuxt-Content",[97,1398,1399],{},"Improve RSS discovery",[97,1401,1402],{},"Improve performance using nuxt seo zeroRuntime option",[86,1404,298],{"id":297},[82,1406,301,1407,308],{},[142,1408,307],{"href":304,"rel":1409},[306],[94,1411,1412,1414,1416],{},[97,1413,313],{},[97,1415,316],{},[97,1417,319],{},{"title":321,"searchDepth":322,"depth":322,"links":1419},[1420,1426],{"id":1356,"depth":322,"text":1357,"children":1421},[1422,1423,1424,1425],{"id":1360,"depth":440,"text":1361},{"id":1367,"depth":440,"text":1368},{"id":1374,"depth":440,"text":1375},{"id":1381,"depth":440,"text":1382},{"id":297,"depth":322,"text":298},"2025-12-27","Major release with new CLI tools, nuxt ui integration, and more.",{},"12",{"text":1432,"minutes":1433,"time":1434,"words":1435},"1 min read",0.75,45000,150,{"title":42,"description":1428},{"loc":43},[347],"RaAzbC_ziNBVoKXYDgE_6zFJmcmtWCKDWEkngzq8J_8",{"id":1441,"title":38,"alternates":76,"author":77,"body":1442,"categories":76,"comments":24,"cover":76,"date":1710,"description":1711,"draft":24,"extension":335,"hidden":24,"language":76,"layout":76,"links":76,"listed":24,"meta":1712,"navigation":337,"nocomments":24,"notoc":24,"pageid":1713,"path":39,"readingTime":1714,"redirect_to_domain":76,"redirect_to_full_url":76,"robots":76,"schemaOrg":76,"seo":1718,"sitemap":1719,"stem":40,"table_of_contents":24,"tags":1720,"__hash__":1721},"page\u002F2025\u002Fversion-2-1.md",{"type":79,"value":1443,"toc":1702},[1444,1447,1451,1455,1458,1547,1567,1571,1574,1577,1655,1659,1662,1681,1684,1686,1691,1699],[82,1445,1446],{},"We're excited to announce the release of Bloggrify 2.1.0! This update improves existing features to enhance your blogging experience: shortcodes and built-in analytics integration.",[86,1448,1450],{"id":1449},"whats-new-in-210","What's New in 2.1.0",[1243,1452,1454],{"id":1453},"_1-shortcodes-simplify-complex-content","1. Shortcodes: Simplify Complex Content",[82,1456,1457],{},"Shortcodes provide an elegant way to insert complex elements into your Markdown content without writing lengthy HTML or Vue components.\nHere are the new shortcodes available in Bloggrify 2.1.0:",[94,1459,1460,1492,1518,1544],{},[97,1461,1462,1463],{},"youtube: Embed YouTube videos with a simple shortcode",[1464,1465,1466,1473],"mdd",{},[1467,1468,1469],"template",{"v-slot:preview":321},[1470,1471],"youtube",{"video-id":1472},"su2gNQJkteg",[1467,1474,1475,1483,1485],{"v-slot:markup":321},[377,1476,1479],{"className":1477,"code":321,"language":1478,"meta":321,"style":321},"language-markdown shiki shiki-themes material-theme-lighter catppuccin-frappe github-dark","markdown",[106,1480,1481],{"__ignoreMap":321},[385,1482],{"class":387,"line":388},[1470,1484],{"video-id":1472},[377,1486,1490],{"className":1487,"code":321,"language":1489},[1488],"language-text","text",[106,1491,321],{"__ignoreMap":321},[97,1493,1494,1495],{},"X: Embed tweets directly in your content",[1464,1496,1497,1503],{},[1467,1498,1499],{"v-slot:preview":321},[1500,1501],"x",{"tweet-id":1502},"1750435525071159309",[1467,1504,1505,1511,1513],{"v-slot:markup":321},[377,1506,1507],{"className":1477,"code":321,"language":1478,"meta":321,"style":321},[106,1508,1509],{"__ignoreMap":321},[385,1510],{"class":387,"line":388},[1500,1512],{"tweet-id":1502},[377,1514,1516],{"className":1515,"code":321,"language":1489},[1488],[106,1517,321],{"__ignoreMap":321},[97,1519,1520,1521],{},"instagram: Display Instagram posts with ease",[1464,1522,1523,1529],{},[1467,1524,1525],{"v-slot:preview":321},[1526,1527],"instagram",{"post-id":1528},"CxOWiQNP2MO",[1467,1530,1531,1537,1539],{"v-slot:markup":321},[377,1532,1533],{"className":1477,"code":321,"language":1478,"meta":321,"style":321},[106,1534,1535],{"__ignoreMap":321},[385,1536],{"class":387,"line":388},[1526,1538],{"post-id":1528},[377,1540,1542],{"className":1541,"code":321,"language":1489},[1488],[106,1543,321],{"__ignoreMap":321},[97,1545,1546],{},"vimeo: Add Vimeo videos to your blog posts",[1464,1548,1549,1555],{},[1467,1550,1551],{"v-slot:preview":321},[1552,1553],"vimeo",{"video-id":1554},"55073825",[1467,1556,1557],{"v-slot:markup":321},[377,1558,1560],{"className":1477,"code":1559,"language":1478,"meta":321,"style":321},":Vimeo{videoId=\"55073825\"}\n\n",[106,1561,1562],{"__ignoreMap":321},[385,1563,1564],{"class":387,"line":388},[385,1565,1566],{"class":420},":Vimeo{videoId=\"55073825\"}\n",[1243,1568,1570],{"id":1569},"_2-analytics-integration","2. Analytics Integration",[82,1572,1573],{},"Umami has been added as a new analytics provider in Bloggrify 2.1.0.",[82,1575,1576],{},"You can now use it alongside Google Analytics, Hakanai Pulse, Fathom, Pirsch, and Plausible to track your blog's performance.",[377,1578,1582],{"className":1579,"code":1580,"language":1581,"meta":321,"style":321},"language-ts shiki shiki-themes material-theme-lighter catppuccin-frappe github-dark","\u002F\u002F app.config.ts\nanalytics: {\n    providers: [ {\n        provider: 'umami',\n        code: 'YOUR_TRACKING_CODE'\n    }]\n }\n","ts",[106,1583,1584,1590,1600,1612,1628,1643,1651],{"__ignoreMap":321},[385,1585,1586],{"class":387,"line":388},[385,1587,1589],{"class":1588},"sRX2Q","\u002F\u002F app.config.ts\n",[385,1591,1592,1596,1598],{"class":387,"line":322},[385,1593,1595],{"class":1594},"ss2FP","analytics",[385,1597,308],{"class":395},[385,1599,749],{"class":395},[385,1601,1602,1605,1607,1610],{"class":387,"line":440},[385,1603,1604],{"class":1594},"    providers",[385,1606,308],{"class":395},[385,1608,1609],{"class":474}," [ ",[385,1611,765],{"class":395},[385,1613,1614,1617,1619,1621,1624,1626],{"class":387,"line":468},[385,1615,1616],{"class":474},"        provider",[385,1618,308],{"class":478},[385,1620,833],{"class":426},[385,1622,1623],{"class":430},"umami",[385,1625,434],{"class":426},[385,1627,437],{"class":395},[385,1629,1630,1633,1635,1637,1640],{"class":387,"line":488},[385,1631,1632],{"class":474},"        code",[385,1634,308],{"class":478},[385,1636,833],{"class":426},[385,1638,1639],{"class":430},"YOUR_TRACKING_CODE",[385,1641,1642],{"class":426},"'\n",[385,1644,1645,1648],{"class":387,"line":775},[385,1646,1647],{"class":395},"    }",[385,1649,1650],{"class":474},"]\n",[385,1652,1653],{"class":387,"line":781},[385,1654,485],{"class":395},[86,1656,1658],{"id":1657},"upgrading-to-210","Upgrading to 2.1.0",[82,1660,1661],{},"Upgrading to Bloggrify 2.1.0 is straightforward:",[377,1663,1667],{"className":1664,"code":1665,"language":1666,"meta":321,"style":321},"language-bash shiki shiki-themes material-theme-lighter catppuccin-frappe github-dark","npm install bloggrify@latest\n","bash",[106,1668,1669],{"__ignoreMap":321},[385,1670,1671,1675,1678],{"class":387,"line":388},[385,1672,1674],{"class":1673},"sAGAT","npm",[385,1676,1677],{"class":430}," install",[385,1679,1680],{"class":430}," bloggrify@latest\n",[82,1682,1683],{},"For existing projects, no configuration changes are required unless you want to use the new features.",[86,1685,298],{"id":297},[82,1687,301,1688,308],{},[142,1689,307],{"href":304,"rel":1690},[306],[94,1692,1693,1695,1697],{},[97,1694,313],{},[97,1696,316],{},[97,1698,319],{},[940,1700,1701],{},"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);}html pre.shiki code .s8bja, html code.shiki .s8bja{--shiki-light:#90A4AE;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .sRX2Q, html code.shiki .sRX2Q{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#949CBB;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .ss2FP, html code.shiki .ss2FP{--shiki-light:#E2931D;--shiki-default:#C6D0F5;--shiki-dark:#B392F0}html pre.shiki code .sdvfp, html code.shiki .sdvfp{--shiki-light:#39ADB5;--shiki-default:#949CBB;--shiki-dark:#E1E4E8}html pre.shiki code .sHJOX, html code.shiki .sHJOX{--shiki-light:#E53935;--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8}html pre.shiki code .s1BmC, html code.shiki .s1BmC{--shiki-light:#39ADB5;--shiki-default:#81C8BE;--shiki-dark:#E1E4E8}html pre.shiki code .srOHQ, html code.shiki .srOHQ{--shiki-light:#39ADB5;--shiki-default:#A6D189;--shiki-dark:#9ECBFF}html pre.shiki code .sw2QF, html code.shiki .sw2QF{--shiki-light:#91B859;--shiki-default:#A6D189;--shiki-dark:#9ECBFF}html pre.shiki code .sAGAT, html code.shiki .sAGAT{--shiki-light:#E2931D;--shiki-light-font-style:inherit;--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit}",{"title":321,"searchDepth":322,"depth":322,"links":1703},[1704,1708,1709],{"id":1449,"depth":322,"text":1450,"children":1705},[1706,1707],{"id":1453,"depth":440,"text":1454},{"id":1569,"depth":440,"text":1570},{"id":1657,"depth":322,"text":1658},{"id":297,"depth":322,"text":298},"2025-01-25","Minor release with new shortcodes and Umami analytics integration. ",{},"5",{"text":1432,"minutes":1715,"time":1716,"words":1717},0.81,48600,162,{"title":38,"description":1711},{"loc":39},[347],"B_Jd1wPYwVldF5VHyY14Xp-dxdN7gy_LImjmFCBIiZg",1784539639611]