[{"data":1,"prerenderedAt":693},["ShallowReactive",2],{"navigation":3,"page-projects,david-poupon":55},[4,8,12,16,51],{"title":5,"path":6,"stem":7},"Vivian SARAZIN","\u002F","1.index",{"title":9,"path":10,"stem":11},"AI","\u002Fai","ai",{"title":13,"path":14,"stem":15},"Misc","\u002Fmisc","misc",{"title":17,"path":18,"stem":19,"children":20},"Projects","\u002Fprojects","projects",[21,23,27,31,35,39,43,47],{"title":17,"path":18,"stem":22},"projects\u002Findex",{"title":24,"path":25,"stem":26},"David Poupon","\u002Fprojects\u002Fdavid-poupon","projects\u002Fdavid-poupon",{"title":28,"path":29,"stem":30},"Groupe Nomblot","\u002Fprojects\u002Fgroupe-nomblot","projects\u002Fgroupe-nomblot",{"title":32,"path":33,"stem":34},"My Grandmother's Recipe Notebooks","\u002Fprojects\u002Fles-cahiers-de-jeanine","projects\u002Fles-cahiers-de-jeanine",{"title":36,"path":37,"stem":38},"TrialFinder by OmiCure","\u002Fprojects\u002Fomicure","projects\u002Fomicure",{"title":40,"path":41,"stem":42},"PME Partner","\u002Fprojects\u002Fpme-partner","projects\u002Fpme-partner",{"title":44,"path":45,"stem":46},"Radiofrance","\u002Fprojects\u002Fradiofrance","projects\u002Fradiofrance",{"title":48,"path":49,"stem":50},"Solinum","\u002Fprojects\u002Fsolinum","projects\u002Fsolinum",{"title":52,"path":53,"stem":54},"Resume","\u002Fresume","resume",{"id":56,"title":24,"body":57,"description":683,"extension":684,"layout":685,"meta":686,"navigation":690,"path":25,"seo":691,"stem":26,"__hash__":692},"content\u002Fprojects\u002Fdavid-poupon.md",{"type":58,"value":59,"toc":672},"minimark",[60,67,72,76,86,89,92,95,98,101,106,109,112,115,118,127,130,135,138,210,214,221,333,337,344,617,620,623,627,631,634,637,640,649,653,656,659,662,665,668],[61,62,63],"p",{},[64,65,66],"em",{},"At Hublo, we work with SvelteKit. Before starting my new job, I had to learn this framework.",[61,68,69],{},[64,70,71],{},"One of the best ways to do so, is by creating a small project. IMO, the smaller, the better!",[73,74,24],"h1",{"id":75},"david-poupon",[61,77,78,79,85],{},"I had a chance to meet ",[80,81,24],"a",{"href":82,"rel":83},"https:\u002F\u002Fwww.poupon-paysage.fr",[84],"nofollow"," a talented trimmer, starting his own company.",[61,87,88],{},"As a solo entrepreneur, David needed a website to showcase his work and provide his contact informations.",[61,90,91],{},"To help ourselves, I proposed to create this pro-bono website.",[61,93,94],{},"The main objective for David is to rank well on Google.",[61,96,97],{},"As you can expect, I just received a logo, a phone number and a few pictures.",[61,99,100],{},"But it's OK, I had some details to start a minimal project.",[102,103,105],"h2",{"id":104},"images-in-sveltekit","Images in SvelteKit",[61,107,108],{},"An interesting part of this project was managing the images.",[61,110,111],{},"Obviously, David didn't hear about Web Vitals, image compression, Google Lighthouse and all of this.",[61,113,114],{},"David sent me a load of very large pictures to display on this website.",[61,116,117],{},"As a lazy developer, I wanted to find a way to resize images directly on the SvelteKit's server, and then, display an optimized image to the client.",[61,119,120,121,126],{},"And here comes ",[80,122,125],{"href":123,"rel":124},"https:\u002F\u002Fsvelte.dev\u002Fdocs\u002Fkit\u002Fimages#sveltejs-enhanced-img",[84],"@sveltejs\u002Fenhanced-img",".",[61,128,129],{},"By leveraging Vite's assets handling features, SvelteKit provides a great DX.",[131,132,134],"h3",{"id":133},"importing-images","Importing images",[61,136,137],{},"You just need to import your images with some params (see the query):",[139,140,145],"pre",{"className":141,"code":142,"language":143,"meta":144,"style":144},"language-svelte shiki shiki-themes github-dark github-light","\u003Cscript lang=\"ts\">\n    let { data } = $props();\n    const imageModules = Object.entries(\n        import.meta.glob(`$lib\u002Fassets\u002Fportfolio\u002F*.jpg`, {\n            eager: true,\n            \u002F** this query optimizes the import *\u002F\n            query: { enhanced: true, w: '1280;640;400' }\n        })\n    ).filter(([k]) => k.includes(data.portfolio.id));\n\u003C\u002Fscript>\n","svelte","",[146,147,148,156,162,168,174,180,186,192,198,204],"code",{"__ignoreMap":144},[149,150,153],"span",{"class":151,"line":152},"line",1,[149,154,155],{},"\u003Cscript lang=\"ts\">\n",[149,157,159],{"class":151,"line":158},2,[149,160,161],{},"    let { data } = $props();\n",[149,163,165],{"class":151,"line":164},3,[149,166,167],{},"    const imageModules = Object.entries(\n",[149,169,171],{"class":151,"line":170},4,[149,172,173],{},"        import.meta.glob(`$lib\u002Fassets\u002Fportfolio\u002F*.jpg`, {\n",[149,175,177],{"class":151,"line":176},5,[149,178,179],{},"            eager: true,\n",[149,181,183],{"class":151,"line":182},6,[149,184,185],{},"            \u002F** this query optimizes the import *\u002F\n",[149,187,189],{"class":151,"line":188},7,[149,190,191],{},"            query: { enhanced: true, w: '1280;640;400' }\n",[149,193,195],{"class":151,"line":194},8,[149,196,197],{},"        })\n",[149,199,201],{"class":151,"line":200},9,[149,202,203],{},"    ).filter(([k]) => k.includes(data.portfolio.id));\n",[149,205,207],{"class":151,"line":206},10,[149,208,209],{},"\u003C\u002Fscript>\n",[131,211,213],{"id":212},"display-images","Display images",[61,215,216,217,220],{},"Thus, inside your Svelte template, you loop over the imported images with the dedicated ",[146,218,219],{},"enhanced:img"," tag:",[139,222,226],{"className":223,"code":224,"language":225,"meta":144,"style":144},"language-html shiki shiki-themes github-dark github-light","\u003Cdiv class=\"my-4 grid grid-cols-2 gap-4 md:px-64\">\n  {#each imageModules as [_, module], i}\n  \u003Cenhanced:img\n    src=\"{module.default}\"\n    alt=\"{`${data.portfolio?.title}\"\n    -\n    ${i}`}\n    sizes=\"(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px\"\n  \u002F>\n  \u003C!-- sizes can be optimized, do your tests!  -->\n  {\u002Feach}\n\u003C\u002Fdiv>\n","html",[146,227,228,252,257,266,276,286,291,296,306,311,317,323],{"__ignoreMap":144},[149,229,230,234,238,242,245,249],{"class":151,"line":152},[149,231,233],{"class":232},"sQ3_J","\u003C",[149,235,237],{"class":236},"sZkSk","div",[149,239,241],{"class":240},"s-Z4r"," class",[149,243,244],{"class":232},"=",[149,246,248],{"class":247},"sg6BJ","\"my-4 grid grid-cols-2 gap-4 md:px-64\"",[149,250,251],{"class":232},">\n",[149,253,254],{"class":151,"line":158},[149,255,256],{"class":232},"  {#each imageModules as [_, module], i}\n",[149,258,259,262],{"class":151,"line":164},[149,260,261],{"class":232},"  \u003C",[149,263,265],{"class":264},"seUEM","enhanced:img\n",[149,267,268,271,273],{"class":151,"line":170},[149,269,270],{"class":240},"    src",[149,272,244],{"class":232},[149,274,275],{"class":247},"\"{module.default}\"\n",[149,277,278,281,283],{"class":151,"line":176},[149,279,280],{"class":240},"    alt",[149,282,244],{"class":232},[149,284,285],{"class":247},"\"{`${data.portfolio?.title}\"\n",[149,287,288],{"class":151,"line":182},[149,289,290],{"class":240},"    -\n",[149,292,293],{"class":151,"line":188},[149,294,295],{"class":240},"    ${i}`}\n",[149,297,298,301,303],{"class":151,"line":194},[149,299,300],{"class":240},"    sizes",[149,302,244],{"class":232},[149,304,305],{"class":247},"\"(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px\"\n",[149,307,308],{"class":151,"line":200},[149,309,310],{"class":232},"  \u002F>\n",[149,312,313],{"class":151,"line":206},[149,314,316],{"class":315},"sryI4","  \u003C!-- sizes can be optimized, do your tests!  -->\n",[149,318,320],{"class":151,"line":319},11,[149,321,322],{"class":232},"  {\u002Feach}\n",[149,324,326,329,331],{"class":151,"line":325},12,[149,327,328],{"class":232},"\u003C\u002F",[149,330,237],{"class":236},[149,332,251],{"class":232},[131,334,336],{"id":335},"the-output","The output",[61,338,339,340,343],{},"The output is an HTML ",[146,341,342],{},"\u003Cpicture>"," element with multiple formats like avif, webp, and jpeg:",[139,345,347],{"className":223,"code":346,"language":225,"meta":144,"style":144},"\u003Cpicture>\n  \u003C!-- avif -->\n  \u003Csource\n    sizes=\"(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px\"\n    srcset=\"\n      https:\u002F\u002Fwww.smthg\u002F-01.DpBnrOf3.avif 1280w,\n      https:\u002F\u002Fwww.smthg\u002F-01.giEScqK7.avif  640w,\n      https:\u002F\u002Fwww.smthg\u002F-01.CBDzHDjx.avif  400w\n    \"\n    type=\"image\u002Favif\" \u002F>\n  \u003C!-- webp -->\n  \u003Csource\n    sizes=\"(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px\"\n    srcset=\"\n      https:\u002F\u002Fwww.smthg\u002F-01.D1yYNfb1.webp 1280w,\n      https:\u002F\u002Fwww.smthg\u002F-01.C2vF8U-Q.webp  640w,\n      https:\u002F\u002Fwww.smthg\u002F-01.DeTegKll.webp  400w\n    \"\n    type=\"image\u002Fwebp\" \u002F>\n  \u003C!-- jpeg -->\n  \u003Csource\n    sizes=\"(min-width:1920px) 1280px, (min-width:1080px) 640px, (min-width:768px) 400px\"\n    srcset=\"\n      https:\u002F\u002Fwww.smthg\u002F-01.BaYrOgC0.jpeg 1280w,\n      https:\u002F\u002Fwww.smthg\u002F-01.CyzWffte.jpeg  640w,\n      https:\u002F\u002Fwww.smthg\u002F-01.DQ1OFJ6d.jpeg  400w\n    \"\n    type=\"image\u002Fjpeg\" \u002F>\n  \u003C!-- fallback -->\n  \u003Cimg\n    src=\"https:\u002F\u002Fwww.smthg\u002F-01.BaYrOgC0.jpeg\"\n    alt=\"Débroussaillage - 0\"\n    width=\"1280\"\n    height=\"1707\"\n\u002F>\u003C\u002Fpicture>\n",[146,348,349,358,363,370,378,388,393,398,403,408,421,426,432,441,450,456,462,468,473,485,491,498,507,516,522,528,534,539,551,557,565,575,585,596,607],{"__ignoreMap":144},[149,350,351,353,356],{"class":151,"line":152},[149,352,233],{"class":232},[149,354,355],{"class":236},"picture",[149,357,251],{"class":232},[149,359,360],{"class":151,"line":158},[149,361,362],{"class":315},"  \u003C!-- avif -->\n",[149,364,365,367],{"class":151,"line":164},[149,366,261],{"class":232},[149,368,369],{"class":236},"source\n",[149,371,372,374,376],{"class":151,"line":170},[149,373,300],{"class":240},[149,375,244],{"class":232},[149,377,305],{"class":247},[149,379,380,383,385],{"class":151,"line":176},[149,381,382],{"class":240},"    srcset",[149,384,244],{"class":232},[149,386,387],{"class":247},"\"\n",[149,389,390],{"class":151,"line":182},[149,391,392],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.DpBnrOf3.avif 1280w,\n",[149,394,395],{"class":151,"line":188},[149,396,397],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.giEScqK7.avif  640w,\n",[149,399,400],{"class":151,"line":194},[149,401,402],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.CBDzHDjx.avif  400w\n",[149,404,405],{"class":151,"line":200},[149,406,407],{"class":247},"    \"\n",[149,409,410,413,415,418],{"class":151,"line":206},[149,411,412],{"class":240},"    type",[149,414,244],{"class":232},[149,416,417],{"class":247},"\"image\u002Favif\"",[149,419,420],{"class":232}," \u002F>\n",[149,422,423],{"class":151,"line":319},[149,424,425],{"class":315},"  \u003C!-- webp -->\n",[149,427,428,430],{"class":151,"line":325},[149,429,261],{"class":232},[149,431,369],{"class":236},[149,433,435,437,439],{"class":151,"line":434},13,[149,436,300],{"class":240},[149,438,244],{"class":232},[149,440,305],{"class":247},[149,442,444,446,448],{"class":151,"line":443},14,[149,445,382],{"class":240},[149,447,244],{"class":232},[149,449,387],{"class":247},[149,451,453],{"class":151,"line":452},15,[149,454,455],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.D1yYNfb1.webp 1280w,\n",[149,457,459],{"class":151,"line":458},16,[149,460,461],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.C2vF8U-Q.webp  640w,\n",[149,463,465],{"class":151,"line":464},17,[149,466,467],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.DeTegKll.webp  400w\n",[149,469,471],{"class":151,"line":470},18,[149,472,407],{"class":247},[149,474,476,478,480,483],{"class":151,"line":475},19,[149,477,412],{"class":240},[149,479,244],{"class":232},[149,481,482],{"class":247},"\"image\u002Fwebp\"",[149,484,420],{"class":232},[149,486,488],{"class":151,"line":487},20,[149,489,490],{"class":315},"  \u003C!-- jpeg -->\n",[149,492,494,496],{"class":151,"line":493},21,[149,495,261],{"class":232},[149,497,369],{"class":236},[149,499,501,503,505],{"class":151,"line":500},22,[149,502,300],{"class":240},[149,504,244],{"class":232},[149,506,305],{"class":247},[149,508,510,512,514],{"class":151,"line":509},23,[149,511,382],{"class":240},[149,513,244],{"class":232},[149,515,387],{"class":247},[149,517,519],{"class":151,"line":518},24,[149,520,521],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.BaYrOgC0.jpeg 1280w,\n",[149,523,525],{"class":151,"line":524},25,[149,526,527],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.CyzWffte.jpeg  640w,\n",[149,529,531],{"class":151,"line":530},26,[149,532,533],{"class":247},"      https:\u002F\u002Fwww.smthg\u002F-01.DQ1OFJ6d.jpeg  400w\n",[149,535,537],{"class":151,"line":536},27,[149,538,407],{"class":247},[149,540,542,544,546,549],{"class":151,"line":541},28,[149,543,412],{"class":240},[149,545,244],{"class":232},[149,547,548],{"class":247},"\"image\u002Fjpeg\"",[149,550,420],{"class":232},[149,552,554],{"class":151,"line":553},29,[149,555,556],{"class":315},"  \u003C!-- fallback -->\n",[149,558,560,562],{"class":151,"line":559},30,[149,561,261],{"class":232},[149,563,564],{"class":236},"img\n",[149,566,568,570,572],{"class":151,"line":567},31,[149,569,270],{"class":240},[149,571,244],{"class":232},[149,573,574],{"class":247},"\"https:\u002F\u002Fwww.smthg\u002F-01.BaYrOgC0.jpeg\"\n",[149,576,578,580,582],{"class":151,"line":577},32,[149,579,280],{"class":240},[149,581,244],{"class":232},[149,583,584],{"class":247},"\"Débroussaillage - 0\"\n",[149,586,588,591,593],{"class":151,"line":587},33,[149,589,590],{"class":240},"    width",[149,592,244],{"class":232},[149,594,595],{"class":247},"\"1280\"\n",[149,597,599,602,604],{"class":151,"line":598},34,[149,600,601],{"class":240},"    height",[149,603,244],{"class":232},[149,605,606],{"class":247},"\"1707\"\n",[149,608,610,613,615],{"class":151,"line":609},35,[149,611,612],{"class":232},"\u002F>\u003C\u002F",[149,614,355],{"class":236},[149,616,251],{"class":232},[61,618,619],{},"This ensures the client’s device chooses the best format and size, improving performance and loading times.",[61,621,622],{},"However, this add a step on the build part which is not a problem for a solo entrepreneur website, but can lead to a quite long build on a big project.",[102,624,626],{"id":625},"developer-experience","Developer Experience",[131,628,630],{"id":629},"deployments","Deployments",[61,632,633],{},"Deployments are not my favorite stuffs. But it's an important part of our job.",[61,635,636],{},"I basically start a Vercel project, connected my repo and the domain name and it worked like a charm.",[61,638,639],{},"For this kind of micro-websites, Vercel is an excellent choice.",[61,641,642,643,648],{},"SvelteKit offers a wide range of ",[80,644,647],{"href":645,"rel":646},"https:\u002F\u002Fsvelte.dev\u002Fdocs\u002Fkit\u002Fadapters",[84],"adapters"," if you want to deploy elsewhere.",[131,650,652],{"id":651},"overall","Overall",[61,654,655],{},"Doing this website was fast and pretty pleasant, since Svelte is made on the top of Web Standards, any developer can easily start something in minutes.",[61,657,658],{},"The tooling is quite nice, and the Svelte's compiler warnings is a brillant idea.",[61,660,661],{},"Thanks to this, I corrected some markups mistakes before getting these errors in Google Lighthouse.",[663,664],"hr",{},[61,666,667],{},"This project was a great learning experience and a fantastic introduction to SvelteKit.",[669,670,671],"style",{},"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 .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 pre.shiki code .sQ3_J, html code.shiki .sQ3_J{--shiki-dark:#E1E4E8;--shiki-default:#24292E}html pre.shiki code .sZkSk, html code.shiki .sZkSk{--shiki-dark:#85E89D;--shiki-default:#22863A}html pre.shiki code .s-Z4r, html code.shiki .s-Z4r{--shiki-dark:#B392F0;--shiki-default:#6F42C1}html pre.shiki code .sg6BJ, html code.shiki .sg6BJ{--shiki-dark:#9ECBFF;--shiki-default:#032F62}html pre.shiki code .seUEM, html code.shiki .seUEM{--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic;--shiki-default:#B31D28;--shiki-default-font-style:italic}html pre.shiki code .sryI4, html code.shiki .sryI4{--shiki-dark:#6A737D;--shiki-default:#6A737D}",{"title":144,"searchDepth":158,"depth":158,"links":673},[674,679],{"id":104,"depth":158,"text":105,"children":675},[676,677,678],{"id":133,"depth":164,"text":134},{"id":212,"depth":164,"text":213},{"id":335,"depth":164,"text":336},{"id":625,"depth":158,"text":626,"children":680},[681,682],{"id":629,"depth":164,"text":630},{"id":651,"depth":164,"text":652},"My very first website with SvelteKit","md",null,{"stack":687},[688,689],"SvelteKit","Vercel",true,{"title":24,"description":683},"cZJLktuUMhCvf5HeWTT-Z2NUXDfxztYrF7gGWkcux94",1785077665219]