[{"data":1,"prerenderedAt":67},["ShallowReactive",2],{"posts:all":3},[4,13,20,28,36,44,52,59],{"id":5,"title":6,"description":7,"date":8,"draft":9,"path":10,"stem":11,"readingTime":12},"posts\u002Fblog\u002Fworkbox-astro-project.md","Integrate Workbox Service Worker into Astro Project","Add a Workbox service worker to an Astro project. Generate the worker in the build, precache the static assets, pick runtime caching rules, and register it.","2023-02-17",false,"\u002Fblog\u002Fworkbox-astro-project","blog\u002Fworkbox-astro-project","8 min read",{"id":14,"title":15,"description":16,"date":17,"draft":9,"path":18,"stem":19,"readingTime":12},"posts\u002Fblog\u002Fnginx-brotli-gzip-compression-docker.md","Add Brotli and Gzip compression to nginx in Docker","Add Brotli and Gzip compression to nginx inside Docker. Build the ngx_brotli module into the image, set the levels and MIME types, then check the headers.","2022-11-27","\u002Fblog\u002Fnginx-brotli-gzip-compression-docker","blog\u002Fnginx-brotli-gzip-compression-docker",{"id":21,"title":22,"description":23,"date":24,"draft":9,"path":25,"stem":26,"readingTime":27},"posts\u002Fblog\u002Fopen-graph-images-using-satori.md","Dynamic OG images using Satori and Astro Server Endpoints","Generate an Open Graph image per page with Satori and an Astro server endpoint. Write the card as JSX, load the font, render it to SVG, then convert the SVG to a PNG.","2022-11-15","\u002Fblog\u002Fopen-graph-images-using-satori","blog\u002Fopen-graph-images-using-satori","11 min read",{"id":29,"title":30,"description":31,"date":32,"draft":9,"path":33,"stem":34,"readingTime":35},"posts\u002Fblog\u002Fvite-env-index-html.md","Inject Environment Variables into index.html file in Vite","Inject environment variables into index.html in Vite. Compare the built-in %VITE_% replacement, a transformIndexHtml plugin, and an HTML template plugin at build time.","2022-10-17","\u002Fblog\u002Fvite-env-index-html","blog\u002Fvite-env-index-html","4 min read",{"id":37,"title":38,"description":39,"date":40,"draft":9,"path":41,"stem":42,"readingTime":43},"posts\u002Fblog\u002Fusing-slots-in-vue.md","Slots and Scoped Slots in Vue.js","Slots let a parent decide what a Vue component renders, and scoped slots pass data back so the parent can render it. A worked example builds a renderless submit button.","2021-09-12","\u002Fblog\u002Fusing-slots-in-vue","blog\u002Fusing-slots-in-vue","5 min read",{"id":45,"title":46,"description":47,"date":48,"draft":9,"path":49,"stem":50,"readingTime":51},"posts\u002Fblog\u002Furl-search-params.md","Cleaner way of dealing with query params using URLSearchParams","Build and read query strings with URLSearchParams instead of joining strings by hand. Turn an object into a query, parse one back, and let the browser handle the escaping.","2021-08-20","\u002Fblog\u002Furl-search-params","blog\u002Furl-search-params","3 min read",{"id":53,"title":54,"description":55,"date":56,"draft":9,"path":57,"stem":58,"readingTime":35},"posts\u002Fblog\u002Fdynamic-font-loading.md","Dynamic font loading with FontFace","Load a web font on demand with the CSS Font Loading API. Build a FontFace in JavaScript, await its load, add it to document.fonts, and skip the fonts a page never shows.","2021-08-11","\u002Fblog\u002Fdynamic-font-loading","blog\u002Fdynamic-font-loading",{"id":60,"title":61,"description":62,"date":63,"draft":9,"path":64,"stem":65,"readingTime":66},"posts\u002Fblog\u002Fhello-world.md","Hello World","The first post on this blog. Rumaan writes about solving problems on the web, how-to guides for current front-end frameworks, and whatever else is worth a note.","2021-08-05","\u002Fblog\u002Fhello-world","blog\u002Fhello-world","1 min read",1788101291944]