From 703d1d7f08c7268b25242cb4299b09f9b8242b2b Mon Sep 17 00:00:00 2001 From: nico Date: Sun, 29 Dec 2024 23:54:33 +0100 Subject: [PATCH] cleanup and refactor i18n + code --- .astro/content-modules.mjs | 10 +- .astro/data-store.json | 2 +- astro.config.mjs | 43 ++++--- bun.lockb | Bin 221901 -> 222308 bytes package.json | 1 + src/components/EditorialContent.astro | 2 - src/components/MetaDate.astro | 14 +- src/content/fragments/fr/visited-links.md | 2 +- src/i18n/en.json | 68 ---------- src/i18n/fr.json | 68 ---------- src/i18n/ui.ts | 150 ---------------------- src/pages/articles/[id].astro | 39 ++---- src/pages/articles/i18n/en.json | 4 - src/pages/articles/i18n/fr.json | 4 - src/pages/articles/index.astro | 59 +++++---- src/pages/fragments/[id].astro | 39 ++---- src/pages/fragments/i18n/en.json | 4 - src/pages/fragments/i18n/fr.json | 4 - src/pages/fragments/index.astro | 59 +++++---- src/pages/i18n/en.json | 15 --- src/pages/i18n/fr.json | 15 --- src/pages/references/i18n/en.json | 4 - src/pages/references/i18n/fr.json | 4 - src/pages/references/index.astro | 40 ++---- src/pages/veille/i18n/en.json | 4 - src/pages/veille/i18n/fr.json | 4 - src/pages/veille/index.astro | 41 +++--- src/styles/global/global-styles.css | 60 ++++++--- 28 files changed, 206 insertions(+), 553 deletions(-) delete mode 100755 src/i18n/en.json delete mode 100755 src/i18n/fr.json delete mode 100644 src/i18n/ui.ts delete mode 100755 src/pages/articles/i18n/en.json delete mode 100755 src/pages/articles/i18n/fr.json delete mode 100755 src/pages/fragments/i18n/en.json delete mode 100755 src/pages/fragments/i18n/fr.json delete mode 100755 src/pages/i18n/en.json delete mode 100755 src/pages/i18n/fr.json delete mode 100755 src/pages/references/i18n/en.json delete mode 100755 src/pages/references/i18n/fr.json delete mode 100755 src/pages/veille/i18n/en.json delete mode 100755 src/pages/veille/i18n/fr.json diff --git a/.astro/content-modules.mjs b/.astro/content-modules.mjs index c4a699e..4169cc6 100644 --- a/.astro/content-modules.mjs +++ b/.astro/content-modules.mjs @@ -4,11 +4,11 @@ export default new Map([ ["src/content/articles/en/sci-hub-blocage.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Fen%2Fsci-hub-blocage.mdx&astroContentModuleFlag=true")], ["src/content/articles/en/the-day-I-jamd.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Fen%2Fthe-day-I-jamd.mdx&astroContentModuleFlag=true")], ["src/content/articles/en/video-compression.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Fen%2Fvideo-compression.mdx&astroContentModuleFlag=true")], -["src/content/fragments/en/image-full.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Fen%2Fimage-full.mdx&astroContentModuleFlag=true")], -["src/content/fragments/en/super-cookies.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Fen%2Fsuper-cookies.mdx&astroContentModuleFlag=true")], -["src/content/articles/fr/sci-hub-blocage.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Ffr%2Fsci-hub-blocage.mdx&astroContentModuleFlag=true")], ["src/content/fragments/fr/buttons.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Ffr%2Fbuttons.mdx&astroContentModuleFlag=true")], ["src/content/fragments/fr/image-full.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Ffr%2Fimage-full.mdx&astroContentModuleFlag=true")], -["src/content/articles/fr/the-day-I-jamd.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Ffr%2Fthe-day-I-jamd.mdx&astroContentModuleFlag=true")], -["src/content/fragments/fr/super-cookies.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Ffr%2Fsuper-cookies.mdx&astroContentModuleFlag=true")]]); +["src/content/fragments/fr/super-cookies.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Ffr%2Fsuper-cookies.mdx&astroContentModuleFlag=true")], +["src/content/articles/fr/sci-hub-blocage.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Ffr%2Fsci-hub-blocage.mdx&astroContentModuleFlag=true")], +["src/content/fragments/en/image-full.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Fen%2Fimage-full.mdx&astroContentModuleFlag=true")], +["src/content/fragments/en/super-cookies.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Ffragments%2Fen%2Fsuper-cookies.mdx&astroContentModuleFlag=true")], +["src/content/articles/fr/the-day-I-jamd.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Farticles%2Ffr%2Fthe-day-I-jamd.mdx&astroContentModuleFlag=true")]]); \ No newline at end of file diff --git a/.astro/data-store.json b/.astro/data-store.json index e65e8a3..4c7de64 100644 --- a/.astro/data-store.json +++ b/.astro/data-store.json @@ -1 +1 @@ -[["Map",1,2,9,10,61,62,427,428,888,889,998,999],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.1.1","content-config-digest","8021b3469f132349","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://www.nardu.in\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[\"assets.nardu.in\"],\"remotePatterns\":[{\"protocol\":\"https\"}]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":\"shiki\",\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"i18n\":{\"defaultLocale\":\"fr\",\"locales\":[\"fr\",\"en\"],\"routing\":{\"prefixDefaultLocale\":false,\"redirectToDefaultLocale\":true,\"fallbackType\":\"redirect\"}},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false},\"legacy\":{\"collections\":false}}","references",["Map",11,12,25,26,39,40,50,51],"3w",{"id":11,"data":13,"filePath":21,"digest":22,"rendered":23},{"title":11,"subtitle":14,"url":15,"lang":16,"slug":11,"tags":17,"createdAt":20},"J'ai fait de la doc!","https://3-w.fr","fr",[18,19],"Front-end","documentation",["Date","2022-10-19T18:02:00.000Z"],"src/content/references/3w.md","0d3d94c8af754e1b",{"html":24},"","natureo",{"id":25,"data":27,"filePath":36,"digest":37,"rendered":38},{"title":28,"subtitle":29,"url":30,"lang":16,"slug":25,"tags":31,"createdAt":35},"Nature en Occitanie","La sobriété au naturel.","https://www.natureo.org/",[18,32,33,34],"accessibilité","éco-conception","CMS",["Date","2023-04-19T18:02:00.000Z"],"src/content/references/natureo.md","6a7169b855b57024",{"html":24},"parole-expression",{"id":39,"data":41,"filePath":47,"digest":48,"rendered":49},{"title":42,"subtitle":43,"url":44,"lang":16,"slug":39,"tags":45,"createdAt":46},"Parole Expression","Un nouveau site pour l'association.","https://www.paroleexpression.fr/",[18,33,34],["Date","2022-04-19T17:11:00.000Z"],"src/content/references/parole-expression.md","ec95a408f8c3e99c",{"html":24},"rose-primaire",{"id":50,"data":52,"filePath":58,"digest":59,"rendered":60},{"title":53,"subtitle":54,"url":55,"lang":16,"slug":50,"tags":56,"createdAt":57},"Rose Primaire","Une agence comme on l'aime.","https://roseprimaire.com/",[18,32,33,34],["Date","2023-04-19T17:11:00.000Z"],"src/content/references/rose-primaire.md","a0133200cf1bee58",{"html":24},"articles",["Map",63,64,76,77,89,90,102,103,113,114,124,125,134,135,171,172,205,206,224,225,239,240,269,270,298,299,315,316,366,367,410,411],"en-after-effects-expressions",{"id":63,"data":65,"body":73,"filePath":74,"digest":75,"deferredRender":72},{"title":66,"subtitle":67,"lang":68,"tags":69,"type":61,"slug":63,"createdAt":71,"code":72},"After Effects Expressions","Animation on steroïds.","en",[70],"Design",["Date","2019-04-24T09:00:00.000Z"],true,"import AstroImage from '../../../components/AstroImage.astro'\n\n## An ever lasting battle\n\nThere is very little documentation and the existing one is hard to find or very old. Very often I just don't have the time to dive into expression learning while animating even though it could help the entire project on the long term.\nSo the last time I had to do a complex animation, **I took the damn time!**\n\n## The begining of the end (of keyframes).\n\nEveryone uses expressions whether they know it or not. Most of the time it's a rather transparent process for the animator. For example: when parenting a property to another one, After Effects creates an expression for us.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/basic_expression_d81b12f1ac.jpeg'\n\twidth='728'\n\theight='80'\n\talt='Parenting the position of the form to a null creates an expression.'\n/>\n\nOver the last updates, Adobe has made an effort to make expressions more accessible to everyone. For example, the expression box is now resembling a code editor thanks to code-coloring and auto-completion features. After Effects expression feel like JavaScript with custom functions.\n\nThose custom functions can be called through a menu once you enabled the expressions on a property. It offers organized shortcut and proper syntax to all of AE native functions and a bunch of JavaScript standard ones.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/shortcut_39cc19d383.jpeg'\n\twidth='728'\n\theight='322'\n\talt='Alt + Click the stopwatch to access the shortcuts.'\n/>\n\n## So I need to learn javascript to do motion design now?\n\n### Why bother?\n\nI know that most animators don't have any kind of development background. However, if Adobe thought it best to let us use expressions, I think we ought to, at least, try.\n\n> A lot of incredible professionals like [Mt Mograph](https://www.mtmograph.com/) and [Video Copilot](https://videocopilot.net/) use expressions.\n\nLike every optimization process, building an expressions knowledge takes time. However, like all optimization process, you will benefit from it afterwards.\n\n### Where to learn\n\nI've gathered a list of my favourite learning grounds. Plenty more exist, **go get'em!**\n\n- [Adobe official expression starter guide (FR)](https://helpx.adobe.com/fr/after-effects/using/expression-language-reference.html)\n- [Adobe official expression basic (EN)](https://helpx.adobe.com/after-effects/using/expression-basics.html)\n- [Adobe forums for expressions](https://community.adobe.com/t5/after-effects/bd-p/after-effects?page=1&sort=latest_replies&filter=all&topics=label-expressions)\n- [Creative Cow expressions forums](https://creativecow.net/forums/forum/adobe-after-effects-expressions/)\n- [Youtube channel about expressions](https://www.youtube.com/playlist?list=PLvr5U5ZSt6IzHyvSL9fo0M9NRPsTvra31)\n- [All expressions explained](http://aescript.jecool.net/reference/)\n- [All expressions explained again](http://expressions.aenhancers.com/index.html)\n- [Nice examples of basic expressions](https://www.schoolofmotion.com/tutorials/amazing-expressions-in-after-effects)\n\n## Real world example\n\n### Number counter\n\nLet's say you need to animate a rather simple counter from 0% to 100%.\n\n- Start by creating a text layer. Define your typographic choices, colours, etc.\n- On the effect menu add expression options > slider control\n- Alt + Click the Source text property\n\n\u003Cvideo width='728' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/alt-counter.mp4' type='video/mp4' />\n\u003C/video>\n\n- Parent the source text to the slider control through the pickwhip.\n\n\u003Cvideo width='462' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/pickwhip.mp4' type='video/mp4' />\n\u003C/video>\n\nYou should get something like this in the expressions panel:\n\n```javascript\neffect(\"Slider Control\")(\"Slider\")​\n```\n\n- Set two keyframes on the slider from 0 to 100. The text should update accordingly.\n- By default, After Effects does not round numbers. In the expression panel, wrap your expression with the `Math.round()` function.\n\n\u003Cvideo width='728' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/round.mp4' type='video/mp4' />\n\u003C/video>\n\n```javascript\nMath.round(effect(\"Slider Control\")(\"Slider\"))​\n```\n\nGreat! We have a working counter. But we wanted a percentage counter. We could add a % glyph in another text layer but let's not.\n\nStill in the expression panel, we're going to add a string containing the % glyph, using basic JavaScript concatenation: `+ '%'`\n\n```javascript\nMath.round(effect(\"Slider Control\")(\"Slider\")) + '%'​\n```\n\n\u003Cvideo width='538' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/percent.mp4' type='video/mp4' />\n\u003C/video>\n\n**And there we go!** A fully functioning and customizable counter using a slider controller and expressions.","src/content/articles/en/after-effects-expressions.mdx","3b6f88fbf35af1a4","en-sci-hub-unblock",{"id":76,"data":78,"body":86,"filePath":87,"digest":88,"deferredRender":72},{"title":79,"subtitle":80,"lang":68,"tags":81,"type":61,"slug":76,"createdAt":84,"updatedAt":85},"Access blocked Sci-hub","The science of sharing.",[82,83],"Internet","Science",["Date","2019-03-31T07:47:36.000Z"],["Date","2022-12-27T12:08:00.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\nThe current sci-hub address is: \u003Ca href=\"https://sci-hub.se\" rel=\"noreferer noopener\">sci-hub.se\u003C/a>\n\n## What is this about?\n\nNot being a researcher myself, here’s an [extremely well done explanatory video](https://youtu.be/rcgxY__YXEc) on the subject of scientific publication (french audio with auto subtitle).\n\n> “This is outrageous!”​\n\nI noticed that my ISP was indeed blocking access. I have not yet been able to check for the other suppliers, but I imagine that they have all complied with the court decision.\nThe restriction in place is quite basic. This is a “DNS” block. A DNS is a server that is used to link a domain name: **www.sci-hub.tw** to an IP address: **186.2.163.90**\nIt is, in a way, the Internet phone book. Without the address, it is impossible to contact the domain. What ISPs have certainly done: block requests to the [sci-hub.se.](http://sci-hub.se/) domain name. As a result, no IP address is returned and the site is not accessible.\n\n## How to bypass this?\n\n- Either by using a VPN\n- Either by modifying the DNS servers of your computers/Internet box\n\nI would recommend the second solution because it allows you to protect yourself against future blockages/filtering/censorship from your ISP and does not require any financial compensation.\nI will focus on change from a computer because it will be effective wherever you are and not only from your home.\n\n### MacOs\n\nGo to:\n\n1. System Preferences\n1. Network\n1. (wi-fi and/or ethernet)\n1. Advanced\n1. DNS\n\nFrom there, you can add DNS servers by clicking the + icon. Click ok and apply the new settings. You might need to restart your computer for the changes to work.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/ef5a4b8e82a046e6a466c73c2fd9e99e.jpg'\n\twidth='728'\n\theight='1060'\n\talt='MacOS network and DNS settings'\n/>\n\n### Windows (10)\n\nGo to:\n\n1. System Settings\n1. Network & Internet\n1. Change adapter options\n1. Right click your adapter then “properties”\n1. Select “internet protocol version 4” (and/or 6)\n1. Properties\n1. Use the following DNS server addresses\n\nFrom there, you can add DNS servers. Click save. You might need to restart your computer for the changes to work.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-settings.jpg'\n\twidth='728'\n\theight='319'\n\talt='Windows system settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-network.jpg'\n\twidth='728'\n\theight='803'\n\talt='Windows network settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter.jpg'\n\twidth='728'\n\theight='327'\n\talt='Windows network connections settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter-settings.jpg'\n\twidth='728'\n\theight='434'\n\talt='Windows network adapter settings'\n/>\n\n## Which DNS?\n\nThere are many DNS servers available. The best known are Google, Cloudflare and OpenDNS. If you really want to use Google’s, I’ll let you look up their address. Here are my recommendations in order of preference.\n\n### [FDN DNS](https://www.fdn.fr/actions/dns/)\n\nMy favorite since it is a [french association](https://www.fdn.fr/)\n\n1. IPV4\n - 80.67.169.12\n - 80.67.169.40\n2. IPV6\n - 2001:910:800::12\n - 2001:910:800::40\n\n### [Quad9](https://www.quad9.net)\n\nQuand9 is a non-profit foundation offering free public DNS servers. Their classic servers offer filtering of identified malicious domains. They do not collect data and are \u003Cabbr title=\"General Data Protection Regulation\">GDPR\u003C/abbr>-compliant.\n\n1. IPV4\n - 9.9.9.9\n - 149.112.112.112\n2. IPV6\n - 2620:fe::fe\n - 2620:fe::9\n\n## That's it.\n\nBy changing these settings, you are free from your ISPs and their content filtering rules.\n\nFor the moment, these restrictions are almost symbolic because if Sci-hub were to change its url, the block would no longer work. But the publishers’ victory in court shows that they have not had their last word. We are therefore not immune to a wider and stronger block in the future.\n\nIf you want to learn more about the struggle of the people who fight to ensure that research is not a paid commodity, I recommend [this documentary](https://youtu.be/y_CQATGOX2w) on Aaron Shwartz. Or [this article](https://arstechnica.com/tech-policy/2016/04/a-spiritual-successor-to-aaron-swartz-is-angering-publishers-all-over-again/) about the founder of Sci-hub.\n\nIn the meantime, good readings to all of you. We stand with you!","src/content/articles/en/sci-hub-blocage.mdx","8959506d941cdcc5","en-the-day-I-jamd",{"id":89,"data":91,"body":99,"filePath":100,"digest":101,"deferredRender":72},{"title":92,"subtitle":93,"lang":68,"tags":94,"type":61,"slug":89,"createdAt":97,"updatedAt":98},"The day I Jam’d","A story of unusual tools and fun gambles.",[95,96],"Dev","Jamstack",["Date","2020-10-08T09:00:00.000Z"],["Date","2022-12-27T15:40:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## The not so easy choice\n\nWhen I was still using Wordpress for my personal website, I thought it would be nice to try [OpenLiteSpeed](https://openlitespeed.org) webserver. Being a designer, I always like to have a graphical interface and I heard OLS had very nice caching and overall performances.\n\n## FIGHT!\n\nA few years later, I learned about Jamstack and its incredible potential. Not being impulsive at all, I chose to entirely remake my website with tools like [11ty](https://www.11ty.dev/) and [Strapi](https://strapi.io/).\n\nI remember Strapi still being in alpha/beta and colleagues telling me it was a risky gamble, especially since I was pretty new to the node.js world.\n\n> Open source and french? Sign me up!\n\nSo I started recreating my website identically with 11ty and Strapi. Same hosting on a Digital Ocean droplet, same webserver, same content. I had done a fair amout of performance optimizations on my wordpress install so I was eager to compare the results with the new static version.\n\nBoy did they exceed my expectations! With almost no optimization on the static side, I got the following results.\n\n### wordpress\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/wordpress_8ee6f54b98.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Performance score of 53/100 on Wordpress.'\n/>\n\nDespite a lot of efforts I could not do better. I’m no expert in caching, do not use CDN and relied on plugins to achieve a lot of stuff (php not being my strongest skill 😬).\n\n### 11ty + strapi\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/static_2c0d9f1eb8.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Performance score of 97/100 on jamstack.'\n/>\n\nAlmost **zero** special configuration (I was too anxious to test) and I reached an awesome score. I know lighthouse scores are not everything but hey, **53 vs 97**… I’ll take it!\n\n## Now kiss 🥰\n\nBoth of these approaches have their benefits and drawbacks. As a freelance, my clients often prefer or ask for Wordpress because of its reputation. I always present a Jamstack alternative when possible but it’s still scary to most compared to Wordpress. I feel however that it’s going to be easier to use Jamstack with time.\n\n## I did it again…\n\nHere we are now, a quarantine and a few months later and this website is running with… [Nuxt.js](https://nuxtjs.org/). I know, I’m sorry, I couldn’t resist the latest [nuxt content](https://content.nuxtjs.org/) functionnality.\n\nSo I re-did everything again… and let me just say: **wow**, what an experience!\nI **love** developing with Nuxt. Using nuxt content allowed me to focus on design and, well, content.\nNo more Apollo client and graphQL query, only markdown and a few promises.\n\nDon’t get me wrong, I really like working with Strapi and its graphQL capabilities but for the purpose of this website, nuxt content does it (extremely well).\n\nI’m still using Strapi as a way to upload, store and manage images, videos, gifs, etc. It might be too much for this use case but I like to know that I can still go back to it if I want to! Also, I spent quite a bit of time setting it up with OpenLiteSpeed and I’m still too attached to this accomplishment to let it go.\n\n## In the end\n\nWordpress, Jamstack, vanilla everything… Does it really matter? For me, the dev experience was far more enjoyable working with 11ty, nuxt.js and strapi than with Wordpress.\n\nOn the performance and accessibility side, it also seems to be the better/smarter choice. It might not be everytime! ¯\\\\\\_(ツ)\\_/¯\n\nCan’t wait to learn [astro](https://astro.build/) and start from scratch again!","src/content/articles/en/the-day-I-jamd.mdx","60b77e216e02f618","en-video-compression",{"id":102,"data":104,"body":110,"filePath":111,"digest":112,"deferredRender":72},{"title":105,"subtitle":106,"lang":68,"tags":107,"type":61,"slug":102,"createdAt":108,"updatedAt":109},"Video compression","Encode like you mean it.",[70],["Date","2021-05-05T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Let's play.\n\nVideos are everywhere. **EVERYWHERE!** But videos can and will be huge when 4k becomes an internet standard. Currently, 1920x1080 is king and we usually have no problem hosting or playing this resolution.\n\n## Because we can doesn't mean we should.\n\nRight now, the (good) trend of web performance is on the rise. Everyone wants a blazing fast loading website, which might not be possible if we send requests to 100mb (or even more) videos.\n\nWith a good connection, users will not see the difference. But if we go down that path, nor will they with a 300mb one. So the goal is to make every asset as small as possible. It's already the case with images. But it's simpler and faster than video encoding.\n\n## Small size, best quality.\n\nLet's say we exported​ a 1920x1080 video from Premiere Pro with these basic settings:\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-premiere-1.jpeg'\n\twidth='673'\n\theight='800'\n/>\n\nIt's gorgeous, it's Full HD, it's 1:30 minute of excellent editing but it's 50mb… What a shame.\n\n> We can already bring down the size from Premiere or Media Encoder by selecting CBR instead of VBR and using a low bitrate (like 2 or 3).\n\nLet's now use [Handbrake!](https://handbrake.fr/) It's free, open source and multi platform. You can also read this great article from [Ueno](https://loremipsum.ueno.co/dear-ueno-how-do-you-compress-videos-6657ebd9dd28?gi=930afecec398) on video encoding.\n\n**Please please PLEASE. Never export videos from within After Effects.**\n\n## Handbrake\n\n### Summary screen\n\nWhile it's not as nice as Premiere Pro, it has way more exporting capabilities. Follow these steps to use good standard settings:\n\n1. Open your source video\n1. Select a preset corresponding to your future usage like Fast 1080p30\n1. Check Web Optimized\n1. Keep MPEG-4 as the format\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-1.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Video screen\n\n1. Keep H.264 (x264) or use H.264 nvidia nvenc if you can (crazy fast encoding by nvidia)\n1. Choose Constant Quality and try a value between 20 and 30​ (higher = smaller size but lower quality)\n1. Choose Peak Framerate. If you don't know the framerate, keep the default setting\n1. Choose the type of video you are encoding (film, animation…)\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-2.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Audio screen\n\nIf you don't have audio, be sure to set the audio channel to none.\nIf you have an audio channel, these settings are great and will not influence the size much​:\n\n1. Codec AAC\n1. Samplerate 44.1\n1. Bitrate 192 to 256 (your choice)\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-3.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Export!\n\nI used a RF of 25 for this example and no audio.\n\n1. My Premiere Pro video was 50,6mb\n1. My Handbrake video is 5,5mb​\n\n> What a save!\n\n​I ended up dividing the original size by 10. Which is cool.\nI tried with a RF of 30. The video was still pretty good and only 3,3mb.\n\n## Exporting for the web\n\nNow that we know how to properly compress videos, let's go further. Say we have a website with a lot of videos on the same page. We still want to load the content as fast as possible. So our videos need to be as small as possible. We won't do better than previously seen using mp4/H.264. However, we can use **webm/VP9.**\nWebm is an html video format and VP9 is its latest codec.\n\nUsing Handbrake and webm/VP9, we can achieve really great compression without losing too much quality (or none at all depending on the settings). I was able to divide by 4 the size of a video using these presets:\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-4.jpg'\n\twidth='728'\n\theight='313'\n\talt=''\n/>\n\nThe only down side is that it takes some time to encode. It will depend on the video length and your computing power.\n\nI tried various settings but I read [here](https://trac.ffmpeg.org/wiki/Encode/VP9) that VP9 is supposed to be used with two-pass encoding. You then have to find the right bitrate (here 1000) for your situation.","src/content/articles/en/video-compression.mdx","5bb9f69df6c651d1","sci-hub-blocage",{"id":113,"data":115,"body":121,"filePath":122,"digest":123,"deferredRender":72},{"title":116,"subtitle":117,"lang":16,"tags":118,"type":61,"slug":113,"createdAt":119,"updatedAt":120},"Sci-hub bloqué, comment contourner","La science du partage.",[82,83],["Date","2019-03-31T07:47:36.000Z"],["Date","2022-12-27T12:08:00.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\nL'adresse actuelle de sci-hub est : [sci-hub.se](https://sci-hub.se)\n\n## Résumé de la situation\n\nN’étant pas moi-même directement chercheur, je vous laisse regarder [cette vidéo](https://youtu.be/rcgxY__YXEc) explicative extrêmement bien faite sur le sujet de la publication scientifique.\n\n> “ Mais c’est scandaleux ! ”​\n\nJ’ai constaté que le blocage était actif chez SFR. Je n’ai pas encore pu vérifier pour les autres fournisseurs mais j’imagine qu’ils se sont tous conformés à la décision de justice.\nLe blocage mis en place est assez basique. Il s’agit d’un blocage “ DNS ”.\n\nUn DNS est un serveur qui sert à faire le lien entre un nom de domaine : **sci-hub.tw** et une adresse IP : **186.2.163.90**.\n\nC’est en quelque sorte l’annuaire d’internet. Sans l’adresse, impossible de contacter le domaine. Ce que les FAI ont certainement fait : bloquer les requêtes au nom de domaine [sci-hub.se.](http://sci-hub.se/) Ainsi, aucune adresse IP n’est renvoyée et le site n’est pas accessible.\n\n## Comment contourner ce blocage ?\n\n- Soit en utilisant un VPN\n- Soit en modifiant les serveurs DNS de vos ordinateurs/box internet\n\nJe recommande la deuxième solution car elle permet de se prémunir contre de futurs blocages/filtrages/censures de la part de votre FAI et ne nécessite pas de contrepartie financière.\nJe vais me focaliser sur le changement depuis un ordinateur car il sera effectif où que vous soyez.\n\n### Sur MacOs\n\nOuvrez :\n\n1. Préférences système\n1. Réseau\n1. Ethernet et/ou Wi-fi\n1. Avancé\n1. DNS\n1. Serveurs DNS\n\nDe là, vous pouvez ajouter des serveurs DNS en cliquant sur l'icône +. Cliquez sur ok et appliquez les nouveaux paramètres. Vous devrez peut-être redémarrer votre ordinateur pour que les changements fonctionnent.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/ef5a4b8e82a046e6a466c73c2fd9e99e.jpg'\n\twidth='728'\n\theight='1060'\n\talt='MacOS réglages réseau et DNS'\n/>\n\n### Sur Windows (ici 10)\n\nOuvrez :\n\n1. Réglages\n1. Réseau et internet\n1. Modifier les options de l'adaptateur\n1. Clic droit sur les propriétés de votre interface réseau\n1. Selectionnez « protocole Internet version 4 » (et/ou 6)\n1. Propriétés\n1. Utiliser l’adresse de serveur DNS suivante\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-settings.jpg'\n\twidth='728'\n\theight='319'\n\talt='Réglages windows'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-network.jpg'\n\twidth='728'\n\theight='803'\n\talt='Windows réglages réseaux'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter.jpg'\n\twidth='728'\n\theight='327'\n\talt='Windows régalges connections réseaux'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter-settings.jpg'\n\twidth='728'\n\theight='434'\n\talt='Windows options adaptateur réseau'\n/>\n\n## Quels serveurs DNS utiliser ?\n\nIl y a de nombreux serveurs DNS accessibles. Les plus connus étant ceux de Google, Cloudflare et OpenDNS. Si vous tenez vraiment à utiliser ceux de Google, je vous laisse chercher leur adresse. Voici mes recommandations par ordre de préférence.\n\nPlusieurs fournisseurs :\n\n### [FDN DNS](https://www.fdn.fr/actions/dns/)\n\nMes favoris puisqu’il s’agit d’une [association française.](https://www.fdn.fr/)\n\n1. IPV4\n - 80.67.169.12\n - 80.67.169.40\n2. IPV6\n - 2001:910:800::12\n - 2001:910:800::40\n\n### [Quad9](https://www.quad9.net/fr)\n\nQuand9 est une fondation à but non lucratif proposant des serveurs DNS publics et gratuits. Leurs serveur classiques offrent un filtrage de domaines malveillants identifiés. Ils ne collectent pas de données et sont conforment au \u003Cabbr title=\"Règlement général sur la protection des données\">RGPD\u003C/abbr>.\n\n1. IPV4\n - 9.9.9.9\n - 149.112.112.112\n2. IPV6\n - 2620:fe::fe\n - 2620:fe::9\n\n## C'est tout.\n\nEn modifiant ces réglages, vous vous affranchissez de vos fournisseurs d’accès et de leurs règles de filtrage du contenu.\n\nPour l’instant, ces blocages sont presque symboliques car si Sci-hub venait à changer d’url, le blocage ne fonctionnerait plus. Mais la victoire des éditeurs au tribunal montre qu’ils n’ont pas dit leur dernier mot. Nous ne sommes donc pas à l’abri d’un futur blocage plus large et plus dur à contrer.\n\nSi vous voulez en apprendre plus sur le combat de ces gens qui se battent pour que la recherche ne soit pas une marchandise, je vous conseille [ce documentaire](https://youtu.be/y_CQATGOX2w) sur Aaron Shwartz. Ou plus simplement [cet article](https://arstechnica.com/tech-policy/2016/04/a-spiritual-successor-to-aaron-swartz-is-angering-publishers-all-over-again/) sur la fondatrice de Sci-hub.\n\nEn attendant, bonnes lectures à tou·te·s. On est avec vous !","src/content/articles/fr/sci-hub-blocage.mdx","6438fdc02b91ec59","the-day-I-jamd",{"id":124,"data":126,"body":131,"filePath":132,"digest":133,"deferredRender":72},{"title":92,"subtitle":127,"lang":16,"tags":128,"type":61,"slug":124,"createdAt":129,"updatedAt":130},"Des paris, des outils et du fun.",[95,96],["Date","2020-10-08T07:47:36.000Z"],["Date","2022-12-27T15:40:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## La solution de non facilité\n\nLorsque j’utilisais encore Wordpress pour mon site web personnel, j’ai voulu essayer le serveur web \u003Ca href=\"https://openlitespeed.org\" lang=\"en\" hreflang=\"en\" rel=\"noopener noreferer\">OpenLiteSpeed (en anglais)\u003C/a>. En tant que designer, j’ai toujours aimé avoir une interface graphique et j’avais entendu dire qu’OLS jouissait de bonnes performances en général et de cache en particulier.\n\n## Battez-vous!\n\nQuelques années plus tard, je découvrais l’univers Jamstack et son incroyable potentiel. N’étant pas du tout impulsif, j’ai choisi de refaire entièrement mon site web avec des outils comme \u003Ca href=\"https://www.11ty.dev/\" lang=\"en\" hreflang=\"en\" rel=\"noopener noreferer\">11ty (en anglais)\u003C/a> et \u003Ca href=\"https://strapi.io/\" hreflang=\"en\">Strapi (en anglais)\u003C/a>.\n\nJe me souviens que Strapi était encore en alpha/beta et que certains collègues me disaient que c’était un pari risqué, surtout que je découvrais à peine le monde de node.js.\n\n> Open source et français ? Je dis banco !\n\nJ’ai donc commencé à recréer mon site web à l’identique avec 11ty et Strapi. Même hébergement chez Digital Ocean, même serveur web, même contenu. J’avais fait pas mal d’optimisations de performances sur mon installation wordpress, j’étais donc impatient de comparer les résultats avec la nouvelle version statique.\n\nJ’en suis resté pantois ! Quasiment sans optimisation du côté statique, j’ai obtenu les résultats ci-dessous.\n\n### wordpress\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/wordpress_8ee6f54b98.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Score de performance de 53/100 sur Wordpress.'\n/>\n\nMalgré beaucoup d’efforts, je n’ai pas pu faire mieux. Je ne suis pas un expert en cache, je n’utilise pas de CDN et je me suis appuyé sur des plugins pour réaliser beaucoup de choses (php n’étant pas ma spécialité 😬).\n\n### 11ty + strapi\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/static_2c0d9f1eb8.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Score de performance de 97/100 en Jamstack.'\n/>\n\nPresque **zéro** configuration spéciale (j’étais trop impatient de tester) et j’ai atteint un score impressionnant. Je sais que les scores lighthouse ne font pas tout mais **53 contre 97**… Ça me va !\n\n## Embrassez-vous 🥰\n\nCes deux approches ont leurs avantages et leurs inconvénients. En tant que freelance, mes clients préfèrent ou demandent souvent Wordpress en raison de sa réputation. Je présente toujours une alternative Jamstack lorsque c’est possible, mais cela reste effrayant la plupart du temps par rapport à Wordpress. Je pense cependant qu’il sera plus facile d’utiliser la Jamstack avec le temps.\n\n## Encore et encore…\n\nNous voici maintenant une quarantaine et quelques mois plus tard et ce site fonctionne avec… [Nuxt.js](https://fr.nuxtjs.org/). Je sais, je suis désolé, je n’ai pas pu résister à la dernière fonctionnalité [\u003Cspan lang=\"en\">nuxt content\u003C/span>](https://content.nuxtjs.org/fr) de Nuxt.\n\nDu coup j’ai tout refait… et laissez-moi vous dire : **wow**, quelle expérience !\nJ’adore développer avec Nuxt. L’utilisation de \u003Cspan lang=\"en\">nuxt content\u003C/span> m’a permis de me concentrer sur le design et, évidemment, sur le contenu.\nPlus de client Apollo ni de requête graphQL, seulement du \u003Cspan lang=\"en\">markdown\u003C/span> et quelques promesses.\n\nAttention, j’aime beaucoup travailler avec Strapi et son interface graphQL mais pour les besoins de ce site, \u003Cspan lang=\"en\">nuxt content\u003C/span> fait le \u003Cspan lang=\"en\">job\u003C/span> (extrêmement bien).\n\nJ’utilise toujours Strapi pour téléverser, stocker et gérer les images, vidéos, gifs, etc. C’est peut-être trop pour ce que j’en fait mais j’aime savoir que je peux toujours y revenir si j’ai envie ! De plus, j’ai passé pas mal de temps à le mettre en place avec \u003Cspan lang=\"en\">OpenLiteSpeed\u003C/span> et je suis encore trop attaché à cette réussite pour la laisser tomber.\n\n## Et en fait à la fin\n\nWordpress, Jamstack, fait main… Est-ce vraiment important ? Pour moi, l’expérience de développement a été bien plus agréable en travaillant avec 11ty, nuxt.js et strapi qu’avec Wordpress.\n\nDu point de vue de la performance et de l’accessibilité, il semble également que ce soit le choix le plus judicieux. Ce n’est peut-être pas le cas à chaque fois ! ¯\\\\\\_(ツ)\\_/¯\n\nJ’ai hâte d’apprendre \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\" >astro\u003C/a> et de tout recommencer à zéro !","src/content/articles/fr/the-day-I-jamd.mdx","57bd292bda8b6632","en-2022",{"id":134,"data":136,"body":142,"filePath":143,"digest":144,"rendered":145},{"title":137,"subtitle":138,"lang":68,"tags":139,"type":61,"slug":134,"createdAt":141},"Nico v2.0","2022 update of many things.",[140],"Freelance",["Date","2022-06-08T14:24:06.000Z"],"After two years of full-time freelancing, I took a step back from my activity. I especially questioned my positioning and the services I was offering.\n\n## Services\n\n### No more print\n\nEven though I am trained in branding, I rarely do it and do not practice it in my free time. The same goes for \"classic\" graphic design. Posters, flyers and other leaflets have disappeared from my quotes for a long time. It seems logical to me to no longer explicitly offer these services because I consider that I am no longer sufficiently competent or interested.\n\n### Internet all the way\n\nOn the other hand, I spend my time **doing web stuff.** A lot of development, some design and a fait amout of server configuration. It is therefore obvious for me to offer **more specific web offerings,** in which I have specialised.\n\nThus, **accessibility** and **eco-design** become integrated expertises in my practice. They are no longer options on a quote but **my core business.**\n\n## The website\n\nI have reworked my website, especially the homepage and its content, to better reflect these decisions.\n\nI have also made several behavioural changes:\n\n- external links no longer open in a new window. I read \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\">this article\u003C/a> about opening links in a new window and I haven't found a good reason to continue using this behaviour;\n- I have removed the open graph and twitter card meta tags as I fully agree with \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\" rel=\"noopener noreferer\" hreflang=\"fr\">this opinion (in french)\u003C/a> by [@HTeuMeuLeu](https://twitter.com/HTeuMeuLeu);\n- \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\" rel=\"noopener noreferer\" hreflang=\"fr\">same for the favicon\u003C/a>;\n- I only trigger animations if the user has not asked the system to reduce the amount motion [(reference)](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion).\n\nI am working on reducing the weight of my pages as much as possible, although I will certainly have to change tools (again) (hello [astro](https://astro.build/) 👀).\n\n## Le Nico\n\nOn a personal level, I have committed myself to a more responsible digital world by joining the \u003Ca href=\"https://www.good-it.org/\" rel=\"noopener noreferer\" hreflang=\"fr\">Good-it! (in french)\u003C/a> collective and by actively participating in its development.\n\nI have also started teaching in several schools. I mainly intervene on digital courses by teaching design and development. I take this opportunity to to make future generations aware of accessibility and eco-design.","src/content/articles/en/2022.md","7b98592763cb0929",{"html":146,"metadata":147},"\u003Cp>After two years of full-time freelancing, I took a step back from my activity. I especially questioned my positioning and the services I was offering.\u003C/p>\n\u003Ch2 id=\"services\">Services\u003C/h2>\n\u003Ch3 id=\"no-more-print\">No more print\u003C/h3>\n\u003Cp>Even though I am trained in branding, I rarely do it and do not practice it in my free time. The same goes for “classic” graphic design. Posters, flyers and other leaflets have disappeared from my quotes for a long time. It seems logical to me to no longer explicitly offer these services because I consider that I am no longer sufficiently competent or interested.\u003C/p>\n\u003Ch3 id=\"internet-all-the-way\">Internet all the way\u003C/h3>\n\u003Cp>On the other hand, I spend my time \u003Cstrong>doing web stuff.\u003C/strong> A lot of development, some design and a fait amout of server configuration. It is therefore obvious for me to offer \u003Cstrong>more specific web offerings,\u003C/strong> in which I have specialised.\u003C/p>\n\u003Cp>Thus, \u003Cstrong>accessibility\u003C/strong> and \u003Cstrong>eco-design\u003C/strong> become integrated expertises in my practice. They are no longer options on a quote but \u003Cstrong>my core business.\u003C/strong>\u003C/p>\n\u003Ch2 id=\"the-website\">The website\u003C/h2>\n\u003Cp>I have reworked my website, especially the homepage and its content, to better reflect these decisions.\u003C/p>\n\u003Cp>I have also made several behavioural changes:\u003C/p>\n\u003Cul>\n\u003Cli>external links no longer open in a new window. I read \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\">this article\u003C/a> about opening links in a new window and I haven’t found a good reason to continue using this behaviour;\u003C/li>\n\u003Cli>I have removed the open graph and twitter card meta tags as I fully agree with \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\" rel=\"noopener noreferer\" hreflang=\"fr\">this opinion (in french)\u003C/a> by \u003Ca href=\"https://twitter.com/HTeuMeuLeu\">@HTeuMeuLeu\u003C/a>;\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\" rel=\"noopener noreferer\" hreflang=\"fr\">same for the favicon\u003C/a>;\u003C/li>\n\u003Cli>I only trigger animations if the user has not asked the system to reduce the amount motion \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion\">(reference)\u003C/a>.\u003C/li>\n\u003C/ul>\n\u003Cp>I am working on reducing the weight of my pages as much as possible, although I will certainly have to change tools (again) (hello \u003Ca href=\"https://astro.build/\">astro\u003C/a> 👀).\u003C/p>\n\u003Ch2 id=\"le-nico\">Le Nico\u003C/h2>\n\u003Cp>On a personal level, I have committed myself to a more responsible digital world by joining the \u003Ca href=\"https://www.good-it.org/\" rel=\"noopener noreferer\" hreflang=\"fr\">Good-it! (in french)\u003C/a> collective and by actively participating in its development.\u003C/p>\n\u003Cp>I have also started teaching in several schools. I mainly intervene on digital courses by teaching design and development. I take this opportunity to to make future generations aware of accessibility and eco-design.\u003C/p>",{"headings":148,"imagePaths":166,"frontmatter":167},[149,153,157,160,163],{"depth":150,"slug":151,"text":152},2,"services","Services",{"depth":154,"slug":155,"text":156},3,"no-more-print","No more print",{"depth":154,"slug":158,"text":159},"internet-all-the-way","Internet all the way",{"depth":150,"slug":161,"text":162},"the-website","The website",{"depth":150,"slug":164,"text":165},"le-nico","Le Nico",[],{"title":137,"subtitle":138,"lang":68,"slug":134,"excerpt":168,"tags":169,"type":61,"createdAt":170},"Changes in my services, the website and myself.",[140],"2022-06-08T14:24:06.000Z","en-2023",{"id":171,"data":173,"body":179,"filePath":180,"digest":181,"rendered":182},{"title":174,"subtitle":175,"lang":68,"tags":176,"type":61,"slug":171,"createdAt":177,"updatedAt":178},"Nico v2.5","Update 2023.",[140],["Date","2023-02-03T17:41:00.000Z"],["Date","2023-05-17T17:41:00.000Z"],"This article will be updated when I have something new to share during the year 2023.\n\n## The website\n\n### Technologies\n\nOops... I (re)did it again.\n\nI have completely redeveloped my site with \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, as predicted by myself [in 2022 !](/en/articles/2022/#the-website)\n\nI will definitely do an article or two about Astro and the extensions I used. It was a great experience. Nuxt v2 is not really up to date anymore, so the performance was not good. Astro has completely fixed that.\n\nMy \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\">PageSpeed\u003C/a> performance score had dropped to 77/100. Thanks to Astro I'm back to a solid **95/100** without any particular optimization. With some small efforts, I've reached the good old 100/100.\n\nI then did a work of modernization of the codebase. Hello CSS variables and goodbye `media queries`. In no particular order, here are some of the improvements I made:\n\n- `flexbox` and `grid` to adapt the layout to different screen sizes;\n- CSS variables for colors, font sizes and margins;\n- some `container queries`, just to try;\n- logical CSS properties (`inline` and `block` instead of `width` and `height` for example).\n\nI took this opportunity to publish [the source code](https://git.nardu.in/nardu.in/website-astro) on my git repository.\n\n**Update #1:** I've added [an RSS feed](/en/rss.xml) as I find myself using it more and more on other websites.\n\n### Analytics\n\nI removed the tracking on my pages. I was using \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\">umami\u003C/a> hosted on my own server. No personal data was collected and I rarely consulted the reports.\n\nIt's nice to see that your site is consulted, but if there is no other purpose behind it, it's an extra resource loaded for nothing by visitors. Maybe I'll reactivate the tracking when I have a use for it (other than flattering my ego).\n\nPrevious visit reports can be found at [this link.](https://stat.nardu.in/share/nJSt1tfS/nardu.in)\n\n### Content\n\n- I've added a [work](/en/work/) page to list some of my projects.\n- I've also added [a page](/en/veille/) where I list some interesting things from around the web.\n\n## Additional projects\n\nI'm still teaching web development this year. In order to expand my course materials, I have set up a mini documentation site available at [3-w.fr](https://3-w.fr/) (an address I am very proud of).\n\nI have to update it more regularly but I hope that the platform will help students progress!\n\n**More to come soon!**","src/content/articles/en/2023.md","489c650e66cced63",{"html":183,"metadata":184},"\u003Cp>This article will be updated when I have something new to share during the year 2023.\u003C/p>\n\u003Ch2 id=\"the-website\">The website\u003C/h2>\n\u003Ch3 id=\"technologies\">Technologies\u003C/h3>\n\u003Cp>Oops… I (re)did it again.\u003C/p>\n\u003Cp>I have completely redeveloped my site with \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, as predicted by myself \u003Ca href=\"/en/articles/2022/#the-website\">in 2022 !\u003C/a>\u003C/p>\n\u003Cp>I will definitely do an article or two about Astro and the extensions I used. It was a great experience. Nuxt v2 is not really up to date anymore, so the performance was not good. Astro has completely fixed that.\u003C/p>\n\u003Cp>My \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\">PageSpeed\u003C/a> performance score had dropped to 77/100. Thanks to Astro I’m back to a solid \u003Cstrong>95/100\u003C/strong> without any particular optimization. With some small efforts, I’ve reached the good old 100/100.\u003C/p>\n\u003Cp>I then did a work of modernization of the codebase. Hello CSS variables and goodbye \u003Ccode>media queries\u003C/code>. In no particular order, here are some of the improvements I made:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>flexbox\u003C/code> and \u003Ccode>grid\u003C/code> to adapt the layout to different screen sizes;\u003C/li>\n\u003Cli>CSS variables for colors, font sizes and margins;\u003C/li>\n\u003Cli>some \u003Ccode>container queries\u003C/code>, just to try;\u003C/li>\n\u003Cli>logical CSS properties (\u003Ccode>inline\u003C/code> and \u003Ccode>block\u003C/code> instead of \u003Ccode>width\u003C/code> and \u003Ccode>height\u003C/code> for example).\u003C/li>\n\u003C/ul>\n\u003Cp>I took this opportunity to publish \u003Ca href=\"https://git.nardu.in/nardu.in/website-astro\">the source code\u003C/a> on my git repository.\u003C/p>\n\u003Cp>\u003Cstrong>Update #1:\u003C/strong> I’ve added \u003Ca href=\"/en/rss.xml\">an RSS feed\u003C/a> as I find myself using it more and more on other websites.\u003C/p>\n\u003Ch3 id=\"analytics\">Analytics\u003C/h3>\n\u003Cp>I removed the tracking on my pages. I was using \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\">umami\u003C/a> hosted on my own server. No personal data was collected and I rarely consulted the reports.\u003C/p>\n\u003Cp>It’s nice to see that your site is consulted, but if there is no other purpose behind it, it’s an extra resource loaded for nothing by visitors. Maybe I’ll reactivate the tracking when I have a use for it (other than flattering my ego).\u003C/p>\n\u003Cp>Previous visit reports can be found at \u003Ca href=\"https://stat.nardu.in/share/nJSt1tfS/nardu.in\">this link.\u003C/a>\u003C/p>\n\u003Ch3 id=\"content\">Content\u003C/h3>\n\u003Cul>\n\u003Cli>I’ve added a \u003Ca href=\"/en/work/\">work\u003C/a> page to list some of my projects.\u003C/li>\n\u003Cli>I’ve also added \u003Ca href=\"/en/veille/\">a page\u003C/a> where I list some interesting things from around the web.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"additional-projects\">Additional projects\u003C/h2>\n\u003Cp>I’m still teaching web development this year. In order to expand my course materials, I have set up a mini documentation site available at \u003Ca href=\"https://3-w.fr/\">3-w.fr\u003C/a> (an address I am very proud of).\u003C/p>\n\u003Cp>I have to update it more regularly but I hope that the platform will help students progress!\u003C/p>\n\u003Cp>\u003Cstrong>More to come soon!\u003C/strong>\u003C/p>",{"headings":185,"imagePaths":199,"frontmatter":200},[186,187,190,193,196],{"depth":150,"slug":161,"text":162},{"depth":154,"slug":188,"text":189},"technologies","Technologies",{"depth":154,"slug":191,"text":192},"analytics","Analytics",{"depth":154,"slug":194,"text":195},"content","Content",{"depth":150,"slug":197,"text":198},"additional-projects","Additional projects",[],{"title":174,"subtitle":175,"lang":68,"slug":171,"excerpt":201,"tags":202,"type":61,"createdAt":203,"updatedAt":204},"New changes.",[140],"2023-02-03T17:41:00.000Z","2023-05-17T17:41:00.000Z","en-faq",{"id":205,"data":207,"body":212,"filePath":213,"digest":214,"rendered":215},{"title":208,"subtitle":209,"lang":68,"tags":210,"type":61,"slug":205,"createdAt":211,"draft":72},"Accessibility and sobriety","Translation in progress, stay tuned ;)",[140],["Date","2022-06-22T15:34:45.000Z"],"[Go back to available articles](/en/articles)","src/content/articles/en/faq.md","82d516449896f6ca",{"html":216,"metadata":217},"\u003Cp>\u003Ca href=\"/en/articles\">Go back to available articles\u003C/a>\u003C/p>",{"headings":218,"imagePaths":219,"frontmatter":220},[],[],{"title":208,"subtitle":209,"lang":68,"slug":205,"draft":72,"excerpt":221,"tags":222,"type":61,"createdAt":223},"Why, how et and especially what.",[140],"2022-06-22T15:34:45.000Z","en-gratuiste",{"id":224,"data":226,"body":212,"filePath":230,"digest":231,"rendered":232},{"title":227,"subtitle":209,"lang":68,"tags":228,"type":61,"slug":224,"createdAt":229,"draft":72},"Gratuiste",[70,140],["Date","2017-05-27T07:47:36.000Z"],"src/content/articles/en/gratuiste.md","ebec75d19f0ff741",{"html":216,"metadata":233},{"headings":234,"imagePaths":235,"frontmatter":236},[],[],{"title":227,"subtitle":209,"lang":68,"slug":224,"draft":72,"excerpt":209,"tags":237,"type":61,"createdAt":238},[70,140],"2017-05-27T07:47:36.000Z","2022",{"id":239,"data":241,"body":245,"filePath":246,"digest":247,"rendered":248},{"title":137,"subtitle":242,"lang":16,"tags":243,"type":61,"slug":239,"createdAt":244},"Mise à jour 2022 de plein de trucs.",[140],["Date","2022-06-08T14:24:06.000Z"],"Après deux ans de freelance à temps plein, j’ai pris du recul sur mon activité. J’ai surtout questionné mon positionnement et les prestations que je proposais.\n\n## Les services\n\n### J’arrête le print\n\nMême si je suis formé à l’identité visuelle, je n’en fais que très rarement et ne pratique pas la discipline sur mon temps libre. Idem pour le graphisme « classique ». Affiches, flyers et autres prospectus ont disparu de mes devis depuis bien longtemps. Il me semble ainsi logique de ne plus proposer explicitement ces services car je considère ne plus être suffisamment compétent ni intéressé.\n\n### J’internet à fond\n\nÀ l’inverse, je passe mon temps à **faire du web.** Énormément de développement, un peu de design et pas mal de configuration serveur. Il est de fait évident pour moi de proposer **des offres web plus précises,** dans lesquelles je me suis spécialisé.\n\nAinsi, **l’accessibilité numérique** et **l’éco-conception** deviennent des expertises intégrées à ma pratique. Ce ne sont plus des options sur un devis mais bien **mon cœur de métier.**\n\n## Le site\n\nJ’ai retravaillé mon site, notamment la page d’accueil et son contenu, pour l’accorder avec ces décisions.\n\nJ’ai également fait plusieurs changements de comportements :\n\n- les liens externes ne s’ouvrent plus dans une nouvelle fenêtre. Je suis tombé sur \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\" hreflang=\"en\">cet article (en anglais)\u003C/a> traitant de l’ouverture des liens dans une nouvelle fenêtre et je n’ai pas trouvé de bonne raison de continuer à utiliser ce comportement ;\n- j’ai supprimé les balises open graph et twitter card car je suis entièrement d’accord avec [cette analyse](https://twitter.com/HTeuMeuLeu/status/1370310316496728065) de [@HTeuMeuLeu](https://twitter.com/HTeuMeuLeu) ;\n- [idem pour la favicon](https://twitter.com/HTeuMeuLeu/status/1370310312214339586) ;\n- je ne déclenche les animations que si l'utilisateur n'a pas demandé au système de minimiser la quantité d'animation ou de mouvement [(référence de l'option)](https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-reduced-motion).\n\nJe suis en train de travailler pour réduire au maximum le poids de mes pages, même si je vais certainement devoir (encore) changer d’outil (coucou \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\" >astro\u003C/a> 👀).\n\n## Le Nico\n\nD’un point de vue personnel, je me suis engagé pour un numérique plus responsable en rejoignant le collectif [Good-it!](https://www.good-it.org/) et en participant activement à son développement.\n\nJ’ai également commencé à donner des cours dans plusieurs écoles. J’interviens essentiellement sur des cursus numériques en enseignant le design et le développement. J’en profite ainsi pour sensibiliser, dès la formation, les futures générations à l’accessibilité et l’éco-conception.","src/content/articles/fr/2022.md","2589166172138721",{"html":249,"metadata":250},"\u003Cp>Après deux ans de freelance à temps plein, j’ai pris du recul sur mon activité. J’ai surtout questionné mon positionnement et les prestations que je proposais.\u003C/p>\n\u003Ch2 id=\"les-services\">Les services\u003C/h2>\n\u003Ch3 id=\"jarrête-le-print\">J’arrête le print\u003C/h3>\n\u003Cp>Même si je suis formé à l’identité visuelle, je n’en fais que très rarement et ne pratique pas la discipline sur mon temps libre. Idem pour le graphisme « classique ». Affiches, flyers et autres prospectus ont disparu de mes devis depuis bien longtemps. Il me semble ainsi logique de ne plus proposer explicitement ces services car je considère ne plus être suffisamment compétent ni intéressé.\u003C/p>\n\u003Ch3 id=\"jinternet-à-fond\">J’internet à fond\u003C/h3>\n\u003Cp>À l’inverse, je passe mon temps à \u003Cstrong>faire du web.\u003C/strong> Énormément de développement, un peu de design et pas mal de configuration serveur. Il est de fait évident pour moi de proposer \u003Cstrong>des offres web plus précises,\u003C/strong> dans lesquelles je me suis spécialisé.\u003C/p>\n\u003Cp>Ainsi, \u003Cstrong>l’accessibilité numérique\u003C/strong> et \u003Cstrong>l’éco-conception\u003C/strong> deviennent des expertises intégrées à ma pratique. Ce ne sont plus des options sur un devis mais bien \u003Cstrong>mon cœur de métier.\u003C/strong>\u003C/p>\n\u003Ch2 id=\"le-site\">Le site\u003C/h2>\n\u003Cp>J’ai retravaillé mon site, notamment la page d’accueil et son contenu, pour l’accorder avec ces décisions.\u003C/p>\n\u003Cp>J’ai également fait plusieurs changements de comportements :\u003C/p>\n\u003Cul>\n\u003Cli>les liens externes ne s’ouvrent plus dans une nouvelle fenêtre. Je suis tombé sur \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\" hreflang=\"en\">cet article (en anglais)\u003C/a> traitant de l’ouverture des liens dans une nouvelle fenêtre et je n’ai pas trouvé de bonne raison de continuer à utiliser ce comportement ;\u003C/li>\n\u003Cli>j’ai supprimé les balises open graph et twitter card car je suis entièrement d’accord avec \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\">cette analyse\u003C/a> de \u003Ca href=\"https://twitter.com/HTeuMeuLeu\">@HTeuMeuLeu\u003C/a> ;\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\">idem pour la favicon\u003C/a> ;\u003C/li>\n\u003Cli>je ne déclenche les animations que si l’utilisateur n’a pas demandé au système de minimiser la quantité d’animation ou de mouvement \u003Ca href=\"https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-reduced-motion\">(référence de l’option)\u003C/a>.\u003C/li>\n\u003C/ul>\n\u003Cp>Je suis en train de travailler pour réduire au maximum le poids de mes pages, même si je vais certainement devoir (encore) changer d’outil (coucou \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">astro\u003C/a> 👀).\u003C/p>\n\u003Ch2 id=\"le-nico\">Le Nico\u003C/h2>\n\u003Cp>D’un point de vue personnel, je me suis engagé pour un numérique plus responsable en rejoignant le collectif \u003Ca href=\"https://www.good-it.org/\">Good-it!\u003C/a> et en participant activement à son développement.\u003C/p>\n\u003Cp>J’ai également commencé à donner des cours dans plusieurs écoles. J’interviens essentiellement sur des cursus numériques en enseignant le design et le développement. J’en profite ainsi pour sensibiliser, dès la formation, les futures générations à l’accessibilité et l’éco-conception.\u003C/p>",{"headings":251,"imagePaths":265,"frontmatter":266},[252,255,258,261,264],{"depth":150,"slug":253,"text":254},"les-services","Les services",{"depth":154,"slug":256,"text":257},"jarrête-le-print","J’arrête le print",{"depth":154,"slug":259,"text":260},"jinternet-à-fond","J’internet à fond",{"depth":150,"slug":262,"text":263},"le-site","Le site",{"depth":150,"slug":164,"text":165},[],{"title":137,"subtitle":242,"lang":16,"slug":239,"excerpt":267,"tags":268,"type":61,"createdAt":170},"Évolution des services, du site et de moi-même.",[140],"2023",{"id":269,"data":271,"body":276,"filePath":277,"digest":278,"rendered":279},{"title":174,"subtitle":272,"lang":16,"tags":273,"type":61,"slug":269,"createdAt":274,"updatedAt":275},"Mise à jour 2023.",[140],["Date","2023-02-03T17:41:00.000Z"],["Date","2023-05-17T17:41:00.000Z"],"Cet article sera mis à jour lorsque j'aurai des nouveautés à partager au cours de l'année 2023.\n\n## Le site\n\n### Technologies\n\nOups… je l'ai encore (re)fait.\n\nJ'ai entièrement re-développé mon site avec \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, comme prédit par moi-même [en 2022 !](/articles/2022/#le-site)\n\nJe ferai certainement un ou deux articles/fragments sur Astro et les extensions que j'ai utilisées. En tout cas c'était super comme expérience. Nuxt v2 n'étant plus vraiment à jour, les performances n'étaient plus au rendez-vous. Astro a complètement corrigé ça.\n\nMon score de performance \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\" hreflang=\"en\" lang=\"en\">PageSpeed\u003C/a> était tombé à 77/100. Grâce à Astro je retrouve un solide **95/100** sans optimisation particulière. Avec quelques efforts sur le poids des ressources, je retrouve ce bon vieux 100/100.\n\nJ'ai ensuite fait un travail de modernisation du code. Bonjour variables CSS et au-revoir les `media queries`. En vrac, voici certaines améliorations que j'ai mises en place :\n\n- `flexbox` et `grid` pour adapter la mise en page aux différentes tailles d'écran ;\n- variables CSS pour les couleurs, les tailles de polices et les marges ;\n- quelques \u003Cspan lang=\"en\">`container queries`\u003C/span> pour essayer ;\n- propriétés logiques CSS (\u003Cspan lang=\"en\">`inline`\u003C/span> et \u003Cspan lang=\"en\">`block`\u003C/span> à la place de \u003Cspan lang=\"en\">`width`\u003C/span> et \u003Cspan lang=\"en\">`height`\u003C/span> par exemple).\n\nJ'en ai profité pour publier [le code source](https://git.nardu.in/nardu.in/website-astro) sur mon dépôt git.\n\n**Mise à jour #1 :** J'ai ajouté [un flux RSS](/rss.xml) car j'utilise de plus en plus le RSS sur d'autres sites web.\n\n### Suivi des visites\n\nJ’ai supprimé le suivi des visites. J’utilisais \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\" hreflang=\"en\">umami\u003C/a> hébergé sur mon propre serveur. Aucune donnée personnelle n'était collectée et je consultais rarement les rapports.\n\nC'est sympa de voir que son site est visité, mais s'il n'y a aucun autre but derrière, c'est une ressource supplémentaire chargée pour rien par les visiteurs. Peut-être que je réactiverai le suivi lorsque j'en aurai l'utilité (autre que flatter mon égo).\n\nLes rapports de visites précédents sont consultables sur [ce lien.](https://stat.nardu.in/share/nJSt1tfS/nardu.in)\n\n### Contenu\n\n- J'ai ajouté une page [références](/references/) pour lister certains de mes projets.\n- J'ai également ajouté [une page](/veille/) où je répertorie des choses intéressantes trouvées sur le web.\n\n## Projets annexes\n\nJe continue d'enseigner le développement web cette année. Afin d'étoffer mes supports de cours, j'ai mis en place un mini site de documentation disponible à l'adresse [3-w.fr](https://3-w.fr/) (adresse dont je suis très fier).\n\nIl faut que j'arrive à être plus régulier dans sa mise à jour mais j'ai bon espoir que la plateforme aide les élèves à progresser !\n\n**Plus de trucs bientôt!**","src/content/articles/fr/2023.md","d97f4a5af975333f",{"html":280,"metadata":281},"\u003Cp>Cet article sera mis à jour lorsque j’aurai des nouveautés à partager au cours de l’année 2023.\u003C/p>\n\u003Ch2 id=\"le-site\">Le site\u003C/h2>\n\u003Ch3 id=\"technologies\">Technologies\u003C/h3>\n\u003Cp>Oups… je l’ai encore (re)fait.\u003C/p>\n\u003Cp>J’ai entièrement re-développé mon site avec \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, comme prédit par moi-même \u003Ca href=\"/articles/2022/#le-site\">en 2022 !\u003C/a>\u003C/p>\n\u003Cp>Je ferai certainement un ou deux articles/fragments sur Astro et les extensions que j’ai utilisées. En tout cas c’était super comme expérience. Nuxt v2 n’étant plus vraiment à jour, les performances n’étaient plus au rendez-vous. Astro a complètement corrigé ça.\u003C/p>\n\u003Cp>Mon score de performance \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\" hreflang=\"en\" lang=\"en\">PageSpeed\u003C/a> était tombé à 77/100. Grâce à Astro je retrouve un solide \u003Cstrong>95/100\u003C/strong> sans optimisation particulière. Avec quelques efforts sur le poids des ressources, je retrouve ce bon vieux 100/100.\u003C/p>\n\u003Cp>J’ai ensuite fait un travail de modernisation du code. Bonjour variables CSS et au-revoir les \u003Ccode>media queries\u003C/code>. En vrac, voici certaines améliorations que j’ai mises en place :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>flexbox\u003C/code> et \u003Ccode>grid\u003C/code> pour adapter la mise en page aux différentes tailles d’écran ;\u003C/li>\n\u003Cli>variables CSS pour les couleurs, les tailles de polices et les marges ;\u003C/li>\n\u003Cli>quelques \u003Cspan lang=\"en\">\u003Ccode>container queries\u003C/code>\u003C/span> pour essayer ;\u003C/li>\n\u003Cli>propriétés logiques CSS (\u003Cspan lang=\"en\">\u003Ccode>inline\u003C/code>\u003C/span> et \u003Cspan lang=\"en\">\u003Ccode>block\u003C/code>\u003C/span> à la place de \u003Cspan lang=\"en\">\u003Ccode>width\u003C/code>\u003C/span> et \u003Cspan lang=\"en\">\u003Ccode>height\u003C/code>\u003C/span> par exemple).\u003C/li>\n\u003C/ul>\n\u003Cp>J’en ai profité pour publier \u003Ca href=\"https://git.nardu.in/nardu.in/website-astro\">le code source\u003C/a> sur mon dépôt git.\u003C/p>\n\u003Cp>\u003Cstrong>Mise à jour #1 :\u003C/strong> J’ai ajouté \u003Ca href=\"/rss.xml\">un flux RSS\u003C/a> car j’utilise de plus en plus le RSS sur d’autres sites web.\u003C/p>\n\u003Ch3 id=\"suivi-des-visites\">Suivi des visites\u003C/h3>\n\u003Cp>J’ai supprimé le suivi des visites. J’utilisais \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\" hreflang=\"en\">umami\u003C/a> hébergé sur mon propre serveur. Aucune donnée personnelle n’était collectée et je consultais rarement les rapports.\u003C/p>\n\u003Cp>C’est sympa de voir que son site est visité, mais s’il n’y a aucun autre but derrière, c’est une ressource supplémentaire chargée pour rien par les visiteurs. Peut-être que je réactiverai le suivi lorsque j’en aurai l’utilité (autre que flatter mon égo).\u003C/p>\n\u003Cp>Les rapports de visites précédents sont consultables sur \u003Ca href=\"https://stat.nardu.in/share/nJSt1tfS/nardu.in\">ce lien.\u003C/a>\u003C/p>\n\u003Ch3 id=\"contenu\">Contenu\u003C/h3>\n\u003Cul>\n\u003Cli>J’ai ajouté une page \u003Ca href=\"/references/\">références\u003C/a> pour lister certains de mes projets.\u003C/li>\n\u003Cli>J’ai également ajouté \u003Ca href=\"/veille/\">une page\u003C/a> où je répertorie des choses intéressantes trouvées sur le web.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"projets-annexes\">Projets annexes\u003C/h2>\n\u003Cp>Je continue d’enseigner le développement web cette année. Afin d’étoffer mes supports de cours, j’ai mis en place un mini site de documentation disponible à l’adresse \u003Ca href=\"https://3-w.fr/\">3-w.fr\u003C/a> (adresse dont je suis très fier).\u003C/p>\n\u003Cp>Il faut que j’arrive à être plus régulier dans sa mise à jour mais j’ai bon espoir que la plateforme aide les élèves à progresser !\u003C/p>\n\u003Cp>\u003Cstrong>Plus de trucs bientôt!\u003C/strong>\u003C/p>",{"headings":282,"imagePaths":294,"frontmatter":295},[283,284,285,288,291],{"depth":150,"slug":262,"text":263},{"depth":154,"slug":188,"text":189},{"depth":154,"slug":286,"text":287},"suivi-des-visites","Suivi des visites",{"depth":154,"slug":289,"text":290},"contenu","Contenu",{"depth":150,"slug":292,"text":293},"projets-annexes","Projets annexes",[],{"title":174,"subtitle":272,"lang":16,"slug":269,"excerpt":296,"tags":297,"type":61,"createdAt":203,"updatedAt":204},"Suite des évolutions.",[140],"after-effects-expressions",{"id":298,"data":300,"body":304,"filePath":305,"digest":306,"rendered":307},{"title":66,"subtitle":301,"lang":16,"tags":302,"type":61,"slug":298,"createdAt":303,"draft":72},"En cours de traduction, revenez bientôt ;)",[70],["Date","2019-04-24T09:00:00.000Z"],"[Retour aux articles](/articles)","src/content/articles/fr/after-effects-expressions.md","884d725859a7bab5",{"html":308,"metadata":309},"\u003Cp>\u003Ca href=\"/articles\">Retour aux articles\u003C/a>\u003C/p>",{"headings":310,"imagePaths":311,"frontmatter":312},[],[],{"title":66,"subtitle":301,"lang":16,"draft":72,"slug":298,"excerpt":301,"tags":313,"type":61,"createdAt":314},[70],"2019-04-24T09:00:00.000Z","faq",{"id":315,"data":317,"body":322,"filePath":323,"digest":324,"rendered":325},{"title":318,"subtitle":319,"lang":16,"tags":320,"type":61,"slug":315,"createdAt":321},"Accessibilité, sobriété et F.A.Q.","Explications sur ma vision et mon fonctionnement.",[140],["Date","2022-06-22T15:34:45.000Z"],"## l'Accessibilité\n\n### Quèsaco ?\n\nD'après [access42 :](https://access42.net)\n\n> L’accessibilité numérique est un droit fondamental. C’est la possibilité pour toutes et tous d’utiliser les outils informatiques, quelle que soit leur façon d’y accéder.\n\nAinsi, lorsque je \u003Cspan lang=\"en\">design\u003C/span> ou développe un site web, je fais le maximum pour que **n'importe quel visiteur** puisse l'utiliser. On pourrait croire que cela rajoute une charge de travail ou un délai allongé de réalisation mais **ce n'est pas le cas !**\n\nLorsqu'un site est pensé et conçu avec l'accessibilité en tête, il ne prend **pas plus de temps** qu'un projet qui ne le fait pas. En revanche, **corriger** un site existant qui n'a pas bénéficié de cette réflexion en amont **demande beaucoup plus d'efforts.**\n\n### Pourquoi c'est important ?\n\nAprès avoir été sensibilisé à l'accessibilité et aux [situations frustrantes voire bloquantes](https://www.france24.com/fr/info-en-continu/20220520-internet-parcours-d-obstacles-pour-les-aveugles) que rencontrent les personnes handicapées sur le web, j'ai décidé de tout faire pour me former et travailler en connaissance de cause. Il m'a semblé que proposer des sites utilisables par le plus grand nombre devait être la norme.\n\n## l'Éco-conception\n\n### Quèsaco ?\n\nD'après le collectif [\u003Cspan lang=\"en\">green it\u003C/span> :](https://www.greenit.fr)\n\n> L’éco-conception de service numérique consiste à améliorer l’efficience des applications dès leur conception pour réduire les impacts environnementaux et économiques associés tout en améliorant significativement l’expérience utilisateur.\n\nIl s'agit ici pour moi de créer des produits les plus sobres possibles. C'est-à-dire de développer ou d'utiliser une fonctionnalité uniquement si elle est indispensable.\n\nPar exemple, mettre en place **un formulaire de contact** sur un site web implique plusieurs choses :\n\n- développer un formulaire\n- envoyer les données au serveur\n- vérifier les données envoyées\n- envoyer les données par mail\n- confirmer l'envoi du mail (en fournissant une copie)\n- gérer les erreurs à chaque étape\n\nUn site statique seul ne peut pas faire tout ça. Il faut obligatoirement un serveur et un langage capable d'effectuer ces opérations (ou un prestataire qui s'en charge). C'est pourquoi je recommande une adresse email et un numéro de téléphone comme moyen de contact plutôt qu'un formulaire. Dans le cas d'un questionnaire ou autre situation particulière, un formulaire est tout à fait envisageable.\n\n### Pourquoi c'est important ?\n\nL'éco-conception fait beaucoup de bien à la qualité globale d'un site et à l'expérience des visiteurs. En effet, étant réalisé uniquement avec ce dont il a besoin, il aura tendance à être plus léger, mieux optimisé, plus rapide, etc.\n\n## F.A.Q.\n\n### Cette démarche est-elle opportuniste ?\n\n**Non.** Il est vrai que l'accessibilité et, surtout, l'éco-conception, commencent à être « tendance ». On pourrait donc croire que j'en profite pour faire du \u003Cspan lang=\"en\">business\u003C/span>. Je considère cependant que c'est ma responsabilité de créer des sites web accessibles et éco-conçus **par défaut.**\n\n### Un site accessible est-il plus cher ?\n\n**Oui et non.** Oui car si on demande un audit, il faudra payer la société qui le réalise. De mon côté, je ne fais pas payer l'accessibilité plus cher sur mes factures étant donné que je travaille ainsi par défaut.\nEn revanche, j'augmente mes tarifs suite à l'obtention de certifications relatives à mon activité.\n\n### Mon site sera-t-il 100 % accessible ?\n\n**Non,** je ne suis pas en mesure de garantir ou de certifier la conformité totale d'un site au [référentiel général d'amélioration de l'accessibilité.](https://www.numerique.gouv.fr/publications/rgaa-accessibilite/) Seul un audit exécuté par une entreprise apte à le réaliser peut certifier la conformité d'un site. Cependant, je peux vous accompagner avant et après l'audit afin d'anticiper puis de corriger les critères d'accessibilité requis. [Access42](https://access42.net/) et [Tanaguru](https://www.tanaguru.com/) font parties de ces entreprises spécialisées.\n\n### Pourquoi ne pas utiliser un outil automatique ?\n\nCar ces outils dits de “surcouche” (dont il ne faut pas prononcer le nom [sous peine de procès](https://www.lalutineduweb.fr/aide-frais-avocate-proces-contre-faciliti/)), ne sont pas des solutions micracles. Lisez [cet article](https://www.lalutineduweb.fr/surcouche-accessibilite-web-mensonges-boules-gommes/) d'une experte en accessibilité et/ou [ce test](https://blog.empreintedigitale.fr/2021/06/01/outils-de-surcouche-daccessibilite-que-valent-ils-vraiment/) de différents outils pour en savoir plus.\n\n### Un site éco-conçu et accessible peut-il être beau ?\n\n**Oui, évidemment.** Je vous laisse juger par vous-même avec [cette liste](https://lowww.directory/) de sites éco-conçus. En ce qui concerne l'accessibilité, elle n'impacte que très peu le \u003Cspan lang=\"en\">design\u003C/span> global d'un site. Même si plusieurs critères visuels existent (contrastes, taille du texte, etc.), elle se concentre essentiellement sur le fonctionnement et l'utilisation d'un produit.","src/content/articles/fr/faq.md","65e9e60bcd00806c",{"html":326,"metadata":327},"\u003Ch2 id=\"laccessibilité\">l’Accessibilité\u003C/h2>\n\u003Ch3 id=\"quèsaco\">Quèsaco ?\u003C/h3>\n\u003Cp>D’après \u003Ca href=\"https://access42.net\">access42 :\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>L’accessibilité numérique est un droit fondamental. C’est la possibilité pour toutes et tous d’utiliser les outils informatiques, quelle que soit leur façon d’y accéder.\u003C/p>\n\u003C/blockquote>\n\u003Cp>Ainsi, lorsque je \u003Cspan lang=\"en\">design\u003C/span> ou développe un site web, je fais le maximum pour que \u003Cstrong>n’importe quel visiteur\u003C/strong> puisse l’utiliser. On pourrait croire que cela rajoute une charge de travail ou un délai allongé de réalisation mais \u003Cstrong>ce n’est pas le cas !\u003C/strong>\u003C/p>\n\u003Cp>Lorsqu’un site est pensé et conçu avec l’accessibilité en tête, il ne prend \u003Cstrong>pas plus de temps\u003C/strong> qu’un projet qui ne le fait pas. En revanche, \u003Cstrong>corriger\u003C/strong> un site existant qui n’a pas bénéficié de cette réflexion en amont \u003Cstrong>demande beaucoup plus d’efforts.\u003C/strong>\u003C/p>\n\u003Ch3 id=\"pourquoi-cest-important\">Pourquoi c’est important ?\u003C/h3>\n\u003Cp>Après avoir été sensibilisé à l’accessibilité et aux \u003Ca href=\"https://www.france24.com/fr/info-en-continu/20220520-internet-parcours-d-obstacles-pour-les-aveugles\">situations frustrantes voire bloquantes\u003C/a> que rencontrent les personnes handicapées sur le web, j’ai décidé de tout faire pour me former et travailler en connaissance de cause. Il m’a semblé que proposer des sites utilisables par le plus grand nombre devait être la norme.\u003C/p>\n\u003Ch2 id=\"léco-conception\">l’Éco-conception\u003C/h2>\n\u003Ch3 id=\"quèsaco-1\">Quèsaco ?\u003C/h3>\n\u003Cp>D’après le collectif \u003Ca href=\"https://www.greenit.fr\">\u003Cspan lang=\"en\">green it\u003C/span> :\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>L’éco-conception de service numérique consiste à améliorer l’efficience des applications dès leur conception pour réduire les impacts environnementaux et économiques associés tout en améliorant significativement l’expérience utilisateur.\u003C/p>\n\u003C/blockquote>\n\u003Cp>Il s’agit ici pour moi de créer des produits les plus sobres possibles. C’est-à-dire de développer ou d’utiliser une fonctionnalité uniquement si elle est indispensable.\u003C/p>\n\u003Cp>Par exemple, mettre en place \u003Cstrong>un formulaire de contact\u003C/strong> sur un site web implique plusieurs choses :\u003C/p>\n\u003Cul>\n\u003Cli>développer un formulaire\u003C/li>\n\u003Cli>envoyer les données au serveur\u003C/li>\n\u003Cli>vérifier les données envoyées\u003C/li>\n\u003Cli>envoyer les données par mail\u003C/li>\n\u003Cli>confirmer l’envoi du mail (en fournissant une copie)\u003C/li>\n\u003Cli>gérer les erreurs à chaque étape\u003C/li>\n\u003C/ul>\n\u003Cp>Un site statique seul ne peut pas faire tout ça. Il faut obligatoirement un serveur et un langage capable d’effectuer ces opérations (ou un prestataire qui s’en charge). C’est pourquoi je recommande une adresse email et un numéro de téléphone comme moyen de contact plutôt qu’un formulaire. Dans le cas d’un questionnaire ou autre situation particulière, un formulaire est tout à fait envisageable.\u003C/p>\n\u003Ch3 id=\"pourquoi-cest-important-1\">Pourquoi c’est important ?\u003C/h3>\n\u003Cp>L’éco-conception fait beaucoup de bien à la qualité globale d’un site et à l’expérience des visiteurs. En effet, étant réalisé uniquement avec ce dont il a besoin, il aura tendance à être plus léger, mieux optimisé, plus rapide, etc.\u003C/p>\n\u003Ch2 id=\"faq\">F.A.Q.\u003C/h2>\n\u003Ch3 id=\"cette-démarche-est-elle-opportuniste\">Cette démarche est-elle opportuniste ?\u003C/h3>\n\u003Cp>\u003Cstrong>Non.\u003C/strong> Il est vrai que l’accessibilité et, surtout, l’éco-conception, commencent à être « tendance ». On pourrait donc croire que j’en profite pour faire du \u003Cspan lang=\"en\">business\u003C/span>. Je considère cependant que c’est ma responsabilité de créer des sites web accessibles et éco-conçus \u003Cstrong>par défaut.\u003C/strong>\u003C/p>\n\u003Ch3 id=\"un-site-accessible-est-il-plus-cher\">Un site accessible est-il plus cher ?\u003C/h3>\n\u003Cp>\u003Cstrong>Oui et non.\u003C/strong> Oui car si on demande un audit, il faudra payer la société qui le réalise. De mon côté, je ne fais pas payer l’accessibilité plus cher sur mes factures étant donné que je travaille ainsi par défaut.\nEn revanche, j’augmente mes tarifs suite à l’obtention de certifications relatives à mon activité.\u003C/p>\n\u003Ch3 id=\"mon-site-sera-t-il-100-accessible\">Mon site sera-t-il 100 % accessible ?\u003C/h3>\n\u003Cp>\u003Cstrong>Non,\u003C/strong> je ne suis pas en mesure de garantir ou de certifier la conformité totale d’un site au \u003Ca href=\"https://www.numerique.gouv.fr/publications/rgaa-accessibilite/\">référentiel général d’amélioration de l’accessibilité.\u003C/a> Seul un audit exécuté par une entreprise apte à le réaliser peut certifier la conformité d’un site. Cependant, je peux vous accompagner avant et après l’audit afin d’anticiper puis de corriger les critères d’accessibilité requis. \u003Ca href=\"https://access42.net/\">Access42\u003C/a> et \u003Ca href=\"https://www.tanaguru.com/\">Tanaguru\u003C/a> font parties de ces entreprises spécialisées.\u003C/p>\n\u003Ch3 id=\"pourquoi-ne-pas-utiliser-un-outil-automatique\">Pourquoi ne pas utiliser un outil automatique ?\u003C/h3>\n\u003Cp>Car ces outils dits de “surcouche” (dont il ne faut pas prononcer le nom \u003Ca href=\"https://www.lalutineduweb.fr/aide-frais-avocate-proces-contre-faciliti/\">sous peine de procès\u003C/a>), ne sont pas des solutions micracles. Lisez \u003Ca href=\"https://www.lalutineduweb.fr/surcouche-accessibilite-web-mensonges-boules-gommes/\">cet article\u003C/a> d’une experte en accessibilité et/ou \u003Ca href=\"https://blog.empreintedigitale.fr/2021/06/01/outils-de-surcouche-daccessibilite-que-valent-ils-vraiment/\">ce test\u003C/a> de différents outils pour en savoir plus.\u003C/p>\n\u003Ch3 id=\"un-site-éco-conçu-et-accessible-peut-il-être-beau\">Un site éco-conçu et accessible peut-il être beau ?\u003C/h3>\n\u003Cp>\u003Cstrong>Oui, évidemment.\u003C/strong> Je vous laisse juger par vous-même avec \u003Ca href=\"https://lowww.directory/\">cette liste\u003C/a> de sites éco-conçus. En ce qui concerne l’accessibilité, elle n’impacte que très peu le \u003Cspan lang=\"en\">design\u003C/span> global d’un site. Même si plusieurs critères visuels existent (contrastes, taille du texte, etc.), elle se concentre essentiellement sur le fonctionnement et l’utilisation d’un produit.\u003C/p>",{"headings":328,"imagePaths":362,"frontmatter":363},[329,332,335,338,341,343,345,347,350,353,356,359],{"depth":150,"slug":330,"text":331},"laccessibilité","l’Accessibilité",{"depth":154,"slug":333,"text":334},"quèsaco","Quèsaco ?",{"depth":154,"slug":336,"text":337},"pourquoi-cest-important","Pourquoi c’est important ?",{"depth":150,"slug":339,"text":340},"léco-conception","l’Éco-conception",{"depth":154,"slug":342,"text":334},"quèsaco-1",{"depth":154,"slug":344,"text":337},"pourquoi-cest-important-1",{"depth":150,"slug":315,"text":346},"F.A.Q.",{"depth":154,"slug":348,"text":349},"cette-démarche-est-elle-opportuniste","Cette démarche est-elle opportuniste ?",{"depth":154,"slug":351,"text":352},"un-site-accessible-est-il-plus-cher","Un site accessible est-il plus cher ?",{"depth":154,"slug":354,"text":355},"mon-site-sera-t-il-100-accessible","Mon site sera-t-il 100 % accessible ?",{"depth":154,"slug":357,"text":358},"pourquoi-ne-pas-utiliser-un-outil-automatique","Pourquoi ne pas utiliser un outil automatique ?",{"depth":154,"slug":360,"text":361},"un-site-éco-conçu-et-accessible-peut-il-être-beau","Un site éco-conçu et accessible peut-il être beau ?",[],{"title":318,"subtitle":319,"lang":16,"slug":315,"excerpt":364,"tags":365,"type":61,"createdAt":223},"Pourquoi, comment et surtout quèsaco.",[140],"gratuiste",{"id":366,"data":368,"body":374,"filePath":375,"digest":376,"rendered":377},{"title":227,"subtitle":369,"lang":16,"tags":370,"type":61,"slug":366,"createdAt":372,"updatedAt":373},"Ou le travail gratuit.",[371,140],"Graphisme",["Date","2017-05-27T07:47:36.000Z"],["Date","2022-12-27T15:36:06.000Z"],"## Gratuiste, qu’est-ce que c’est ?\n\nDans le monde francophone du graphisme, le terme gratuiste est un terme péjoratif employé pour dénoncer certaines conditions de travail. Les plus répandues sont les concours d’affiche/de logo, les clients qui demandent que vous commenciez à travailler sans vous payer et qui paieront si ça leur convient, les appels d’offre non défrayés, etc. \nDe plus en plus, la communauté s’élève contre ces pratiques et les [dénonce.](https://twitter.com/PayeTonAffiche)\n\n> “ On n’est pas des gratuistes ! ”\n\nComprendre : nous exerçons un métier à part entière qui requiert de nombreuses connaissances et beaucoup de travail, payez-nous. Rien d’extravagant en somme. Regardez [cette vidéo](https://youtu.be/essNmNOrQto) qui transpose ces pratiques à des métiers “ standards ” et [celle-ci](https://youtu.be/DsstOs-K7gk) qui explique en détails le processus actuel.\n\n## T’es débile du coup ?\n\nJ’aime à penser que non. Je n’aspire pas à devenir gratuiste dans ce sens là du terme. J’aimerais lui en donner un nouveau, plus positif. Dans les conditions précédentes, gratuiste est en effet une situation que personne (graphiste ou autre) n’aimerait expérimenter et encore moins promouvoir. À part peut-être des “ clients ” sans scrupules.\n\nÉtant encore assez nouveau sur le marché du travail, je n’ai pas la solution de faire des dons à des associations, qu’ils soient financiers ou autre. \nNéanmoins, j’ai envie d’aider à mon échelle et selon mes capacités.\n\n## Le concept\n\nJe compte proposer mes services et mes compétences gratuitement à des associations caritatives/ONG qui viennent en aide aux personnes dans le besoin ou aux animaux. \nCe type de prestation porte le nom de “ **pro bono publico** ” – “ **pour le bien public** ”.\n\nCette pratique existe essentiellement dans les milieux juridiques. Je pense cependant qu’elle n’est pas incompatible avec le métier de graphiste.\n\n> Graphiste pro bono, pourquoi pas ?\n\n## Quels genres de services ?\n\nEn toute logique, le type qui rend service à l’association, qui peut faire une différence. À mes yeux, essentiellement des sites internet. Je pense qu’un site web aura bien plus d’intérêt qu’un nouveau logo. Pourquoi pas des flyers/des petits visuels pour des pin’s/badges.\n\n### En résumé :\n\n- maquette de site web\n- intégration front-end (en dur ou via wordpress) du site\n- gestion de la mise en ligne du site\n- newsletter (design et/ou intégration)\n- flyers\n- autres petites demandes\n\nVous pouvez avoir un aperçu de mon travail [sur ce même site.](/) J’ai déjà eu l’occasion de travailler pour :\n\n- [Cygnal](/projets/cygnal)\n- [OpenMole](https://openmole.org/)\n- [Good-it](https://good-it.org)\n\n## Dans quelles conditions ?\n\n- l’association doit être active\n- elle doit porter des valeurs que je partage\n- elle doit pouvoir me montrer ses actions\n- elle ne doit pas avoir les moyens de se payer un graphiste\n\n## C’est un peu trop beau pour être vrai ton truc…\n\nIl faut garder à l’esprit que je compte travailler bénévolement pendant mon temps libre. Je ne cherche pas une relation client habituelle puisqu’il n’y aura pas de client à proprement parler. Cela me permettra d’éviter des délais intenables, des retours par milliers et toute obligation de finir le travail en cas de coup fourré.\nJe préfère être franc là-dessus même si je ne me fais pas trop de soucis sur les mœurs du monde associatif. Aussi, faudra-t-il être un peu patient si jamais j’ai déjà une demande en cours.\n\nSi vous êtes intéressés, [envoyez-moi un mail !](mailto:contac@nardu.in)\n\n## Qu’est-ce que t’y gagnes toi ?\n\nSimplement la satisfaction d’avoir aidé, à mon échelle, des personnes en difficulté. Je ne fais pas ça pour me faire de la pub ou pour étayer mon portfolio. Cela me permettra en revanche de travailler sur d’autres sujets et dans un cadre différent.","src/content/articles/fr/gratuiste.md","80c20493583a842c",{"html":378,"metadata":379},"\u003Ch2 id=\"gratuiste-quest-ce-que-cest\">Gratuiste, qu’est-ce que c’est ?\u003C/h2>\n\u003Cp>Dans le monde francophone du graphisme, le terme gratuiste est un terme péjoratif employé pour dénoncer certaines conditions de travail. Les plus répandues sont les concours d’affiche/de logo, les clients qui demandent que vous commenciez à travailler sans vous payer et qui paieront si ça leur convient, les appels d’offre non défrayés, etc.\u003Cbr>\nDe plus en plus, la communauté s’élève contre ces pratiques et les \u003Ca href=\"https://twitter.com/PayeTonAffiche\">dénonce.\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>“ On n’est pas des gratuistes ! ”\u003C/p>\n\u003C/blockquote>\n\u003Cp>Comprendre : nous exerçons un métier à part entière qui requiert de nombreuses connaissances et beaucoup de travail, payez-nous. Rien d’extravagant en somme. Regardez \u003Ca href=\"https://youtu.be/essNmNOrQto\">cette vidéo\u003C/a> qui transpose ces pratiques à des métiers “ standards ” et \u003Ca href=\"https://youtu.be/DsstOs-K7gk\">celle-ci\u003C/a> qui explique en détails le processus actuel.\u003C/p>\n\u003Ch2 id=\"tes-débile-du-coup\">T’es débile du coup ?\u003C/h2>\n\u003Cp>J’aime à penser que non. Je n’aspire pas à devenir gratuiste dans ce sens là du terme. J’aimerais lui en donner un nouveau, plus positif. Dans les conditions précédentes, gratuiste est en effet une situation que personne (graphiste ou autre) n’aimerait expérimenter et encore moins promouvoir. À part peut-être des “ clients ” sans scrupules.\u003C/p>\n\u003Cp>Étant encore assez nouveau sur le marché du travail, je n’ai pas la solution de faire des dons à des associations, qu’ils soient financiers ou autre.\u003Cbr>\nNéanmoins, j’ai envie d’aider à mon échelle et selon mes capacités.\u003C/p>\n\u003Ch2 id=\"le-concept\">Le concept\u003C/h2>\n\u003Cp>Je compte proposer mes services et mes compétences gratuitement à des associations caritatives/ONG qui viennent en aide aux personnes dans le besoin ou aux animaux.\u003Cbr>\nCe type de prestation porte le nom de “ \u003Cstrong>pro bono publico\u003C/strong> ” – “ \u003Cstrong>pour le bien public\u003C/strong> ”.\u003C/p>\n\u003Cp>Cette pratique existe essentiellement dans les milieux juridiques. Je pense cependant qu’elle n’est pas incompatible avec le métier de graphiste.\u003C/p>\n\u003Cblockquote>\n\u003Cp>Graphiste pro bono, pourquoi pas ?\u003C/p>\n\u003C/blockquote>\n\u003Ch2 id=\"quels-genres-de-services\">Quels genres de services ?\u003C/h2>\n\u003Cp>En toute logique, le type qui rend service à l’association, qui peut faire une différence. À mes yeux, essentiellement des sites internet. Je pense qu’un site web aura bien plus d’intérêt qu’un nouveau logo. Pourquoi pas des flyers/des petits visuels pour des pin’s/badges.\u003C/p>\n\u003Ch3 id=\"en-résumé\">En résumé :\u003C/h3>\n\u003Cul>\n\u003Cli>maquette de site web\u003C/li>\n\u003Cli>intégration front-end (en dur ou via wordpress) du site\u003C/li>\n\u003Cli>gestion de la mise en ligne du site\u003C/li>\n\u003Cli>newsletter (design et/ou intégration)\u003C/li>\n\u003Cli>flyers\u003C/li>\n\u003Cli>autres petites demandes\u003C/li>\n\u003C/ul>\n\u003Cp>Vous pouvez avoir un aperçu de mon travail \u003Ca href=\"/\">sur ce même site.\u003C/a> J’ai déjà eu l’occasion de travailler pour :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/projets/cygnal\">Cygnal\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"https://openmole.org/\">OpenMole\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"https://good-it.org\">Good-it\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"dans-quelles-conditions\">Dans quelles conditions ?\u003C/h2>\n\u003Cul>\n\u003Cli>l’association doit être active\u003C/li>\n\u003Cli>elle doit porter des valeurs que je partage\u003C/li>\n\u003Cli>elle doit pouvoir me montrer ses actions\u003C/li>\n\u003Cli>elle ne doit pas avoir les moyens de se payer un graphiste\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"cest-un-peu-trop-beau-pour-être-vrai-ton-truc\">C’est un peu trop beau pour être vrai ton truc…\u003C/h2>\n\u003Cp>Il faut garder à l’esprit que je compte travailler bénévolement pendant mon temps libre. Je ne cherche pas une relation client habituelle puisqu’il n’y aura pas de client à proprement parler. Cela me permettra d’éviter des délais intenables, des retours par milliers et toute obligation de finir le travail en cas de coup fourré.\nJe préfère être franc là-dessus même si je ne me fais pas trop de soucis sur les mœurs du monde associatif. Aussi, faudra-t-il être un peu patient si jamais j’ai déjà une demande en cours.\u003C/p>\n\u003Cp>Si vous êtes intéressés, \u003Ca href=\"mailto:contac@nardu.in\">envoyez-moi un mail !\u003C/a>\u003C/p>\n\u003Ch2 id=\"quest-ce-que-ty-gagnes-toi\">Qu’est-ce que t’y gagnes toi ?\u003C/h2>\n\u003Cp>Simplement la satisfaction d’avoir aidé, à mon échelle, des personnes en difficulté. Je ne fais pas ça pour me faire de la pub ou pour étayer mon portfolio. Cela me permettra en revanche de travailler sur d’autres sujets et dans un cadre différent.\u003C/p>",{"headings":380,"imagePaths":405,"frontmatter":406},[381,384,387,390,393,396,399,402],{"depth":150,"slug":382,"text":383},"gratuiste-quest-ce-que-cest","Gratuiste, qu’est-ce que c’est ?",{"depth":150,"slug":385,"text":386},"tes-débile-du-coup","T’es débile du coup ?",{"depth":150,"slug":388,"text":389},"le-concept","Le concept",{"depth":150,"slug":391,"text":392},"quels-genres-de-services","Quels genres de services ?",{"depth":154,"slug":394,"text":395},"en-résumé","En résumé :",{"depth":150,"slug":397,"text":398},"dans-quelles-conditions","Dans quelles conditions ?",{"depth":150,"slug":400,"text":401},"cest-un-peu-trop-beau-pour-être-vrai-ton-truc","C’est un peu trop beau pour être vrai ton truc…",{"depth":150,"slug":403,"text":404},"quest-ce-que-ty-gagnes-toi","Qu’est-ce que t’y gagnes toi ?",[],{"title":227,"subtitle":369,"lang":16,"slug":366,"excerpt":407,"tags":408,"type":61,"createdAt":238,"updatedAt":409},"J’ai cherché un moyen de mettre mes compétences au service d’autrui et je pense avoir trouvé: je vais travailler gratuitement pour des associations.",[371,140],"2022-12-27T15:36:06.000Z","video-compression",{"id":410,"data":412,"body":304,"filePath":417,"digest":418,"rendered":419},{"title":413,"subtitle":301,"lang":16,"tags":414,"type":61,"slug":410,"createdAt":415,"updatedAt":416,"draft":72},"Compression vidéo",[70],["Date","2021-05-05T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"src/content/articles/fr/video-compression.md","2296c41874b23b3d",{"html":308,"metadata":420},{"headings":421,"imagePaths":422,"frontmatter":423},[],[],{"title":413,"subtitle":301,"lang":16,"draft":72,"slug":410,"excerpt":424,"tags":425,"type":61,"createdAt":426,"updatedAt":170},"Pas encore traduit",[70],"2021-05-05T09:00:00.000Z","fragments",["Map",429,430,441,442,452,453,462,463,473,474,484,485,539,540,556,557,574,575,587,588,651,652,713,714,748,749,782,783,806,807,848,849],"en-image-full",{"id":429,"data":431,"body":438,"filePath":439,"digest":440,"deferredRender":72},{"title":432,"subtitle":209,"lang":68,"tags":433,"type":435,"slug":429,"createdAt":436,"updatedAt":437,"draft":72},"Full width image",[434],"CSS","snippets",["Date","2020-09-15T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"[Go back to available snippets](/en/snippets)","src/content/fragments/en/image-full.mdx","2e3dddf593f6d72f","en-super-cookies",{"id":441,"data":443,"body":449,"filePath":450,"digest":451,"deferredRender":72},{"title":444,"subtitle":445,"lang":68,"tags":446,"type":435,"slug":441,"createdAt":448},"The best cookies","Consentless biscuits.",[447],"food",["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Vegetalian version\n\n### Ingredients\n\n- 250 grams of flour\n- 70 grams of muscovado/vergeoise sugar (unrefined)\n- 20 grams of brown sugar\n- 1 pinch of salt\n- 1 tablespoon of baking powder\n- 3/4 of aquafaba from 400g of chickpea (chickpea water)\n- 125 grams of coconut oil\n- 2 teaspoons of maple syrup\n- 1 chocolate bar (black) cut in “ chunks ”\n\n### Method\n\n- if necessary, melt the coconut oil over low heat\n- meanwhile, mix all the dry ingredients\n- add all liquid ingredients (oil, aquafaba, maple syrup)\n- mix well\n- add the chocolate\n- mix well (fig. 1)\n\n### Baking\n\nForm balls with the obtained mixture on a baking sheet.\nBake for 9 minutes at 210 degrees (Celsius) - fan setting (fig. 2).\n\n## Non vegetalian version\n\n### Ingredients\n\n- 250 grams of flour\n- 70 grams of muscovado/vergeoise sugar (unrefined)\n- 20 grams of brown sugar\n- 1 pinch of salt\n- 1 table spoon of baking powder\n- 1 egg\n- 125 grams of melted butter\n- 2 teaspoons of honey\n- 1 chocolate bar (black) cut in “ chunks ”\n\n### Method\n\n- melt butter over low heat\n- meanwhile, mix all dry ingredients\n- add all liquid ingredients (melted butter, egg, honey)\n- mix well\n- add the chocolate\n- mix well (fig. 1)\n\n### Baking\n\nForm balls with the obtained mixture on a baking sheet.\nBake for 9 minutes at 210 degrees (Celsius) - fan setting (fig. 2).\n\n## Notes\n\nChocolate can be replaced by anything like nuts, raisins, legos... (don't eat legos be reasonable).\n\n## Figures\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-1.jpg'\n\twidth='753'\n\theight='1248'\n\talt='All ingredients mixed together to form a brown paste.'\n/>\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-2.jpg'\n\twidth='753'\n\theight='1248'\n\talt='The cookies are round and soft after baking.'\n/>","src/content/fragments/en/super-cookies.mdx","b0c67adad40c177c","buttons",{"id":452,"data":454,"body":459,"filePath":460,"digest":461,"deferredRender":72},{"title":455,"subtitle":456,"lang":16,"tags":457,"type":427,"slug":452,"createdAt":458,"code":72,"draft":72},"Effets de survol de boutons","Simples mais efficaces.",[434],["Date","2020-10-08T09:00:00.000Z"],"## Styles généraux\n\nTous les boutons présents utilisent ces styles comme base en guise de « reset » :\n\n> N'oubliez pas de préfixer si besoin !\n\n```css\n.btn {\n\tmargin: 20px 0;\n\tpadding: 12px 26px;\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tfont-size: 20rem; /* 20px */\n\tline-height: 1.6;\n\ttext-align: center;\n\ttext-decoration: none;\n\tfont-weight: bold;\n\tcursor: pointer;\n\tborder: none;\n\tborder-radius: 2px;\n\t-moz-appearance: none;\n\t-webkit-appearance: none;\n\tcolor: white;\n\tbackground-color: hotpink;\n\ttransition: background-color 0.3s ease;\n}\n```\n\n## Ajout d'icône\n\n\u003Cbutton role='none' class='btn btn-icon'>\n\t\u003Cspan>Icône\u003C/span>\n\u003C/button>\n\n```css\n.btn-icon {\n\tbackground-color: hotpink;\n}\n.btn-icon::before {\n\tcontent: url('./assets/svg/arrow-right-white.svg');\n\tposition: absolute;\n\twidth: 20px;\n\ttop: 50%;\n\tright: 0;\n\ttransform: translate(40px, -50%);\n\ttransition: transform ease 0.3s;\n}\n.btn-icon:hover,\n.btn-icon:focus {\n\tbackground-color: darkorchid;\n}\n.btn-icon:hover::before,\n.btn-icon:focus::before {\n\ttransform: translate(-10px, -50%);\n}\n.btn-icon > span {\n\tdisplay: inline-block;\n\twidth: 100%;\n\theight: 100%;\n\ttransition: transform 0.3s ease;\n}\n.btn-icon:hover > span,\n.btn-icon:focus > span {\n\ttransform: translateX(-10px);\n}\n```\n\n## Double volet\n\n\u003Cbutton role='none' class='btn btn-rideau'>\n\t\u003Cspan>Volet\u003C/span>\n\u003C/button>\n\n```css\n.btn-rideau {\n\tborder: 2px solid #10113a;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n\ttransition: color 0.3s ease;\n}\n.btn-rideau:hover {\n\tcolor: white;\n}\n.btn-rideau::before {\n\tbackground: hotpink;\n}\n.btn-rideau::after {\n\tbackground: darkorchid;\n}\n.btn-rideau::before,\n.btn-rideau::after {\n\tcontent: '';\n\tposition: absolute;\n\theight: 100%;\n\twidth: 100%;\n\tbottom: 100%;\n\tleft: 0;\n\tz-index: -1;\n\ttransition: transform 0.3s;\n\ttransition-timing-function: ease;\n\ttransition-timing-function: cubic-bezier(0.75, 0, 0.125, 1);\n}\n.btn-rideau:hover::before,\n.btn-rideau:hover::after,\n.btn-rideau:focus::before,\n.btn-rideau:focus::after {\n\ttransform: translateY(100%);\n}\n.btn-rideau:hover::after,\n.btn-rideau:focus::after {\n\ttransition-delay: 0.175s;\n}\n```\n\n## Dégradé animé\n\n\u003Cbutton role='none' class='btn btn-gradient'>\n\t\u003Cspan>Dégradé\u003C/span>\n\u003C/button>\n\n```css\n.btn-gradient {\n\tbackground: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);\n\tbackground-size: 400% 400%;\n\tbackground-position: 0% 50%;\n\tanimation: GradientReverse 0.5s ease 1 normal forwards;\n}\n.btn-gradient:hover,\n.btn-gradient:focus {\n\tanimation: Gradient 0.5s ease 1 normal forwards;\n}\n@keyframes Gradient {\n\t0% {\n\t\tbackground-position: 0% 50%;\n\t}\n\t100% {\n\t\tbackground-position: 100% 100%;\n\t}\n}\n@keyframes GradientReverse {\n\t0% {\n\t\tbackground-position: 100% 100%;\n\t}\n\t100% {\n\t\tbackground-position: 0% 50%;\n\t}\n}\n```\n\n## Échelle non desctructrice\n\n\u003Cbutton role='none' class='btn btn-scale'>\n\t\u003Cspan>Échelle\u003C/span>\n\u003C/button>\n\n```css\n.btn-scale {\n\toverflow: visible;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n}\n.btn-scale::after {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n\twidth: 100%;\n\tborder: 2px solid #10113a;\n\tborder-radius: 2px;\n\ttransition: transform 0.3s ease;\n}\n.btn-scale:hover::after,\n.btn-scale:focus::after {\n\ttransform: scale(1.1);\n}\n```","src/content/fragments/fr/buttons.mdx","f5d7b03520f96b04","image-full",{"id":462,"data":464,"body":470,"filePath":471,"digest":472,"deferredRender":72},{"title":465,"subtitle":466,"lang":16,"tags":467,"type":427,"slug":462,"createdAt":468,"updatedAt":469},"Image pleine largeur","Casser le conteneur.",[434],["Date","2020-09-15T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Image inline\n\nOn est parfois obligé d'utiliser des images dans des balises `img` plutôt que dans un `background` en css. Comment faire alors pour que l'image sorte de son conteneur pour en faire une bannière ? Exemple pratique à partir de ce même site.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_container_9e3939b3ae.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Contexte\n\nConsidérons le html suivant :\n\n```html\n\u003Csection class=\"container\">\n\t\u003Cdiv class=\"hero\">\n\t\t\u003Cimg class=\"hero__image\" src=\"hero.img\" />\n\t\u003C/div>\n\u003C/section>\n```\n\nEt le style suivant :\n\n```css\n.container {\n\tpadding: 0 14px;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tmax-width: 1040px;\n}\nimg {\n\tmax-width: 100%;\n\theight: auto;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_original_d49f0d11bf.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Déborder du conteneur\n\nAfin de faire prendre à l'image toute la largeur, on agit sur son conteneur :\n\n```css\n.hero {\n\tmargin-left: calc(50% - 50vw);\n\tposition: relative;\n\twidth: 100vw;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_full_2a902f9539.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Faire une bannière\n\nOn peut alors réduire la hauteur du conteneur pour obtenir une bannière plutôt que l'image entière et faire correspondre la hauteur de l'image à la hauteur du conteneur :\n\n```css\n.hero {\n\theight: 200px;\n}\n.hero__image {\n\theight: 100%;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_height_81b4ce969a.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nIl faut ensuite forcer l'image à prendre toute la largeur du conteneur :\n\n```css\n.hero__image {\n\twidth: 100%;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_deformed_479046d2cb.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nPas top…\n\n### J'ai cassé l'image…\n\n**ENFIN** le code magique pour redonner son ratio à l'image sans la déformer :\n\n```css\n.hero__image {\n\tobject-fit: cover;\n\tobject-position: center; /* à positionner comme on veut */\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_6c164e82b3.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nCette technique s'apparente à l'utilisation d'une image de background mais en dur 😁\n\n## TL;DR\n\nLe code complet :\n\n```css\n.hero {\n\tmargin-left: calc(50% - 50vw);\n\tposition: relative;\n\twidth: 100vw;\n\theight: 200px;\n}\n.hero__image {\n\twidth: 100%;\n\theight: 100%;\n\t-o-object-fit: cover;\n\tobject-fit: cover;\n\t-o-object-position: center;\n\tobject-position: center;\n}\n```","src/content/fragments/fr/image-full.mdx","91ebd97eef5cb8a4","super-cookies",{"id":473,"data":475,"body":481,"filePath":482,"digest":483,"deferredRender":72},{"title":476,"subtitle":477,"lang":16,"tags":478,"type":427,"slug":473,"createdAt":480},"Les meilleurs cookies","Des gâteaux sans consentement.",[479],"cuisine",["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Version végétalienne\n\n### Ingrédients\n\n- 250 grammes de farine\n- 70 grammes de sucre muscovado/vergeoise (non raffiné)\n- 20 grammes de cassonade\n- 1 pincée de sel\n- 1 cuillère à soupe de levure\n- 3/4 de l'aquafaba de 400g de pois chiche (l'eau des pois chiche)\n- 125 grammes d'huile de noix de coco\n- 2 cuillères à café de sirop d'érable\n- 1 plaquette de chocolat (noir) coupée en “ chunks ”\n\n### Méthode\n\n- faire fondre si besoin l'huile de noix de coco à feu doux\n- mélanger tous les ingrédients secs pendant ce temps\n- ajouter tous les ingrédients liquides (huile, aquafaba, sirop d'érable)\n- bien mélanger\n- ajouter le chocolat\n- bien mélanger (fig. 1)\n\n### Cuisson\n\nRéaliser des boules avec la mixture obtenue sur une plaque de cuisson.\nCuire 9 minutes à 210 degrés (celsius) - chaleur tournante (fig. 2).\n\n## Version non végétalienne\n\n### Ingrédients\n\n- 250 grammes de farine\n- 70 grammes de sucre muscovado/vergeoise (non raffiné)\n- 20 grammes de cassonade\n- 1 pincée de sel\n- 1 cuillère à soupe de levure\n- 1 œuf\n- 125 grammes de beurre fondu\n- 2 cuillères à café de miel\n- 1 plaquette de chocolat (noir/blanc/les deux) coupée en “ chunks ”\n\n### Méthode\n\n- faire fondre le beurre à feu doux\n- mélanger tous les ingrédients secs pendant ce temps\n- ajouter tous les ingrédients liquides (beurre fondu, œuf, miel)\n- bien mélanger\n- ajouter le chocolat\n- bien mélanger (fig. 1)\n\n### Cuisson\n\nRéaliser des boules avec la mixture obtenue sur une plaque de cuisson.\nCuire 9 minutes à 210 degrés (celsius) - chaleur tournante (fig. 2).\n\n## Notes\n\nLe chocolat peut-être remplacé par n'importe quoi comme des noix, des raisins secs, des légos… (mangez pas des légos soyez sérieux).\n\n## Figures\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-1.jpg'\n\twidth='753'\n\theight='1248'\n\talt='Tous les ingrédients mélangés forment une pâte marron.'\n/>\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-2.jpg'\n\twidth='753'\n\theight='1248'\n\talt='Les cookies cuits sont bombés et très moelleux.'\n/>","src/content/fragments/fr/super-cookies.mdx","f7a802e0b68cb04a","en-toulouse-fun",{"id":484,"data":486,"body":492,"filePath":493,"digest":494,"rendered":495},{"title":487,"subtitle":488,"lang":68,"tags":489,"type":435,"slug":484,"createdAt":491},"Toulouse yourself","Only the bestest",[490],"lifestyle",["Date","2022-06-22T15:34:45.000Z"],"Here is my list of great places to go to when in Toulouse. There are of course a lot of other great places to go to, these are just my all time favourite. \n**It's always a good idea to make a reservation!**\n\n## Restaurants\n\n### French cuisine\n\n- [Solides](https://www.solides.fr/) — semi-gastronomic\n- [Les impulsifs](https://les-impulsifs-toulouse.eatbu.com/?lang=en) — semi-gastronomic\n- [Sixta](https://sixta-toulouse.fr/) — vege/vegan/gluten friendly\n- [Attila](https://attila.site-solocal.com/) — great **fish restaurant,** just above the Victor Hugo market\n- [Chez Emile](https://www.restaurant-emile.com/) - best [cassoulet](https://en.wikipedia.org/wiki/Cassoulet) in town (or so I'm told)\n\n### Korean\n\n- [Le ptit Louis](https://leptitlouis.fr/) — best of its kind, **only for lunch**\n- [Kongbap](https://kong-bap.com/) — street-food like\n\n### Japanese\n\n- [Iori](https://www.iori.fr/) — best ramen\n- [Japoyaki](https://www.qwant.com/maps/place/osm:node:2447719414@Japoyaki#map=16.50/43.6061725/1.4473402) — best sushi/sashimis\n\n## Drinks and snacks\n\n### Bars\n\n- [Le Bièrographe](https://www.qwant.com/maps/place/osm:node:1532531236@Le_Bi%C3%A8rographe#map=16.50/43.5986892/1.4428327) — all time favourite, **check out the typical toulouse basement**\n- [A Taula](https://www.facebook.com/ataulatolosa/) — all time favourite in summer, **amazing terrace,** also: great tapas\n- [The Hopscotch Pub](https://www.qwant.com/maps/place/osm:node:5592180378@The_Hopscotch#map=18.14/43.6006796/1.4431385) — good beers, good whiskies, good cocktials, good food\n\n### Cafés & tea rooms\n\n- [Bapz](https://www.bapz.fr/contact) — Excellent pastries / hot beverages\n- [Ô thé divin](https://fr-fr.facebook.com/%C3%94-Th%C3%A9-Divin-245018828864405/) — nice lunch options\n- [Les Rêveries d’Hercule](https://www.lesreveriesdhercule.com/) — Pottery Café, relaxing activity (ceramics need to be baked, there'll be a delay to get them back)\n- Bonus: the best bakeries in [Carmes](https://www.qwant.com/maps/place/osm:node:450165912@Boulangerie_des_Carmes#map=16.37/43.6022638/1.4439872) and [Saint-Aubin](https://www.qwant.com/maps/place/osm:node:456844404@La_P%C3%A9trie#map=18.84/43.6045088/1.4544694) — croissants, baguettes **traditions**, chocolatines and more\n\n### Wine shops\n\n- [l'envie du sud](https://www.qwant.com/maps/place/osm:node:3861692629@LEnvie#map=19.57/43.5978194/1.4443930) — amazing selection of wines and other spirits, excellent advice from the staff\n- [enoteca](https://www.qwant.com/maps/place/osm:node:3751077562@Enoteca_31#map=16.50/43.6045636/1.4531952) — smaller selection but more beers and great advice from the staff as well\n\n## Other delights\n\n### Ice creams\n\n- [Forno gusto](https://www.qwant.com/maps/place/osm:node:2462248749@Caf%C3%A9t%C3%A9ria_Gelateria#map=20.00/43.6027626/1.4421450) — only in the summer\n- [Moustache](https://www.qwant.com/maps/place/osm:node:2165543146@Glaces_Moustache#map=16.50/43.6036985/1.4350540) — lots of flavours\n\n### Cheese shop\n\n- [Xavier](https://xavier.fr/) — one of the **best of the country**, two shops in Toulouse, including one at Victor Hugo market\n- [Massembea](https://www.qwant.com/maps/place/osm:node:6164095797@Massembea#map=16.50/43.6043930/1.4539490) — a serious contender in Toulouse (weird hours)\n\n### Delicatessen\n\n- [Café Bacquié](http://cafe-bacquie.com/) — stock up on fine foods, coffees, teas and other great quality products","src/content/fragments/en/toulouse-fun.md","370491cc68079e8c",{"html":496,"metadata":497},"\u003Cp>Here is my list of great places to go to when in Toulouse. There are of course a lot of other great places to go to, these are just my all time favourite.\u003Cbr>\n\u003Cstrong>It’s always a good idea to make a reservation!\u003C/strong>\u003C/p>\n\u003Ch2 id=\"restaurants\">Restaurants\u003C/h2>\n\u003Ch3 id=\"french-cuisine\">French cuisine\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.solides.fr/\">Solides\u003C/a> — semi-gastronomic\u003C/li>\n\u003Cli>\u003Ca href=\"https://les-impulsifs-toulouse.eatbu.com/?lang=en\">Les impulsifs\u003C/a> — semi-gastronomic\u003C/li>\n\u003Cli>\u003Ca href=\"https://sixta-toulouse.fr/\">Sixta\u003C/a> — vege/vegan/gluten friendly\u003C/li>\n\u003Cli>\u003Ca href=\"https://attila.site-solocal.com/\">Attila\u003C/a> — great \u003Cstrong>fish restaurant,\u003C/strong> just above the Victor Hugo market\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.restaurant-emile.com/\">Chez Emile\u003C/a> - best \u003Ca href=\"https://en.wikipedia.org/wiki/Cassoulet\">cassoulet\u003C/a> in town (or so I’m told)\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"korean\">Korean\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://leptitlouis.fr/\">Le ptit Louis\u003C/a> — best of its kind, \u003Cstrong>only for lunch\u003C/strong>\u003C/li>\n\u003Cli>\u003Ca href=\"https://kong-bap.com/\">Kongbap\u003C/a> — street-food like\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"japanese\">Japanese\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.iori.fr/\">Iori\u003C/a> — best ramen\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2447719414@Japoyaki#map=16.50/43.6061725/1.4473402\">Japoyaki\u003C/a> — best sushi/sashimis\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"drinks-and-snacks\">Drinks and snacks\u003C/h2>\n\u003Ch3 id=\"bars\">Bars\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:1532531236@Le_Bi%C3%A8rographe#map=16.50/43.5986892/1.4428327\">Le Bièrographe\u003C/a> — all time favourite, \u003Cstrong>check out the typical toulouse basement\u003C/strong>\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.facebook.com/ataulatolosa/\">A Taula\u003C/a> — all time favourite in summer, \u003Cstrong>amazing terrace,\u003C/strong> also: great tapas\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:5592180378@The_Hopscotch#map=18.14/43.6006796/1.4431385\">The Hopscotch Pub\u003C/a> — good beers, good whiskies, good cocktials, good food\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"cafés--tea-rooms\">Cafés & tea rooms\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.bapz.fr/contact\">Bapz\u003C/a> — Excellent pastries / hot beverages\u003C/li>\n\u003Cli>\u003Ca href=\"https://fr-fr.facebook.com/%C3%94-Th%C3%A9-Divin-245018828864405/\">Ô thé divin\u003C/a> — nice lunch options\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lesreveriesdhercule.com/\">Les Rêveries d’Hercule\u003C/a> — Pottery Café, relaxing activity (ceramics need to be baked, there’ll be a delay to get them back)\u003C/li>\n\u003Cli>Bonus: the best bakeries in \u003Ca href=\"https://www.qwant.com/maps/place/osm:node:450165912@Boulangerie_des_Carmes#map=16.37/43.6022638/1.4439872\">Carmes\u003C/a> and \u003Ca href=\"https://www.qwant.com/maps/place/osm:node:456844404@La_P%C3%A9trie#map=18.84/43.6045088/1.4544694\">Saint-Aubin\u003C/a> — croissants, baguettes \u003Cstrong>traditions\u003C/strong>, chocolatines and more\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"wine-shops\">Wine shops\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:3861692629@LEnvie#map=19.57/43.5978194/1.4443930\">l’envie du sud\u003C/a> — amazing selection of wines and other spirits, excellent advice from the staff\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:3751077562@Enoteca_31#map=16.50/43.6045636/1.4531952\">enoteca\u003C/a> — smaller selection but more beers and great advice from the staff as well\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"other-delights\">Other delights\u003C/h2>\n\u003Ch3 id=\"ice-creams\">Ice creams\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2462248749@Caf%C3%A9t%C3%A9ria_Gelateria#map=20.00/43.6027626/1.4421450\">Forno gusto\u003C/a> — only in the summer\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2165543146@Glaces_Moustache#map=16.50/43.6036985/1.4350540\">Moustache\u003C/a> — lots of flavours\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"cheese-shop\">Cheese shop\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://xavier.fr/\">Xavier\u003C/a> — one of the \u003Cstrong>best of the country\u003C/strong>, two shops in Toulouse, including one at Victor Hugo market\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:6164095797@Massembea#map=16.50/43.6043930/1.4539490\">Massembea\u003C/a> — a serious contender in Toulouse (weird hours)\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"delicatessen\">Delicatessen\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"http://cafe-bacquie.com/\">Café Bacquié\u003C/a> — stock up on fine foods, coffees, teas and other great quality products\u003C/li>\n\u003C/ul>",{"headings":498,"imagePaths":535,"frontmatter":536},[499,502,505,508,511,514,517,520,523,526,529,532],{"depth":150,"slug":500,"text":501},"restaurants","Restaurants",{"depth":154,"slug":503,"text":504},"french-cuisine","French cuisine",{"depth":154,"slug":506,"text":507},"korean","Korean",{"depth":154,"slug":509,"text":510},"japanese","Japanese",{"depth":150,"slug":512,"text":513},"drinks-and-snacks","Drinks and snacks",{"depth":154,"slug":515,"text":516},"bars","Bars",{"depth":154,"slug":518,"text":519},"cafés--tea-rooms","Cafés & tea rooms",{"depth":154,"slug":521,"text":522},"wine-shops","Wine shops",{"depth":150,"slug":524,"text":525},"other-delights","Other delights",{"depth":154,"slug":527,"text":528},"ice-creams","Ice creams",{"depth":154,"slug":530,"text":531},"cheese-shop","Cheese shop",{"depth":154,"slug":533,"text":534},"delicatessen","Delicatessen",[],{"title":487,"subtitle":488,"lang":68,"slug":484,"excerpt":537,"tags":538,"type":435,"createdAt":223},"Gonna have to trust me on this ¯\\_(ツ)_/¯",[490],"en-visited-links",{"id":539,"data":541,"body":438,"filePath":545,"digest":546,"rendered":547},{"title":542,"subtitle":209,"lang":68,"tags":543,"type":435,"slug":539,"createdAt":544,"draft":72},"Visited links and visuel aid",[18],["Date","2023-06-06T18:34:00.000Z"],"src/content/fragments/en/visited-links.md","cb7c11c12c25067e",{"html":548,"metadata":549},"\u003Cp>\u003Ca href=\"/en/snippets\">Go back to available snippets\u003C/a>\u003C/p>",{"headings":550,"imagePaths":551,"frontmatter":552},[],[],{"title":542,"subtitle":209,"lang":68,"draft":72,"slug":539,"excerpt":553,"tags":554,"type":435,"createdAt":555},"Petit hack CSS",[18],"2023-06-06T18:34:00.000Z","array-vs-array",{"id":556,"data":558,"body":564,"filePath":565,"digest":566,"rendered":567},{"title":559,"subtitle":560,"lang":16,"tags":561,"type":427,"slug":556,"createdAt":563,"draft":72},"Filtrer un array avec un autre array","En cours de traduction.",[562],"nuxt.js",["Date","2022-06-08T14:24:06.000Z"],"[Voir les fragments disponibles](/fragments)","src/content/fragments/fr/array-vs-array.md","7321d444177c3841",{"html":568,"metadata":569},"\u003Cp>\u003Ca href=\"/fragments\">Voir les fragments disponibles\u003C/a>\u003C/p>",{"headings":570,"imagePaths":571,"frontmatter":572},[],[],{"title":559,"subtitle":560,"lang":16,"draft":72,"slug":556,"createdAt":170,"excerpt":560,"tags":573,"type":427},[562],"toulouse-fun",{"id":574,"data":576,"body":564,"filePath":579,"digest":580,"rendered":581},{"title":487,"subtitle":560,"lang":16,"tags":577,"type":427,"slug":574,"createdAt":578,"draft":72},[490],["Date","2022-06-22T15:34:45.000Z"],"src/content/fragments/fr/toulouse-fun.md","a0c25b438b34c05e",{"html":568,"metadata":582},{"headings":583,"imagePaths":584,"frontmatter":585},[],[],{"title":487,"subtitle":560,"lang":16,"draft":72,"slug":574,"createdAt":223,"excerpt":560,"tags":586,"type":427},[490],"en-acme-sh-tls-cert",{"id":587,"data":589,"body":595,"filePath":596,"digest":597,"rendered":598},{"title":590,"subtitle":591,"lang":68,"tags":592,"type":435,"slug":587,"createdAt":594},"Strong TLS certificates with acme.sh","384-bit of https",[593],"security",["Date","2022-06-08T14:24:06.000Z"],"## Disclaimer\n\nI'm, in absolutely no regards, a security expert. I just fancy shiny new things of the interwebs. \nThis is why I've switched my default TLS certificates to use elliptic curve cryptography (ECC) instead of RSA. Now I have a sweet 100/100 on [tls.imirhil.fr](https://tls.imirhil.fr/)\n\nYou can learn (far) more by reading [this topic](https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa) and its linked resources.\n\n## Requirements\n\n### Installing acme.sh\n\nFor automation and ease of use purposes, I'm using [acme.sh](https://github.com/acmesh-official/acme.sh)\n\n```bash\n# for using standalone mode, you might have to install as sudo\ncurl https://get.acme.sh | sh -s email=mail@domain.tld\n```\n\n### Changing default authority\n\nBy default, acme.sh uses ZeroSSL to sign certificates. We need to change this to Let's Encrypt because according to acme.sh, they're the only ones offering ECC capabilities.\n\n```bash\nacme.sh --set-default-ca --server letsencrypt\n```\n\n## Using your DNS api\n\nIf available, the easiest way to issue a certificate is to use the DNS api of your DNS provider. acme.sh supports [a lot](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) of DNS providers.\n\n### Define an api key\n\nFollow the [docs](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) for your DNS provider, usually:\n\n```bash\nexport PROVIDER_Key=\"YOUR_API_KEY\"\n```\n\n### Issue the cert\n\n```bash\nacme.sh --issue -d domain.tld --dns dns_provider --keylength ec-384\n```\n\n## Using standalone mode\n\nIf you don't have access to the DNS provider, we can use the standalone mode to spin up a temporary web server that will handle all the verifications.\n\nPort `80` must be free.\n\n```bash\nacme.sh --issue --standalone -d domain.tld --keylength ec-384\n```\n\n## Examples\n\n### Multi domains standalone\n\n```bash\nacme.sh --issue --standalone -d domain.tld -d www.domain.tld -d subdomain.domain.tld --keylength ec-384\n```\n\n### Wildcard domain DNS\n\n```bash\nacme.sh --issue -d domain.tld -d '*.domain.tld' --dns dns_provider --keylength ec-384\n```\n\n## Next steps\n\nThe ECC certificate alone will not grant you a high/perfect score.\n\n### TLS version\n\nLimit TLS version to 1.2 and 1.3 (or just 1.3 as there is only a [5% compatibility gap](https://caniuse.com/?search=tls%201.) with 1.2).\n\n### HSTS\n\nUse the [strict transport security](https://scotthelme.co.uk/hsts-the-missing-link-in-tls/) header.\n\n```\nStrict-Transport-Security: max-age=31536000; includeSubDomains\n```\n\n### Cipher suite\n\nUse recent and strong ciphers. This is where my knowledge hits its limit… I'm having a really hard time understanding what to use and why.\n\nI've based my initial choices of ciphers on [this list](https://tls.imirhil.fr/ciphers), cross referencing it with (older?) [browser compatibility](https://tls.imirhil.fr/suite).\n\nI then asked [Aeris](https://twitter.com/aeris22), the creator of [tls.imirhil.fr](https://tls.imirhil.fr), about it and he advised me to use the following:\n\n```\nECDHE+AES:ECDHE+CHACHA20\n```\n\nIn order to achieve a perfect score, we can be a little more restrictive with:\n\n```\nECDHE+AES256:ECDHE+CHACHA20\n```","src/content/fragments/en/acme-sh-tls-cert.md","41577e8aee884f85",{"html":599,"metadata":600},"\u003Ch2 id=\"disclaimer\">Disclaimer\u003C/h2>\n\u003Cp>I’m, in absolutely no regards, a security expert. I just fancy shiny new things of the interwebs.\u003Cbr>\nThis is why I’ve switched my default TLS certificates to use elliptic curve cryptography (ECC) instead of RSA. Now I have a sweet 100/100 on \u003Ca href=\"https://tls.imirhil.fr/\">tls.imirhil.fr\u003C/a>\u003C/p>\n\u003Cp>You can learn (far) more by reading \u003Ca href=\"https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa\">this topic\u003C/a> and its linked resources.\u003C/p>\n\u003Ch2 id=\"requirements\">Requirements\u003C/h2>\n\u003Ch3 id=\"installing-acmesh\">Installing acme.sh\u003C/h3>\n\u003Cp>For automation and ease of use purposes, I’m using \u003Ca href=\"https://github.com/acmesh-official/acme.sh\">acme.sh\u003C/a>\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># for using standalone mode, you might have to install as sudo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">curl\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> https://get.acme.sh\u003C/span>\u003Cspan style=\"color:#F97583\"> |\u003C/span>\u003Cspan style=\"color:#B392F0\"> sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -s\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> email=mail@domain.tld\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"changing-default-authority\">Changing default authority\u003C/h3>\n\u003Cp>By default, acme.sh uses ZeroSSL to sign certificates. We need to change this to Let’s Encrypt because according to acme.sh, they’re the only ones offering ECC capabilities.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --set-default-ca\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --server\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"using-your-dns-api\">Using your DNS api\u003C/h2>\n\u003Cp>If available, the easiest way to issue a certificate is to use the DNS api of your DNS provider. acme.sh supports \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">a lot\u003C/a> of DNS providers.\u003C/p>\n\u003Ch3 id=\"define-an-api-key\">Define an api key\u003C/h3>\n\u003Cp>Follow the \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">docs\u003C/a> for your DNS provider, usually:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">export\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> PROVIDER_Key\u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"YOUR_API_KEY\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-the-cert\">Issue the cert\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --dns\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> dns_provider\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"using-standalone-mode\">Using standalone mode\u003C/h2>\n\u003Cp>If you don’t have access to the DNS provider, we can use the standalone mode to spin up a temporary web server that will handle all the verifications.\u003C/p>\n\u003Cp>Port \u003Ccode>80\u003C/code> must be free.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --standalone\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"examples\">Examples\u003C/h2>\n\u003Ch3 id=\"multi-domains-standalone\">Multi domains standalone\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --standalone\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> www.domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> subdomain.domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"wildcard-domain-dns\">Wildcard domain DNS\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> '*.domain.tld'\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --dns\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> dns_provider\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"next-steps\">Next steps\u003C/h2>\n\u003Cp>The ECC certificate alone will not grant you a high/perfect score.\u003C/p>\n\u003Ch3 id=\"tls-version\">TLS version\u003C/h3>\n\u003Cp>Limit TLS version to 1.2 and 1.3 (or just 1.3 as there is only a \u003Ca href=\"https://caniuse.com/?search=tls%201.\">5% compatibility gap\u003C/a> with 1.2).\u003C/p>\n\u003Ch3 id=\"hsts\">HSTS\u003C/h3>\n\u003Cp>Use the \u003Ca href=\"https://scotthelme.co.uk/hsts-the-missing-link-in-tls/\">strict transport security\u003C/a> header.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>Strict-Transport-Security: max-age=31536000; includeSubDomains\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"cipher-suite\">Cipher suite\u003C/h3>\n\u003Cp>Use recent and strong ciphers. This is where my knowledge hits its limit… I’m having a really hard time understanding what to use and why.\u003C/p>\n\u003Cp>I’ve based my initial choices of ciphers on \u003Ca href=\"https://tls.imirhil.fr/ciphers\">this list\u003C/a>, cross referencing it with (older?) \u003Ca href=\"https://tls.imirhil.fr/suite\">browser compatibility\u003C/a>.\u003C/p>\n\u003Cp>I then asked \u003Ca href=\"https://twitter.com/aeris22\">Aeris\u003C/a>, the creator of \u003Ca href=\"https://tls.imirhil.fr\">tls.imirhil.fr\u003C/a>, about it and he advised me to use the following:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>In order to achieve a perfect score, we can be a little more restrictive with:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES256:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":601,"imagePaths":647,"frontmatter":648},[602,605,608,611,614,617,620,623,626,629,632,635,638,641,644],{"depth":150,"slug":603,"text":604},"disclaimer","Disclaimer",{"depth":150,"slug":606,"text":607},"requirements","Requirements",{"depth":154,"slug":609,"text":610},"installing-acmesh","Installing acme.sh",{"depth":154,"slug":612,"text":613},"changing-default-authority","Changing default authority",{"depth":150,"slug":615,"text":616},"using-your-dns-api","Using your DNS api",{"depth":154,"slug":618,"text":619},"define-an-api-key","Define an api key",{"depth":154,"slug":621,"text":622},"issue-the-cert","Issue the cert",{"depth":150,"slug":624,"text":625},"using-standalone-mode","Using standalone mode",{"depth":150,"slug":627,"text":628},"examples","Examples",{"depth":154,"slug":630,"text":631},"multi-domains-standalone","Multi domains standalone",{"depth":154,"slug":633,"text":634},"wildcard-domain-dns","Wildcard domain DNS",{"depth":150,"slug":636,"text":637},"next-steps","Next steps",{"depth":154,"slug":639,"text":640},"tls-version","TLS version",{"depth":154,"slug":642,"text":643},"hsts","HSTS",{"depth":154,"slug":645,"text":646},"cipher-suite","Cipher suite",[],{"title":590,"subtitle":591,"lang":68,"slug":587,"createdAt":170,"excerpt":649,"tags":650,"type":435},"Real cert have curves.",[593],"acme-sh-tls-cert",{"id":651,"data":653,"body":659,"filePath":660,"digest":661,"rendered":662},{"title":654,"subtitle":655,"lang":16,"tags":656,"type":427,"slug":651,"createdAt":658},"Certificates TLS robustes avec acme.sh","384-bit de https",[657],"sécurité",["Date","2022-06-08T14:24:06.000Z"],"## Attention\n\nJe ne suis pas du tout un expert en sécurité. J'aime juste les trucs nouveaux et stylés des internets. \nC'est pourquoi j'ai modifié mes certificats TLS par défaut pour utiliser la cryptographie à courbe elliptique (ECC) au lieu de RSA. J'ai maintenant un joli 100/100 sur [tls.imirhil.fr](https://tls.imirhil.fr/)\n\nVous pouvez en apprendre (beaucoup) plus [ici](https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa) et sur les liens cités (en anglais).\n\n## Prérequis\n\n### Installer acme.sh\n\nPour des raisons de simplicité et d'automatisation, j'utilise [acme.sh](https://github.com/acmesh-official/acme.sh)\n\n```bash\n# pour utiliser le mode standalone, il peut être nécessaire d'installer en sudo\ncurl https://get.acme.sh | sh -s email=mail@domain.tld\n```\n\n### Changer l'authorité par défaut\n\nPar défaut, acme.sh utilise ZeroSSL pour signer les certificats. Il faut changer ce paramètre pour Let's Encrypt car, d'après acme.sh, ils sont les seuls à proposer des certificats ECC.\n\n```bash\nacme.sh --set-default-ca --server letsencrypt\n```\n\n## Utiliser l'api DNS\n\nSi vous en avez la possibilité, la façon la plus simple de générer un certificat est via l'api de votre fournisseur DNS. acme.sh supporte [énormément](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) de fournisseurs DNS.\n\n### Definir la clé api\n\nSuivez la [documentation](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) pour votre fournisseur DNS, généralement:\n\n```bash\nexport PROVIDER_Key=\"YOUR_API_KEY\"\n```\n\n### Émettre le certificat\n\n```bash\nacme.sh --issue -d domain.tld --dns dns_provider --keylength ec-384\n```\n\n## Utiliser le mode standalone\n\nSi vous n'avez pas accès aux réglages DNS, le mode standalone permet de lancer un serveur web temporaire qui s'occupe de toutes les vérifications.\n\nLe port `80` doit être disponible.\n\n```bash\nacme.sh --issue --standalone -d domain.tld --keylength ec-384\n```\n\n## Exemples\n\n### Multi domaines standalone\n\n```bash\nacme.sh --issue --standalone -d domain.tld -d www.domain.tld -d subdomain.domain.tld --keylength ec-384\n```\n\n### Wildcard domaine DNS\n\n```bash\nacme.sh --issue -d domain.tld -d '*.domain.tld' --dns dns_provider --keylength ec-384\n```\n\n## Étapes supplémentaires\n\nLe certificat ECC seul ne suffira pas à obtenir un score élevé/parfait.\n\n### Version TLS\n\nLimiter la version TLS à 1.2 et 1.3 (voire uniquement 1.3 vu [la différence de compatibilité de 5%](https://caniuse.com/?search=tls%201.) avec 1.2).\n\n### HSTS\n\nUtiliser le header [strict transport security](https://scotthelme.co.uk/hsts-the-missing-link-in-tls/).\n\n```\nStrict-Transport-Security: max-age=31536000; includeSubDomains\n```\n\n### Suite cryptographique\n\nUtiliser une suite cryptographique récente et robuste. C'est ici que mes connaissances deviennent limitées… J'ai encore un peu de mal à comprendre quelles suites fonctionnent bien et pourquoi.\n\nJ'avais basé ma première suite sur [cette liste](https://tls.imirhil.fr/ciphers), en la comparant avec celle de la compatibilité (d'anciens ?) [navigateurs](https://tls.imirhil.fr/suite).\n\nJ'ai ensuite demandé à [Aeris](https://twitter.com/aeris22), le créateur de [tls.imirhil.fr](https://tls.imirhil.fr), ses conseils sur cette suite. Il m'a recommandé d'utiliser :\n\n```\nECDHE+AES:ECDHE+CHACHA20\n```\n\nAfin d'atteindre un score de 100/100, il est possible de restreindre un peu plus la suite comme ceci :\n\n```\nECDHE+AES256:ECDHE+CHACHA20\n```","src/content/fragments/fr/acme-sh-tls-cert.md","82e6d91747c28ea5",{"html":663,"metadata":664},"\u003Ch2 id=\"attention\">Attention\u003C/h2>\n\u003Cp>Je ne suis pas du tout un expert en sécurité. J’aime juste les trucs nouveaux et stylés des internets.\u003Cbr>\nC’est pourquoi j’ai modifié mes certificats TLS par défaut pour utiliser la cryptographie à courbe elliptique (ECC) au lieu de RSA. J’ai maintenant un joli 100/100 sur \u003Ca href=\"https://tls.imirhil.fr/\">tls.imirhil.fr\u003C/a>\u003C/p>\n\u003Cp>Vous pouvez en apprendre (beaucoup) plus \u003Ca href=\"https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa\">ici\u003C/a> et sur les liens cités (en anglais).\u003C/p>\n\u003Ch2 id=\"prérequis\">Prérequis\u003C/h2>\n\u003Ch3 id=\"installer-acmesh\">Installer acme.sh\u003C/h3>\n\u003Cp>Pour des raisons de simplicité et d’automatisation, j’utilise \u003Ca href=\"https://github.com/acmesh-official/acme.sh\">acme.sh\u003C/a>\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># pour utiliser le mode standalone, il peut être nécessaire d'installer en sudo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">curl\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> https://get.acme.sh\u003C/span>\u003Cspan style=\"color:#F97583\"> |\u003C/span>\u003Cspan style=\"color:#B392F0\"> sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -s\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> email=mail@domain.tld\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"changer-lauthorité-par-défaut\">Changer l’authorité par défaut\u003C/h3>\n\u003Cp>Par défaut, acme.sh utilise ZeroSSL pour signer les certificats. Il faut changer ce paramètre pour Let’s Encrypt car, d’après acme.sh, ils sont les seuls à proposer des certificats ECC.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --set-default-ca\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --server\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"utiliser-lapi-dns\">Utiliser l’api DNS\u003C/h2>\n\u003Cp>Si vous en avez la possibilité, la façon la plus simple de générer un certificat est via l’api de votre fournisseur DNS. acme.sh supporte \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">énormément\u003C/a> de fournisseurs DNS.\u003C/p>\n\u003Ch3 id=\"definir-la-clé-api\">Definir la clé api\u003C/h3>\n\u003Cp>Suivez la \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">documentation\u003C/a> pour votre fournisseur DNS, généralement:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">export\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> PROVIDER_Key\u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"YOUR_API_KEY\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"émettre-le-certificat\">Émettre le certificat\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --dns\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> dns_provider\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"utiliser-le-mode-standalone\">Utiliser le mode standalone\u003C/h2>\n\u003Cp>Si vous n’avez pas accès aux réglages DNS, le mode standalone permet de lancer un serveur web temporaire qui s’occupe de toutes les vérifications.\u003C/p>\n\u003Cp>Le port \u003Ccode>80\u003C/code> doit être disponible.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --standalone\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"exemples\">Exemples\u003C/h2>\n\u003Ch3 id=\"multi-domaines-standalone\">Multi domaines standalone\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --standalone\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> www.domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> subdomain.domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"wildcard-domaine-dns\">Wildcard domaine DNS\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">acme.sh\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --issue\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> domain.tld\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -d\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> '*.domain.tld'\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --dns\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> dns_provider\u003C/span>\u003Cspan style=\"color:#79B8FF\"> --keylength\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"étapes-supplémentaires\">Étapes supplémentaires\u003C/h2>\n\u003Cp>Le certificat ECC seul ne suffira pas à obtenir un score élevé/parfait.\u003C/p>\n\u003Ch3 id=\"version-tls\">Version TLS\u003C/h3>\n\u003Cp>Limiter la version TLS à 1.2 et 1.3 (voire uniquement 1.3 vu \u003Ca href=\"https://caniuse.com/?search=tls%201.\">la différence de compatibilité de 5%\u003C/a> avec 1.2).\u003C/p>\n\u003Ch3 id=\"hsts\">HSTS\u003C/h3>\n\u003Cp>Utiliser le header \u003Ca href=\"https://scotthelme.co.uk/hsts-the-missing-link-in-tls/\">strict transport security\u003C/a>.\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>Strict-Transport-Security: max-age=31536000; includeSubDomains\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"suite-cryptographique\">Suite cryptographique\u003C/h3>\n\u003Cp>Utiliser une suite cryptographique récente et robuste. C’est ici que mes connaissances deviennent limitées… J’ai encore un peu de mal à comprendre quelles suites fonctionnent bien et pourquoi.\u003C/p>\n\u003Cp>J’avais basé ma première suite sur \u003Ca href=\"https://tls.imirhil.fr/ciphers\">cette liste\u003C/a>, en la comparant avec celle de la compatibilité (d’anciens ?) \u003Ca href=\"https://tls.imirhil.fr/suite\">navigateurs\u003C/a>.\u003C/p>\n\u003Cp>J’ai ensuite demandé à \u003Ca href=\"https://twitter.com/aeris22\">Aeris\u003C/a>, le créateur de \u003Ca href=\"https://tls.imirhil.fr\">tls.imirhil.fr\u003C/a>, ses conseils sur cette suite. Il m’a recommandé d’utiliser :\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Afin d’atteindre un score de 100/100, il est possible de restreindre un peu plus la suite comme ceci :\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES256:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":665,"imagePaths":709,"frontmatter":710},[666,669,672,675,678,681,684,687,690,693,696,699,702,705,706],{"depth":150,"slug":667,"text":668},"attention","Attention",{"depth":150,"slug":670,"text":671},"prérequis","Prérequis",{"depth":154,"slug":673,"text":674},"installer-acmesh","Installer acme.sh",{"depth":154,"slug":676,"text":677},"changer-lauthorité-par-défaut","Changer l’authorité par défaut",{"depth":150,"slug":679,"text":680},"utiliser-lapi-dns","Utiliser l’api DNS",{"depth":154,"slug":682,"text":683},"definir-la-clé-api","Definir la clé api",{"depth":154,"slug":685,"text":686},"émettre-le-certificat","Émettre le certificat",{"depth":150,"slug":688,"text":689},"utiliser-le-mode-standalone","Utiliser le mode standalone",{"depth":150,"slug":691,"text":692},"exemples","Exemples",{"depth":154,"slug":694,"text":695},"multi-domaines-standalone","Multi domaines standalone",{"depth":154,"slug":697,"text":698},"wildcard-domaine-dns","Wildcard domaine DNS",{"depth":150,"slug":700,"text":701},"étapes-supplémentaires","Étapes supplémentaires",{"depth":154,"slug":703,"text":704},"version-tls","Version TLS",{"depth":154,"slug":642,"text":643},{"depth":154,"slug":707,"text":708},"suite-cryptographique","Suite cryptographique",[],{"title":654,"subtitle":655,"lang":16,"slug":651,"createdAt":170,"excerpt":711,"tags":712,"type":427},"La sécurité avec des courbes.",[657],"visited-links",{"id":713,"data":715,"body":721,"filePath":722,"digest":723,"rendered":724},{"title":716,"subtitle":717,"lang":16,"tags":718,"type":435,"slug":713,"createdAt":719,"draft":720},"Liens visités et indication visuelle","Comment différencier les liens déjà cliqués",[18],["Date","2023-06-06T18:34:00.000Z"],false,"## La théorie\n\nIl est possible sur le web d'appliquer un style différent aux liens déjà visités par un utilisateur. Par défaut, un lien non visité est bleu tandis qu'un lien visité est violet.\n\nGénéralement, ces styles sont modifiés, voire supprimés dans le cas des liens visités. L'information qu'un lien a déjà été visité ne semble pas indispensable à la navigation. C'est sûrement vrai, mais personnellement, je suis assez content d'avoir un rappel des pages que j'ai déjà consultées lorsque je navigue.\n\nUne information uniquement communiquée par la couleur est faillible, car certaines personnes ne distinguent pas les couleurs correctement. J'ai alors cherché un moyen d'ajouter un élément graphique supplémentaire aux liens visités/non visités. La solution démontrée ici n'est certainement pas idéale, elle se rapproche plus d'une expérience, à priori inoffensive pour l'internaute.\n\n## La spécification\n\nQuand je me suis intéressé à ce qu'il était possible de faire avec les liens déjà visités, j'ai découvert qu'extrêmement peu de propriétés \u003Cabbr>CSS\u003C/abbr> étaient autorisées. En effet, seulement des changements de couleurs sont disponibles. Ceci est dû au fait qu'il était possible de récupérer l'historique de navigation d'un utilisateur grâce aux styles des liens visités. Le sélecteur `:visited` a donc été restreint par les navigateurs afin de lutter contre cette brèche de la vie privée. [Plus d'informations dans cet article.](https://developer.mozilla.org/fr/docs/Web/CSS/Privacy_and_the_:visited_selector)\n\n## La pratique\n\nQue faire alors, en terme de style, quand on ne peut changer que des couleurs ?\n\nD'après MDN, les propriétés suivantes sont modifiables :\n\n- `color`\n- `background-color`\n- `border-color` (et les propriétés détaillées associées),\n- `column-rule-color`\n- `outline-color`\n- `text-decoration-color`\n- `text-emphasis-color`\n- Les composantes de couleur liées aux attributs SVG `fill` et `stroke`.\n\nChanger la couleur d'un lien visité ne sera pas compris par les internautes, à moins de garder une colorimétrie proche de celle par défaut (bleu et violet).\n\nEn revanche, il est possible de \" masquer \" un élément en modifiant sa couleur pour qu'elle corresponde à la couleur du fond de la page ou de l'élément parent. On pourrait ainsi imaginer masquer une `border` ou un `outline`.\n\nJ'ai personnellement choisi de faire différemment. J'ai décidé d'utiliser un pseudo-élément `::before` sur l'état non visité du lien puis de le masquer quand celui-ci devient visité.\n\n### Le code\n\n```css\na {\n\tposition: relative;\n\ttext-decoration: none;\n}\na::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 0;\n\tinline-size: 2px;\n\tblock-size: 2px;\n\tborder-radius: 4px;\n\ttransform: translate(-6px, 0);\n\tbackground-color: grey;\n}\na:visited::before {\n\tbackground-color: white;\n}\n```\n\nCes règles, utilisées dans la table des matières de mes articles, ajoutent une sorte de petite puce ou pastille au début du lien. Cette puce est ensuite passée en blanc sur fond blanc une fois que le lien est visité, ce qui la masque visuellement.\n\n### Accessibilité\n\nOn pourrait simplifier la règle et utiliser le caractère de puce directement dans la propriété `content` mais les lecteurs d'écran annonceront alors ce caractère lors de leur retranscription du lien. De plus, les lecteurs d'écrans annoncent déjà si un lien est visité avant de lire son intitulé.\n\n## Aller plus loin\n\nAfin de pousser l'expérience un peu plus loin, j'ai tenté d'utiliser des éléments plus explicites pour signifier l'état visité du lien. Bien qu'encore assez imparfait, il est possible de créer un indicateur plus complet de lien visité.\n\nL'idée est d'avoir un `::before` et un `::after`, chacun contenant une icône en base 64 blanche en tant qu'image de fond. Quand le lien est non visité, le `::before` contient un fond coloré qui fait apparaître l'icône. Quand le lien passe en visité, le fond du `::before` devient blanc et celui du `::after` devient coloré, ce qui masque la première icône et affiche la deuxième.\n\nIl est nécessaire de positionner les icônes côte à côte sinon elles se retrouveront l'une sur l'autre.\n\n[Voir la démo sur codepen.](https://codepen.io/narduin/pen/VwVwmrO)","src/content/fragments/fr/visited-links.md","52385f4f8bc864b2",{"html":725,"metadata":726},"\u003Ch2 id=\"la-théorie\">La théorie\u003C/h2>\n\u003Cp>Il est possible sur le web d’appliquer un style différent aux liens déjà visités par un utilisateur. Par défaut, un lien non visité est bleu tandis qu’un lien visité est violet.\u003C/p>\n\u003Cp>Généralement, ces styles sont modifiés, voire supprimés dans le cas des liens visités. L’information qu’un lien a déjà été visité ne semble pas indispensable à la navigation. C’est sûrement vrai, mais personnellement, je suis assez content d’avoir un rappel des pages que j’ai déjà consultées lorsque je navigue.\u003C/p>\n\u003Cp>Une information uniquement communiquée par la couleur est faillible, car certaines personnes ne distinguent pas les couleurs correctement. J’ai alors cherché un moyen d’ajouter un élément graphique supplémentaire aux liens visités/non visités. La solution démontrée ici n’est certainement pas idéale, elle se rapproche plus d’une expérience, à priori inoffensive pour l’internaute.\u003C/p>\n\u003Ch2 id=\"la-spécification\">La spécification\u003C/h2>\n\u003Cp>Quand je me suis intéressé à ce qu’il était possible de faire avec les liens déjà visités, j’ai découvert qu’extrêmement peu de propriétés \u003Cabbr>CSS\u003C/abbr> étaient autorisées. En effet, seulement des changements de couleurs sont disponibles. Ceci est dû au fait qu’il était possible de récupérer l’historique de navigation d’un utilisateur grâce aux styles des liens visités. Le sélecteur \u003Ccode>:visited\u003C/code> a donc été restreint par les navigateurs afin de lutter contre cette brèche de la vie privée. \u003Ca href=\"https://developer.mozilla.org/fr/docs/Web/CSS/Privacy_and_the_:visited_selector\">Plus d’informations dans cet article.\u003C/a>\u003C/p>\n\u003Ch2 id=\"la-pratique\">La pratique\u003C/h2>\n\u003Cp>Que faire alors, en terme de style, quand on ne peut changer que des couleurs ?\u003C/p>\n\u003Cp>D’après MDN, les propriétés suivantes sont modifiables :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>background-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>border-color\u003C/code> (et les propriétés détaillées associées),\u003C/li>\n\u003Cli>\u003Ccode>column-rule-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>outline-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>text-decoration-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>text-emphasis-color\u003C/code>\u003C/li>\n\u003Cli>Les composantes de couleur liées aux attributs SVG \u003Ccode>fill\u003C/code> et \u003Ccode>stroke\u003C/code>.\u003C/li>\n\u003C/ul>\n\u003Cp>Changer la couleur d’un lien visité ne sera pas compris par les internautes, à moins de garder une colorimétrie proche de celle par défaut (bleu et violet).\u003C/p>\n\u003Cp>En revanche, il est possible de ” masquer ” un élément en modifiant sa couleur pour qu’elle corresponde à la couleur du fond de la page ou de l’élément parent. On pourrait ainsi imaginer masquer une \u003Ccode>border\u003C/code> ou un \u003Ccode>outline\u003C/code>.\u003C/p>\n\u003Cp>J’ai personnellement choisi de faire différemment. J’ai décidé d’utiliser un pseudo-élément \u003Ccode>::before\u003C/code> sur l’état non visité du lien puis de le masquer quand celui-ci devient visité.\u003C/p>\n\u003Ch3 id=\"le-code\">Le code\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">a\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">relative\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttext-decoration\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">none\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">a\u003C/span>\u003Cspan style=\"color:#B392F0\">::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcontent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">''\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">absolute\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttop\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tleft\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tinline-size\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tblock-size\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder-radius\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">4\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">translate\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">-6\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">grey\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#85E89D\">a\u003C/span>\u003Cspan style=\"color:#B392F0\">:visited::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">white\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Ces règles, utilisées dans la table des matières de mes articles, ajoutent une sorte de petite puce ou pastille au début du lien. Cette puce est ensuite passée en blanc sur fond blanc une fois que le lien est visité, ce qui la masque visuellement.\u003C/p>\n\u003Ch3 id=\"accessibilité\">Accessibilité\u003C/h3>\n\u003Cp>On pourrait simplifier la règle et utiliser le caractère de puce directement dans la propriété \u003Ccode>content\u003C/code> mais les lecteurs d’écran annonceront alors ce caractère lors de leur retranscription du lien. De plus, les lecteurs d’écrans annoncent déjà si un lien est visité avant de lire son intitulé.\u003C/p>\n\u003Ch2 id=\"aller-plus-loin\">Aller plus loin\u003C/h2>\n\u003Cp>Afin de pousser l’expérience un peu plus loin, j’ai tenté d’utiliser des éléments plus explicites pour signifier l’état visité du lien. Bien qu’encore assez imparfait, il est possible de créer un indicateur plus complet de lien visité.\u003C/p>\n\u003Cp>L’idée est d’avoir un \u003Ccode>::before\u003C/code> et un \u003Ccode>::after\u003C/code>, chacun contenant une icône en base 64 blanche en tant qu’image de fond. Quand le lien est non visité, le \u003Ccode>::before\u003C/code> contient un fond coloré qui fait apparaître l’icône. Quand le lien passe en visité, le fond du \u003Ccode>::before\u003C/code> devient blanc et celui du \u003Ccode>::after\u003C/code> devient coloré, ce qui masque la première icône et affiche la deuxième.\u003C/p>\n\u003Cp>Il est nécessaire de positionner les icônes côte à côte sinon elles se retrouveront l’une sur l’autre.\u003C/p>\n\u003Cp>\u003Ca href=\"https://codepen.io/narduin/pen/VwVwmrO\">Voir la démo sur codepen.\u003C/a>\u003C/p>",{"headings":727,"imagePaths":745,"frontmatter":746},[728,731,734,737,740,742],{"depth":150,"slug":729,"text":730},"la-théorie","La théorie",{"depth":150,"slug":732,"text":733},"la-spécification","La spécification",{"depth":150,"slug":735,"text":736},"la-pratique","La pratique",{"depth":154,"slug":738,"text":739},"le-code","Le code",{"depth":154,"slug":32,"text":741},"Accessibilité",{"depth":150,"slug":743,"text":744},"aller-plus-loin","Aller plus loin",[],{"title":716,"subtitle":717,"lang":16,"draft":720,"slug":713,"excerpt":553,"tags":747,"type":435,"createdAt":555},[18],"en-buttons",{"id":748,"data":750,"body":755,"filePath":756,"digest":757,"rendered":758},{"title":751,"subtitle":752,"lang":68,"tags":753,"type":435,"slug":748,"createdAt":754,"code":72,"draft":72},"Buttons hover","Simple, but nice.",[434],["Date","2020-10-08T09:00:00.000Z"],"## General rules\n\nAll the buttons use these styles as a “reset”:\n\n> Don't forget to prefix if necessary!\n\n```css\n.btn {\n\tmargin: 20px 0;\n\tpadding: 12px 26px;\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tfont-size: 20rem; /* 20px */\n\tline-height: 1.6;\n\ttext-align: center;\n\ttext-decoration: none;\n\tfont-weight: bold;\n\tcursor: pointer;\n\tborder: none;\n\tborder-radius: 2px;\n\t-moz-appearance: none;\n\t-webkit-appearance: none;\n\tcolor: white;\n\tbackground-color: hotpink;\n\ttransition: background-color 0.3s ease;\n}\n```\n\n## Add an icon\n\n\u003Cbutton role=\"none\" class=\"btn btn-icon\">\n \u003Cspan>Icon\u003C/span>\n\u003C/button>\n\n```css\n.btn-icon {\n\tbackground-color: hotpink;\n}\n.btn-icon::before {\n\tcontent: url('~assets/svg/arrow-right-white.svg');\n\tposition: absolute;\n\twidth: 20px;\n\ttop: 50%;\n\tright: 0;\n\ttransform: translate(40px, -50%);\n\ttransition: transform ease 0.3s;\n}\n.btn-icon:hover,\n.btn-icon:focus {\n\tbackground-color: darkorchid;\n}\n.btn-icon:hover::before,\n.btn-icon:focus::before {\n\ttransform: translate(-10px, -50%);\n}\n.btn-icon > span {\n\tdisplay: inline-block;\n\twidth: 100%;\n\theight: 100%;\n\ttransition: transform 0.3s ease;\n}\n.btn-icon:hover > span,\n.btn-icon:focus > span {\n\ttransform: translateX(-10px);\n}\n```\n\n## Double shutter down\n\n\u003Cbutton role=\"none\" class=\"btn btn-rideau\">\n \u003Cspan>Shutter\u003C/span>\n\u003C/button>\n\n```css\n.btn-rideau {\n\tborder: 2px solid #10113a;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n\ttransition: color 0.3s ease;\n}\n.btn-rideau:hover {\n\tcolor: white;\n}\n.btn-rideau::before {\n\tbackground: hotpink;\n}\n.btn-rideau::after {\n\tbackground: darkorchid;\n}\n.btn-rideau::before,\n.btn-rideau::after {\n\tcontent: '';\n\tposition: absolute;\n\theight: 100%;\n\twidth: 100%;\n\tbottom: 100%;\n\tleft: 0;\n\tz-index: -1;\n\ttransition: transform 0.3s;\n\ttransition-timing-function: ease;\n\ttransition-timing-function: cubic-bezier(0.75, 0, 0.125, 1);\n}\n.btn-rideau:hover::before,\n.btn-rideau:hover::after,\n.btn-rideau:focus::before,\n.btn-rideau:focus::after {\n\ttransform: translateY(100%);\n}\n.btn-rideau:hover::after,\n.btn-rideau:focus::after {\n\ttransition-delay: 0.175s;\n}\n```\n\n## Animated gradient\n\n\u003Cbutton role=\"none\" class=\"btn btn-gradient\">\n \u003Cspan>Gradient\u003C/span>\n\u003C/button>\n\n```css\n.btn-gradient {\n\tbackground: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);\n\tbackground-size: 400% 400%;\n\tbackground-position: 0% 50%;\n\tanimation: GradientReverse 0.5s ease 1 normal forwards;\n}\n.btn-gradient:hover,\n.btn-gradient:focus {\n\tanimation: Gradient 0.5s ease 1 normal forwards;\n}\n@keyframes Gradient {\n\t0% {\n\t\tbackground-position: 0% 50%;\n\t}\n\t100% {\n\t\tbackground-position: 100% 100%;\n\t}\n}\n@keyframes GradientReverse {\n\t0% {\n\t\tbackground-position: 100% 100%;\n\t}\n\t100% {\n\t\tbackground-position: 0% 50%;\n\t}\n}\n```\n\n## Non destructive scale\n\n\u003Cbutton role=\"none\" class=\"btn btn-scale\">\n \u003Cspan>Scale\u003C/span>\n\u003C/button>\n\n```css\n.btn-scale {\n\toverflow: visible;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n}\n.btn-scale::after {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n\twidth: 100%;\n\tborder: 2px solid #10113a;\n\tborder-radius: 2px;\n\ttransition: transform 0.3s ease;\n}\n.btn-scale:hover::after,\n.btn-scale:focus::after {\n\ttransform: scale(1.1);\n}\n```","src/content/fragments/en/buttons.md","ea9a5513a5a4cef4",{"html":759,"metadata":760},"\u003Ch2 id=\"general-rules\">General rules\u003C/h2>\n\u003Cp>All the buttons use these styles as a “reset”:\u003C/p>\n\u003Cblockquote>\n\u003Cp>Don’t forget to prefix if necessary!\u003C/p>\n\u003C/blockquote>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tmargin\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">20\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tpadding\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">12\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 26\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">relative\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tdisplay\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">inline-block\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\toverflow\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">hidden\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tfont-size\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">20\u003C/span>\u003Cspan style=\"color:#F97583\">rem\u003C/span>\u003Cspan style=\"color:#E1E4E8\">; \u003C/span>\u003Cspan style=\"color:#6A737D\">/* 20px */\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tline-height\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">1.6\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttext-align\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">center\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttext-decoration\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">none\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tfont-weight\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">bold\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcursor\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">pointer\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">none\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder-radius\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t-moz-appearance\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">none\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t-webkit-appearance\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">none\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcolor\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">white\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">hotpink\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: background-color \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"add-an-icon\">Add an icon\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-icon\">\n \u003Cspan>Icon\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">hotpink\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcontent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">url\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'~assets/svg/arrow-right-white.svg'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">absolute\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\twidth\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">20\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttop\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tright\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">translate\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">40\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">-50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: transform \u003C/span>\u003Cspan style=\"color:#79B8FF\">ease\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:hover\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:focus\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">darkorchid\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:hover::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:focus::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">translate\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">-10\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">-50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon\u003C/span>\u003Cspan style=\"color:#F97583\"> >\u003C/span>\u003Cspan style=\"color:#85E89D\"> span\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tdisplay\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">inline-block\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\twidth\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\theight\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: transform \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:hover\u003C/span>\u003Cspan style=\"color:#F97583\"> >\u003C/span>\u003Cspan style=\"color:#85E89D\"> span\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-icon:focus\u003C/span>\u003Cspan style=\"color:#F97583\"> >\u003C/span>\u003Cspan style=\"color:#85E89D\"> span\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">translateX\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">-10\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"double-shutter-down\">Double shutter down\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-rideau\">\n \u003Cspan>Shutter\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#79B8FF\"> solid\u003C/span>\u003Cspan style=\"color:#79B8FF\"> #10113a\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcolor\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">#10113a\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">transparent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">color\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:hover\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcolor\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">white\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">hotpink\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">darkorchid\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcontent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">''\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">absolute\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\theight\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\twidth\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbottom\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tleft\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tz-index\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">-1\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: transform \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition-timing-function\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">ease\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition-timing-function\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">cubic-bezier\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">0.75\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.125\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">1\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:hover::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:hover::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:focus::before\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:focus::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">translateY\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:hover::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-rideau:focus::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition-delay\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.175\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"animated-gradient\">Animated gradient\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-gradient\">\n \u003Cspan>Gradient\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-gradient\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">linear-gradient\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">-45\u003C/span>\u003Cspan style=\"color:#F97583\">deg\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">#ee7752\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">#e73c7e\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">#23a6d5\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">#23d5ab\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-size\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">400\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 400\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-position\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tanimation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: GradientReverse \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.5\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 1\u003C/span>\u003Cspan style=\"color:#79B8FF\"> normal\u003C/span>\u003Cspan style=\"color:#79B8FF\"> forwards\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-gradient:hover\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-gradient:focus\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tanimation\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: Gradient \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.5\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 1\u003C/span>\u003Cspan style=\"color:#79B8FF\"> normal\u003C/span>\u003Cspan style=\"color:#79B8FF\"> forwards\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">@keyframes\u003C/span>\u003Cspan style=\"color:#FFAB70\"> Gradient\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">\t0%\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t\tbackground-position\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">\t100%\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t\tbackground-position\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">@keyframes\u003C/span>\u003Cspan style=\"color:#FFAB70\"> GradientReverse\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">\t0%\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t\tbackground-position\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">\t100%\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\t\tbackground-position\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 50\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"non-destructive-scale\">Non destructive scale\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-scale\">\n \u003Cspan>Scale\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-scale\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\toverflow\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">visible\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcolor\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">#10113a\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbackground-color\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">transparent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-scale::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tcontent\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">''\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tposition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">absolute\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttop\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tleft\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tbottom\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">0\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\twidth\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">100\u003C/span>\u003Cspan style=\"color:#F97583\">%\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#79B8FF\"> solid\u003C/span>\u003Cspan style=\"color:#79B8FF\"> #10113a\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\tborder-radius\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#F97583\">px\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransition\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: transform \u003C/span>\u003Cspan style=\"color:#79B8FF\">0.3\u003C/span>\u003Cspan style=\"color:#F97583\">s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> ease\u003C/span>\u003Cspan style=\"color:#E1E4E8\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-scale:hover::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">.btn-scale:focus::after\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">\ttransform\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: \u003C/span>\u003Cspan style=\"color:#79B8FF\">scale\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#79B8FF\">1.1\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":761,"imagePaths":777,"frontmatter":778},[762,765,768,771,774],{"depth":150,"slug":763,"text":764},"general-rules","General rules",{"depth":150,"slug":766,"text":767},"add-an-icon","Add an icon",{"depth":150,"slug":769,"text":770},"double-shutter-down","Double shutter down",{"depth":150,"slug":772,"text":773},"animated-gradient","Animated gradient",{"depth":150,"slug":775,"text":776},"non-destructive-scale","Non destructive scale",[],{"title":751,"subtitle":752,"lang":68,"slug":748,"draft":72,"excerpt":779,"tags":780,"code":72,"type":435,"createdAt":781},"Easy to grab and use hover effects.",[434],"2020-10-08T09:00:00.000Z","en-array-vs-array",{"id":782,"data":784,"body":789,"filePath":790,"digest":791,"rendered":792},{"title":785,"subtitle":786,"lang":68,"tags":787,"type":435,"slug":782,"createdAt":788},"Filter an array against another array","Array vs Array.",[562],["Date","2022-06-08T14:24:06.000Z"],"## Context\n\nFor a project, I had to come up with a way to filter an array of objects based on another array of strings.\n\nIn other words, I needed to include every object which `user` property was found in the second array.\n\nHere is an example:\n\n```javascript\nconst skills = [\n\t{\n\t\tname: 'Be awesome',\n\t\tuser: 'Jean'\n\t},\n\t{\n\t\tname: 'Great jokes',\n\t\tuser: 'Jacques'\n\t},\n\t{\n\t\tname: 'Heavy sleeper',\n\t\tuser: 'Jean'\n\t},\n\t{\n\t\tname: 'Heavy sleeper',\n\t\tuser: 'Beatriz'\n\t}\n]\n\nconst selectedUsers = ['Jean', 'Beatriz']\n```\n\nI thought it would be pretty easy but I guess I'm not familiar enough with javascript 😬\n\n## My solution\n\nAfter a bit of thinking, I came up with the following statement:\n\n> I need to filter the skills based on which users are selected. So I need to loop over the `selectedUsers` array and filter the skills according to their `user` value.\n\nAfter a bit more trials and errors, this is the code I ended up using in a `computed property`:\n\n```javascript\n// index.vue\nconst filteredSkills = selectedUsers.map((user) => {\n\treturn skills.filter((skill) => {\n\t\treturn skill.user === user\n\t})\n})\n```\n\nI used `map()` in order to loop on the second array and used its string value to only include the corresponding skills with `filter()`.\n\nI'm pretty sure there is a better way to do it though…","src/content/fragments/en/array-vs-array.md","c63ba57b1049cf4c",{"html":793,"metadata":794},"\u003Ch2 id=\"context\">Context\u003C/h2>\n\u003Cp>For a project, I had to come up with a way to filter an array of objects based on another array of strings.\u003C/p>\n\u003Cp>In other words, I needed to include every object which \u003Ccode>user\u003C/code> property was found in the second array.\u003C/p>\n\u003Cp>Here is an example:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> skills\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tname: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Be awesome'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tuser: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Jean'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tname: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Great jokes'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tuser: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Jacques'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tname: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Heavy sleeper'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tuser: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Jean'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tname: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Heavy sleeper'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\tuser: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Beatriz'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> selectedUsers\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> [\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Jean'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Beatriz'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">]\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>I thought it would be pretty easy but I guess I’m not familiar enough with javascript 😬\u003C/p>\n\u003Ch2 id=\"my-solution\">My solution\u003C/h2>\n\u003Cp>After a bit of thinking, I came up with the following statement:\u003C/p>\n\u003Cblockquote>\n\u003Cp>I need to filter the skills based on which users are selected. So I need to loop over the \u003Ccode>selectedUsers\u003C/code> array and filter the skills according to their \u003Ccode>user\u003C/code> value.\u003C/p>\n\u003C/blockquote>\n\u003Cp>After a bit more trials and errors, this is the code I ended up using in a \u003Ccode>computed property\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> filteredSkills\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> selectedUsers.\u003C/span>\u003Cspan style=\"color:#B392F0\">map\u003C/span>\u003Cspan style=\"color:#E1E4E8\">((\u003C/span>\u003Cspan style=\"color:#FFAB70\">user\u003C/span>\u003Cspan style=\"color:#E1E4E8\">) \u003C/span>\u003Cspan style=\"color:#F97583\">=>\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">\treturn\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> skills.\u003C/span>\u003Cspan style=\"color:#B392F0\">filter\u003C/span>\u003Cspan style=\"color:#E1E4E8\">((\u003C/span>\u003Cspan style=\"color:#FFAB70\">skill\u003C/span>\u003Cspan style=\"color:#E1E4E8\">) \u003C/span>\u003Cspan style=\"color:#F97583\">=>\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">\t\treturn\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> skill.user \u003C/span>\u003Cspan style=\"color:#F97583\">===\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> user\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t})\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">})\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>I used \u003Ccode>map()\u003C/code> in order to loop on the second array and used its string value to only include the corresponding skills with \u003Ccode>filter()\u003C/code>.\u003C/p>\n\u003Cp>I’m pretty sure there is a better way to do it though…\u003C/p>",{"headings":795,"imagePaths":802,"frontmatter":803},[796,799],{"depth":150,"slug":797,"text":798},"context","Context",{"depth":150,"slug":800,"text":801},"my-solution","My solution",[],{"title":785,"subtitle":786,"lang":68,"slug":782,"createdAt":170,"excerpt":804,"tags":805,"type":435},"My peak javascript",[562],"en-nuxt-graphql-static",{"id":806,"data":808,"body":814,"filePath":815,"digest":816,"rendered":817},{"title":809,"subtitle":810,"lang":68,"tags":811,"type":435,"slug":806,"createdAt":812,"updatedAt":813},"Static website and GraphQL queries with Nuxt.js","Graphql client is king.",[562],["Date","2022-06-08T14:24:06.000Z"],["Date","2022-09-08T13:43:33.000Z"],"## The problem\n\nI encountered a nasty bug while using static generation with Nuxt and [nuxt apollo](https://github.com/nuxt-community/apollo-module 'Dépôt github du module nuxt apollo (new tab)') client.\nI found [the issue](https://github.com/nuxt-community/apollo-module/issues/339 'Github issue on nuxt/apollo repository (new tab)') already reported on github.\n\nIt seems the module doesn't handle static generation correctly with `nuxt generate`.\n\nI could find request to my local API url after the static generation. Moreover, it also seemed like `\u003Cnuxt-link>` navigation was broken.\n\n## The solution 🙌\n\nFortunately, there is another Nuxt module that handles GraphQL requests!\n\n[Nuxt graphql request to the rescue!](https://github.com/gomah/nuxt-graphql-request)\n\n### The conf\n\n```javascript\n// nuxt.config.js\nbuildModules: [\n 'nuxt-graphql-request',\n],\ngraphql: {\n clients: {\n default: {\n endpoint: 'http://API_URL/graphql',\n options: {\n headers: {\n authorization: 'Bearer API_TOKEN',\n },\n },\n },\n },\n},\n```\n\n### The request\n\nThe best approach so far is to use `asyncData` in pages and `fetch` in components. Using `fetch` in pages does not work well at all with `nuxt generate`.\n\nI also install the `graphql-tag` package (only in `devDependencies`) to be able to import directly `.gql` files.\n\nQuery example:\n\n```graphql\n# homepage.gql\nquery {\n\thomepage {\n\t\ttitle\n\t\tsubtitle\n\t\thero {\n\t\t\tid\n\t\t\talt\n\t\t}\n\t}\n}\n```\n\n#### Inside a page\n\n```javascript\n// index.vue\n\u003Cscript>\nimport homepageQuery from '~/graphql/queries/singles/homepage'\n\nexport default {\n async asyncData({ $graphql }) {\n const data = await $graphql.default.request(homepageQuery)\n return { data }\n },\n}\n\u003C/script>\n```\n\n#### Inside a component\n\nIt is safer to wait until `fetch` has received a response before displaying anything. You can use `$fetchState` to be sure ([documentation](https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch 'Documentation on the fetch hook (new tab)')).\n\n```javascript\n// Header.vue\n\u003Ctemplate>\n \u003Cheader v-if=\"!$fetchState.pending\">\n …\n \u003C/header>\n\u003C/template>\n\n\u003Cscript>\nimport headerQuery from '~/graphql/queries/singles/header'\n\nexport default {\n data() {\n return {\n data: {},\n }\n },\n async fetch() {\n try {\n const data = await this.$graphql.default.request(headerQuery)\n this.data = data\n } catch (error) {\n console.error(JSON.stringify(error, undefined, 2))\n }\n },\n}\n\u003C/script>\n```\n\n### Options\n\nTo pass options to the request, for example for a multilingual version with [nuxt/i18n](https://i18n.nuxtjs.org/) and/or a url parameter in a dynamic page:\n\n```javascript\n// _slug.vue\n\u003Cscript>\nimport articleQuery from '~/graphql/queries/articles'\n\nexport default {\n async asyncData({ $graphql, app, params }) {\n const locale = app.i18n.localeProperties.iso\n const data = await $graphql.default.request(articleQuery, {\n code: locale,\n slug: params.slug,\n })\n return { data }\n },\n}\n\u003C/script>\n```","src/content/fragments/en/nuxt-graphql-static.md","181e8091294eb858",{"html":818,"metadata":819},"\u003Ch2 id=\"the-problem\">The problem\u003C/h2>\n\u003Cp>I encountered a nasty bug while using static generation with Nuxt and \u003Ca href=\"https://github.com/nuxt-community/apollo-module\" title=\"Dépôt github du module nuxt apollo (new tab)\">nuxt apollo\u003C/a> client.\nI found \u003Ca href=\"https://github.com/nuxt-community/apollo-module/issues/339\" title=\"Github issue on nuxt/apollo repository (new tab)\">the issue\u003C/a> already reported on github.\u003C/p>\n\u003Cp>It seems the module doesn’t handle static generation correctly with \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>I could find request to my local API url after the static generation. Moreover, it also seemed like \u003Ccode><nuxt-link>\u003C/code> navigation was broken.\u003C/p>\n\u003Ch2 id=\"the-solution\">The solution 🙌\u003C/h2>\n\u003Cp>Fortunately, there is another Nuxt module that handles GraphQL requests!\u003C/p>\n\u003Cp>\u003Ca href=\"https://github.com/gomah/nuxt-graphql-request\">Nuxt graphql request to the rescue!\u003C/a>\u003C/p>\n\u003Ch3 id=\"the-conf\">The conf\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// nuxt.config.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">buildModules\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\"> 'nuxt-graphql-request'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">graphql\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> clients\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\"> default\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> endpoint: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'http://API_URL/graphql'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> options: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> headers: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> authorization: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Bearer API_TOKEN'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">},\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"the-request\">The request\u003C/h3>\n\u003Cp>The best approach so far is to use \u003Ccode>asyncData\u003C/code> in pages and \u003Ccode>fetch\u003C/code> in components. Using \u003Ccode>fetch\u003C/code> in pages does not work well at all with \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>I also install the \u003Ccode>graphql-tag\u003C/code> package (only in \u003Ccode>devDependencies\u003C/code>) to be able to import directly \u003Ccode>.gql\u003C/code> files.\u003C/p>\n\u003Cp>Query example:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"graphql\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># homepage.gql\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">query\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\thomepage\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\ttitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\tsubtitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\thero\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\t\tid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\t\talt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"inside-a-page\">Inside a page\u003C/h4>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import homepageQuery from '~/graphql/queries/singles/homepage'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">asyncData\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({ $graphql }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> $graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(homepageQuery)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return { data }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"inside-a-component\">Inside a component\u003C/h4>\n\u003Cp>It is safer to wait until \u003Ccode>fetch\u003C/code> has received a response before displaying anything. You can use \u003Ccode>$fetchState\u003C/code> to be sure (\u003Ca href=\"https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch\" title=\"Documentation on the fetch hook (new tab)\">documentation\u003C/a>).\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// Header.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">template\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> <\u003C/span>\u003Cspan style=\"color:#85E89D\">header\u003C/span>\u003Cspan style=\"color:#B392F0\"> v-if\u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"!$fetchState.pending\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> …\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> </\u003C/span>\u003Cspan style=\"color:#85E89D\">header\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">template\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import headerQuery from '~/graphql/queries/singles/header'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> data\u003C/span>\u003Cspan style=\"color:#E1E4E8\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> data\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">fetch\u003C/span>\u003Cspan style=\"color:#E1E4E8\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> try {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\"> const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> data\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#79B8FF\"> this\u003C/span>\u003Cspan style=\"color:#E1E4E8\">.$graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(headerQuery)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\"> this\u003C/span>\u003Cspan style=\"color:#E1E4E8\">.data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> } catch (error) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> console.\u003C/span>\u003Cspan style=\"color:#B392F0\">error\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(JSON.stringify(\u003C/span>\u003Cspan style=\"color:#FFAB70\">error\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#FFAB70\">undefined\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, 2))\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"options\">Options\u003C/h3>\n\u003Cp>To pass options to the request, for example for a multilingual version with \u003Ca href=\"https://i18n.nuxtjs.org/\">nuxt/i18n\u003C/a> and/or a url parameter in a dynamic page:\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// _slug.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import articleQuery from '~/graphql/queries/articles'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">asyncData\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({ $graphql, app, params }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const locale \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> app.i18n.localeProperties.iso\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> $graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(articleQuery, {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> code: locale,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> slug: params.slug,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> })\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return { data }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":820,"imagePaths":843,"frontmatter":844},[821,824,827,830,833,837,840],{"depth":150,"slug":822,"text":823},"the-problem","The problem",{"depth":150,"slug":825,"text":826},"the-solution","The solution 🙌",{"depth":154,"slug":828,"text":829},"the-conf","The conf",{"depth":154,"slug":831,"text":832},"the-request","The request",{"depth":834,"slug":835,"text":836},4,"inside-a-page","Inside a page",{"depth":834,"slug":838,"text":839},"inside-a-component","Inside a component",{"depth":154,"slug":841,"text":842},"options","Options",[],{"title":809,"subtitle":810,"lang":68,"slug":806,"createdAt":170,"updatedAt":845,"excerpt":846,"tags":847,"type":435},"2022-09-08T13:43:33.000Z","When the most used gql module doesn't work…",[562],"nuxt-graphql-static",{"id":848,"data":850,"body":856,"filePath":857,"digest":858,"rendered":859},{"title":851,"subtitle":852,"lang":16,"tags":853,"type":427,"slug":848,"createdAt":854,"updatedAt":855},"Site statique et requêtes GraphQL avec Nuxt.js","Le client graphql est roi.",[562],["Date","2022-06-08T14:24:06.000Z"],["Date","2022-09-08T13:43:33.000Z"],"## Le problème\n\nJe me suis heurté à un villain bug en utilisant Nuxt en mode génération statique complète et le client [nuxt apollo](https://github.com/nuxt-community/apollo-module 'Dépôt github du module nuxt apollo (nouvel onglet)').\nAprès quelques recherches, voici [le bug constaté par quelqu'un d'autre](https://github.com/nuxt-community/apollo-module/issues/339 'Bug visible sur le dépôt github du module nuxt/apollo (nouvel onglet)') sur github.\n\nIl semblerait que le module en l'état ne gère pas correctement la génération statique avec `nuxt generate`.\n\nJe trouvais toujours des appels à mon API locale après la génération statique et la navigation depuis les `\u003Cnuxt-link>` ne fonctionnait pas.\n\n## La solution 🙌\n\nHeureusement, il existe un autre module Nuxt pour gérer les requêtes GraphQL !\n\n[Nuxt graphql request à la rescousse !](https://github.com/gomah/nuxt-graphql-request 'Dépôt github du module (nouvel onglet)')\n\n### La conf\n\n```javascript\n// nuxt.config.js\nbuildModules: [\n 'nuxt-graphql-request',\n],\ngraphql: {\n clients: {\n default: {\n endpoint: 'http://API_URL/graphql',\n options: {\n headers: {\n authorization: 'Bearer API_TOKEN',\n },\n },\n },\n },\n},\n```\n\n### La requête\n\nLa meilleure méthode à ce jour est d'utiliser `asyncData` dans les pages et `fetch` dans les composants. Utiliser `fetch` dans les pages ne fonctionne pas bien du tout avec `nuxt generate`.\n\nJ'installe également le paquet `graphql-tag` (uniquement en `devDependencies`) afin de pouvoir importer directement des fichiers `.gql`\n\nExemple de fichier :\n\n```graphql\n# homepage.gql\nquery {\n\thomepage {\n\t\ttitle\n\t\tsubtitle\n\t\thero {\n\t\t\tid\n\t\t\talt\n\t\t}\n\t}\n}\n```\n\n#### Dans une page\n\n```javascript\n// index.vue\n\u003Cscript>\nimport homepageQuery from '~/graphql/queries/singles/homepage'\n\nexport default {\n async asyncData({ $graphql }) {\n const data = await $graphql.default.request(homepageQuery)\n return { data }\n },\n}\n\u003C/script>\n```\n\n#### Dans un composant\n\nIl est plus prudent d'attendre que `fetch` ait reçu une réponse avant d'afficher quoi que ce soit. On peut utiliser `$fetchState` afin d'être tranquille ([documentation](https://fr.nuxtjs.org/docs/2.x/components-glossary/pages-fetch 'Documentation sur la méthode fetch (nouvel onglet)')).\n\n```javascript\n// Header.vue\n\u003Ctemplate>\n \u003Cheader v-if=\"!$fetchState.pending\">\n …\n \u003C/header>\n\u003C/template>\n\n\u003Cscript>\nimport headerQuery from '~/graphql/queries/singles/header'\n\nexport default {\n data() {\n return {\n data: {},\n }\n },\n async fetch() {\n try {\n const data = await this.$graphql.default.request(headerQuery)\n this.data = data\n } catch (error) {\n console.error(JSON.stringify(error, undefined, 2))\n }\n },\n}\n\u003C/script>\n```\n\n### Les options\n\nPour passer des options à la requête, par exemple pour une version multilingue avec [nuxt/i18n](https://i18n.nuxtjs.org/ 'Documentation de nuxt i18n (nouvel onglet)') et/ou un paramètre d'url dans le cadre d'une page dynamique :\n\n```javascript\n// _slug.vue\n\u003Cscript>\nimport articleQuery from '~/graphql/queries/articles'\n\nexport default {\n async asyncData({ $graphql, app, params }) {\n const locale = app.i18n.localeProperties.iso\n const data = await $graphql.default.request(articleQuery, {\n code: locale,\n slug: params.slug,\n })\n return { data }\n },\n}\n\u003C/script>\n```","src/content/fragments/fr/nuxt-graphql-static.md","73b6cc6b4fed04f5",{"html":860,"metadata":861},"\u003Ch2 id=\"le-problème\">Le problème\u003C/h2>\n\u003Cp>Je me suis heurté à un villain bug en utilisant Nuxt en mode génération statique complète et le client \u003Ca href=\"https://github.com/nuxt-community/apollo-module\" title=\"Dépôt github du module nuxt apollo (nouvel onglet)\">nuxt apollo\u003C/a>.\nAprès quelques recherches, voici \u003Ca href=\"https://github.com/nuxt-community/apollo-module/issues/339\" title=\"Bug visible sur le dépôt github du module nuxt/apollo (nouvel onglet)\">le bug constaté par quelqu’un d’autre\u003C/a> sur github.\u003C/p>\n\u003Cp>Il semblerait que le module en l’état ne gère pas correctement la génération statique avec \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>Je trouvais toujours des appels à mon API locale après la génération statique et la navigation depuis les \u003Ccode><nuxt-link>\u003C/code> ne fonctionnait pas.\u003C/p>\n\u003Ch2 id=\"la-solution\">La solution 🙌\u003C/h2>\n\u003Cp>Heureusement, il existe un autre module Nuxt pour gérer les requêtes GraphQL !\u003C/p>\n\u003Cp>\u003Ca href=\"https://github.com/gomah/nuxt-graphql-request\" title=\"Dépôt github du module (nouvel onglet)\">Nuxt graphql request à la rescousse !\u003C/a>\u003C/p>\n\u003Ch3 id=\"la-conf\">La conf\u003C/h3>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// nuxt.config.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">buildModules\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#9ECBFF\"> 'nuxt-graphql-request'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">graphql\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> clients\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\"> default\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> endpoint: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'http://API_URL/graphql'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> options: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> headers: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> authorization: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'Bearer API_TOKEN'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">},\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"la-requête\">La requête\u003C/h3>\n\u003Cp>La meilleure méthode à ce jour est d’utiliser \u003Ccode>asyncData\u003C/code> dans les pages et \u003Ccode>fetch\u003C/code> dans les composants. Utiliser \u003Ccode>fetch\u003C/code> dans les pages ne fonctionne pas bien du tout avec \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>J’installe également le paquet \u003Ccode>graphql-tag\u003C/code> (uniquement en \u003Ccode>devDependencies\u003C/code>) afin de pouvoir importer directement des fichiers \u003Ccode>.gql\u003C/code>\u003C/p>\n\u003Cp>Exemple de fichier :\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"graphql\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># homepage.gql\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">query\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\thomepage\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\ttitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\tsubtitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\thero\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\t\tid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFAB70\">\t\t\talt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"dans-une-page\">Dans une page\u003C/h4>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import homepageQuery from '~/graphql/queries/singles/homepage'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">asyncData\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({ $graphql }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> $graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(homepageQuery)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return { data }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"dans-un-composant\">Dans un composant\u003C/h4>\n\u003Cp>Il est plus prudent d’attendre que \u003Ccode>fetch\u003C/code> ait reçu une réponse avant d’afficher quoi que ce soit. On peut utiliser \u003Ccode>$fetchState\u003C/code> afin d’être tranquille (\u003Ca href=\"https://fr.nuxtjs.org/docs/2.x/components-glossary/pages-fetch\" title=\"Documentation sur la méthode fetch (nouvel onglet)\">documentation\u003C/a>).\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// Header.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">template\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> <\u003C/span>\u003Cspan style=\"color:#85E89D\">header\u003C/span>\u003Cspan style=\"color:#B392F0\"> v-if\u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"!$fetchState.pending\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> …\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> </\u003C/span>\u003Cspan style=\"color:#85E89D\">header\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">template\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import headerQuery from '~/graphql/queries/singles/header'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> data\u003C/span>\u003Cspan style=\"color:#E1E4E8\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\"> data\u003C/span>\u003Cspan style=\"color:#E1E4E8\">: {},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">fetch\u003C/span>\u003Cspan style=\"color:#E1E4E8\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> try {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\"> const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> data\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#79B8FF\"> this\u003C/span>\u003Cspan style=\"color:#E1E4E8\">.$graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(headerQuery)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\"> this\u003C/span>\u003Cspan style=\"color:#E1E4E8\">.data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> } catch (error) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> console.\u003C/span>\u003Cspan style=\"color:#B392F0\">error\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(JSON.stringify(\u003C/span>\u003Cspan style=\"color:#FFAB70\">error\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#FFAB70\">undefined\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, 2))\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"les-options\">Les options\u003C/h3>\n\u003Cp>Pour passer des options à la requête, par exemple pour une version multilingue avec \u003Ca href=\"https://i18n.nuxtjs.org/\" title=\"Documentation de nuxt i18n (nouvel onglet)\">nuxt/i18n\u003C/a> et/ou un paramètre d’url dans le cadre d’une page dynamique :\u003C/p>\n\u003Cpre class=\"astro-code github-dark\" style=\"background-color:#24292e;color:#e1e4e8; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">// _slug.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"><\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">import articleQuery from '~/graphql/queries/articles'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">export default {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> async \u003C/span>\u003Cspan style=\"color:#B392F0\">asyncData\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({ $graphql, app, params }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const locale \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> app.i18n.localeProperties.iso\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> const data \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#F97583\"> await\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> $graphql.default.\u003C/span>\u003Cspan style=\"color:#B392F0\">request\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(articleQuery, {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> code: locale,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> slug: params.slug,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> })\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> return { data }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\"></\u003C/span>\u003Cspan style=\"color:#85E89D\">script\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":862,"imagePaths":884,"frontmatter":885},[863,866,869,872,875,878,881],{"depth":150,"slug":864,"text":865},"le-problème","Le problème",{"depth":150,"slug":867,"text":868},"la-solution","La solution 🙌",{"depth":154,"slug":870,"text":871},"la-conf","La conf",{"depth":154,"slug":873,"text":874},"la-requête","La requête",{"depth":834,"slug":876,"text":877},"dans-une-page","Dans une page",{"depth":834,"slug":879,"text":880},"dans-un-composant","Dans un composant",{"depth":154,"slug":882,"text":883},"les-options","Les options",[],{"title":851,"subtitle":852,"lang":16,"slug":848,"createdAt":170,"updatedAt":845,"excerpt":886,"tags":887,"type":427},"Quand le module gql le plus utilisé ne fonctionne pas…",[562],"HPsections",["Map",890,891,911,912,928,929,945,946,970,971],"011-offre",{"id":890,"data":892,"body":899,"filePath":900,"digest":901,"rendered":902},{"type":893,"lang":16,"uid":894,"image":895,"order":896,"quickTitle":897,"quickImage":898,"reference":39},"section","offre","/assets/images/home/offre-1.1.svg",1.1,"Mes offres en freelance","/assets/images/home/icon-desktop.svg","## L'offre site web classique\n\nCette offre est destinée à un public souhaitant **se doter d'un site web**, sans forcément intégrer l'accessibilité au cœur du projet. Le site sera malgré tout développé au plus proche des règles du [référentiel général d'amélioration de l'accessibilité](https://accessibilite.numerique.gouv.fr/) (\u003Cabbr>RGAA\u003C/abbr>).\n\nL'objectif principal de cette offre étant d'**établir une présence en ligne** pour le client. Que cette dernière ait un but informatif et/ou éditorial.\n\n\u003C!-- \u003Ca href=\"/offres/web-classique\" class=\"btn\">L'offre classique en détails\u003C/a> -->","src/data/HP/011-offre.md","290ecd1ed94a1087",{"html":903,"metadata":904},"\u003Ch2 id=\"loffre-site-web-classique\">L’offre site web classique\u003C/h2>\n\u003Cp>Cette offre est destinée à un public souhaitant \u003Cstrong>se doter d’un site web\u003C/strong>, sans forcément intégrer l’accessibilité au cœur du projet. Le site sera malgré tout développé au plus proche des règles du \u003Ca href=\"https://accessibilite.numerique.gouv.fr/\">référentiel général d’amélioration de l’accessibilité\u003C/a> (\u003Cabbr>RGAA\u003C/abbr>).\u003C/p>\n\u003Cp>L’objectif principal de cette offre étant d’\u003Cstrong>établir une présence en ligne\u003C/strong> pour le client. Que cette dernière ait un but informatif et/ou éditorial.\u003C/p>\n\u003C!-- \u003Ca href=\"/offres/web-classique\" class=\"btn\">L'offre classique en détails\u003C/a> -->",{"headings":905,"imagePaths":909,"frontmatter":910},[906],{"depth":150,"slug":907,"text":908},"loffre-site-web-classique","L’offre site web classique",[],{"type":893,"uid":894,"lang":16,"image":895,"order":896,"quickTitle":897,"quickImage":898,"reference":39},"012-offre",{"id":911,"data":913,"body":916,"filePath":917,"digest":918,"rendered":919},{"type":893,"lang":16,"image":914,"order":915,"reference":50},"/assets/images/home/offre-1.2.svg",1.2,"## L'offre accessibilité avancée\n\nCette offre s'adresse plus spécifiquement aux entités pour lesquelles **l'accessibilité du site est un critère majeur.** Qu'il s'agisse d'une création ou d'une mise en conformité après un audit d'accessibilité.\n\nLorsque le projet le nécessite, je fais appel à des partenaires talentueux partageant les mêmes valeurs :\n\n- [Rose Primaire](https://roseprimaire.com/) pour le conseil et l'accompagnement du projet ;\n- [Sylvain Plantier](https://jedessinebien.com/) et/ou [Benoît Etchevery](http://ben-etche.com/) pour l'illustration et la direction artistique.\n\n\u003C!-- \u003Ca href=\"/offres/accessibilite\" class=\"btn\">L'offre accessibilité en détails\u003C/a> -->","src/data/HP/012-offre.md","2a3bf3411b3c171b",{"html":920,"metadata":921},"\u003Ch2 id=\"loffre-accessibilité-avancée\">L’offre accessibilité avancée\u003C/h2>\n\u003Cp>Cette offre s’adresse plus spécifiquement aux entités pour lesquelles \u003Cstrong>l’accessibilité du site est un critère majeur.\u003C/strong> Qu’il s’agisse d’une création ou d’une mise en conformité après un audit d’accessibilité.\u003C/p>\n\u003Cp>Lorsque le projet le nécessite, je fais appel à des partenaires talentueux partageant les mêmes valeurs :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://roseprimaire.com/\">Rose Primaire\u003C/a> pour le conseil et l’accompagnement du projet ;\u003C/li>\n\u003Cli>\u003Ca href=\"https://jedessinebien.com/\">Sylvain Plantier\u003C/a> et/ou \u003Ca href=\"http://ben-etche.com/\">Benoît Etchevery\u003C/a> pour l’illustration et la direction artistique.\u003C/li>\n\u003C/ul>\n\u003C!-- \u003Ca href=\"/offres/accessibilite\" class=\"btn\">L'offre accessibilité en détails\u003C/a> -->",{"headings":922,"imagePaths":926,"frontmatter":927},[923],{"depth":150,"slug":924,"text":925},"loffre-accessibilité-avancée","L’offre accessibilité avancée",[],{"type":893,"lang":16,"order":915,"image":914,"reference":50},"013-offre",{"id":928,"data":930,"body":933,"filePath":934,"digest":935,"rendered":936},{"type":893,"lang":16,"image":931,"order":932},"/assets/images/home/offre-1.3.svg",1.3,"## Et l'éco-conception alors ?\n\nJe ne conçois pas l'éco-conception comme une offre. C'est plutôt une façon de travailler, voire même une vision de mon métier. On fait rarement de l'éco-conception sans accessibilité, j'applique donc ces méthodologies quelque soit le projet !","src/data/HP/013-offre.md","03e37f364ac27cb4",{"html":937,"metadata":938},"\u003Ch2 id=\"et-léco-conception-alors\">Et l’éco-conception alors ?\u003C/h2>\n\u003Cp>Je ne conçois pas l’éco-conception comme une offre. C’est plutôt une façon de travailler, voire même une vision de mon métier. On fait rarement de l’éco-conception sans accessibilité, j’applique donc ces méthodologies quelque soit le projet !\u003C/p>",{"headings":939,"imagePaths":943,"frontmatter":944},[940],{"depth":150,"slug":941,"text":942},"et-léco-conception-alors","Et l’éco-conception alors ?",[],{"type":893,"lang":16,"order":932,"image":931},"020-methodo",{"id":945,"data":947,"body":952,"filePath":953,"digest":954,"rendered":955},{"type":893,"lang":16,"uid":948,"image":949,"order":150,"quickTitle":950,"quickImage":951},"methodology","/assets/images/home/methodo.svg","Ma méthodologie","/assets/images/home/icon-methodo.svg","## Méthodologie\n\n### Accessibilité par défaut\n\nEngagé pour un web plus accessible, je crée des **sites web** en m'appuyant sur le [référentiel général d'amélioration de l'accessibilité (RGAA)](https://www.numerique.gouv.fr/publications/rgaa-accessibilite/) ainsi que sur les bonnes pratiques [Opquast.](https://www.opquast.com/rendre-le-web-meilleur/)\n\n### Sobriété par choix\n\nJe privilégie le développement de **sites statiques** en adoptant une approche [d'éco-conception numérique.](https://eco-conception.designersethiques.org/guide/fr/) \nC'est-à-dire que le site est pensé pour n'embarquer que les fonctionnalités nécessaires à son utilisation.\n\nCette approche présente de **nombreux avantages :**\n\n- chargement rapide des pages ;\n- sécurité renforcée ;\n- coûts serveur réduits ;\n- maintenance facilitée.\n\nLorsque le projet le demande, je mets en place un outil de gestion des contenus (CMS) découplé de l'interface. Cela permet de garantir que **le site reste en ligne** même si le CMS venait à ne plus fonctionner.","src/data/HP/020-methodo.md","75a09b4e0b1e926b",{"html":956,"metadata":957},"\u003Ch2 id=\"méthodologie\">Méthodologie\u003C/h2>\n\u003Ch3 id=\"accessibilité-par-défaut\">Accessibilité par défaut\u003C/h3>\n\u003Cp>Engagé pour un web plus accessible, je crée des \u003Cstrong>sites web\u003C/strong> en m’appuyant sur le \u003Ca href=\"https://www.numerique.gouv.fr/publications/rgaa-accessibilite/\">référentiel général d’amélioration de l’accessibilité (RGAA)\u003C/a> ainsi que sur les bonnes pratiques \u003Ca href=\"https://www.opquast.com/rendre-le-web-meilleur/\">Opquast.\u003C/a>\u003C/p>\n\u003Ch3 id=\"sobriété-par-choix\">Sobriété par choix\u003C/h3>\n\u003Cp>Je privilégie le développement de \u003Cstrong>sites statiques\u003C/strong> en adoptant une approche \u003Ca href=\"https://eco-conception.designersethiques.org/guide/fr/\">d’éco-conception numérique.\u003C/a>\u003Cbr>\nC’est-à-dire que le site est pensé pour n’embarquer que les fonctionnalités nécessaires à son utilisation.\u003C/p>\n\u003Cp>Cette approche présente de \u003Cstrong>nombreux avantages :\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>chargement rapide des pages ;\u003C/li>\n\u003Cli>sécurité renforcée ;\u003C/li>\n\u003Cli>coûts serveur réduits ;\u003C/li>\n\u003Cli>maintenance facilitée.\u003C/li>\n\u003C/ul>\n\u003Cp>Lorsque le projet le demande, je mets en place un outil de gestion des contenus (CMS) découplé de l’interface. Cela permet de garantir que \u003Cstrong>le site reste en ligne\u003C/strong> même si le CMS venait à ne plus fonctionner.\u003C/p>",{"headings":958,"imagePaths":968,"frontmatter":969},[959,962,965],{"depth":150,"slug":960,"text":961},"méthodologie","Méthodologie",{"depth":154,"slug":963,"text":964},"accessibilité-par-défaut","Accessibilité par défaut",{"depth":154,"slug":966,"text":967},"sobriété-par-choix","Sobriété par choix",[],{"type":893,"uid":948,"lang":16,"image":949,"order":150,"quickTitle":950,"quickImage":951},"030-about",{"id":970,"data":972,"body":977,"filePath":978,"digest":979,"rendered":980},{"type":893,"lang":16,"uid":973,"image":974,"order":154,"quickTitle":975,"quickImage":976},"about","/assets/images/home/about.svg","Moi","/assets/images/home/icon-heart.svg","## À propos\n\n### Formations personnelles\n\nAfin de solidifier mes compétences, j'ai suivi les formations et passé les certifications suivantes :\n\n- [Opquast](https://directory.opquast.com/fr/certificat/CTQSKP/) - Maîtrise de la qualité en projet web ;\n- Access42 - Développer et coder des sites accessibles (certificat numéro : 696fa2e0-cc67-11ec-88d2-9dabf3f992d4).\n\n### Formations des autres\n\nDepuis plusieurs années, j'interviens dans différents campus afin de dispenser des cours de développement web.\n\n### Temps libre\n\nJ’essaie de contribuer à des [projets open source](https://git.nardu.in/explore/repos) qui me tiennent à cœur et je m'engage localement avec le collectif [good-it!](https://www.good-it.org/)\n\nAh et j’écris [des articles](/articles) aussi ! Des articles sur le design, le développement web et l’informatique.","src/data/HP/030-about.md","a7abff6d744406ce",{"html":981,"metadata":982},"\u003Ch2 id=\"à-propos\">À propos\u003C/h2>\n\u003Ch3 id=\"formations-personnelles\">Formations personnelles\u003C/h3>\n\u003Cp>Afin de solidifier mes compétences, j’ai suivi les formations et passé les certifications suivantes :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://directory.opquast.com/fr/certificat/CTQSKP/\">Opquast\u003C/a> - Maîtrise de la qualité en projet web ;\u003C/li>\n\u003Cli>Access42 - Développer et coder des sites accessibles (certificat numéro : 696fa2e0-cc67-11ec-88d2-9dabf3f992d4).\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"formations-des-autres\">Formations des autres\u003C/h3>\n\u003Cp>Depuis plusieurs années, j’interviens dans différents campus afin de dispenser des cours de développement web.\u003C/p>\n\u003Ch3 id=\"temps-libre\">Temps libre\u003C/h3>\n\u003Cp>J’essaie de contribuer à des \u003Ca href=\"https://git.nardu.in/explore/repos\">projets open source\u003C/a> qui me tiennent à cœur et je m’engage localement avec le collectif \u003Ca href=\"https://www.good-it.org/\">good-it!\u003C/a>\u003C/p>\n\u003Cp>Ah et j’écris \u003Ca href=\"/articles\">des articles\u003C/a> aussi ! Des articles sur le design, le développement web et l’informatique.\u003C/p>",{"headings":983,"imagePaths":996,"frontmatter":997},[984,987,990,993],{"depth":150,"slug":985,"text":986},"à-propos","À propos",{"depth":154,"slug":988,"text":989},"formations-personnelles","Formations personnelles",{"depth":154,"slug":991,"text":992},"formations-des-autres","Formations des autres",{"depth":154,"slug":994,"text":995},"temps-libre","Temps libre",[],{"type":893,"uid":973,"lang":16,"image":974,"order":154,"quickTitle":975,"quickImage":976},"veille",["Map",269,1000],{"id":269,"data":1001,"body":1003,"filePath":1004,"digest":1005,"rendered":1006},{"lang":16,"title":269,"updatedAt":1002},["Date","2023-04-20T17:12:06.000Z"],"- [mmm.page](https://build.mmm.page/) - Éditeur de sites web très simples, en glisser-déposer, pour n'importe quoi.\n- [Color.io](https://www.color.io/) - Éditeur photo en ligne.\n- [Addy's toolkit](https://toolkit.addy.codes/) - Outils et ressources pour les designers et développeurs sites web.\n- [L’accessibilité n’est pas une variable d’ajustement](https://www.sophie-drouvroy.com/blog/laccessibilite-nest-pas-une-variable-dajustement/) — Sophie Drouvroy, intégratrice front-end, partage son quotidien en tant que personne sourde dans notre société.\n > L’accessibilité doit être au cœur du projet et pas une cerise sur le gâteau.\n- [3D en CSS (english)](https://garden.bradwoods.io/notes/css/3d) – Explications et exemples des propriétés 3D en CSS.\n- [Climat : Comment ne pas déprimer ?](https://www.lemonde.fr/podcasts/article/2022/06/21/climat-comment-ne-pas-deprimer_6131347_5463015.html) – Podcast.\n- [Fable (english)](https://fable.app) – Application de motion design.\n- [Rive (english)](https://rive.app) – Application de motion design.\n- [Cake Desk](https://cakedesk.app/) – Application de facturation.\n- [Ombre fluide en CSS](https://shadows.brumm.af/) – Générateur.\n- [Smol CSS](https://smolcss.dev/) – Collection de fragments CSS.\n- [Ajustement optique](https://marvelapp.com/blog/optical-adjustment-logic-vs-designers/) (english) – Aligner visuellement plutôt que techniquement.\n- [Datawrapper](https://blog.datawrapper.de/category/datavis-dos-and-donts/) (english) – Conseils pour montrer de la donnée.\n- [Assistivlabs](https://assistivlabs.com/) (english) – Service de test des technologies d'assistance (browserstack mais pour l'accessibilité).\n- [Les caractères fantaisistes et l'accessibilité](https://www.lalutineduweb.fr/detournement-unicode-emojis-accessibilite/) – Explications et exemples de l'enfer que sont les caractères Unicode pour les technologies d'assistance.\n- [Créer un champ `time` sur le web](https://adamsilver.io/blog/designing-a-time-input-backed-by-research/) (english) – Article.\n- [La cascade](https://la-cascade.io) – Collection d'articles sur le CSS.\n- [Tabby](https://tabby.sh) (english) – An alternative terminal app.\n- [Newglyph](https://newglyph.com/) – Fonderie indépendante.\n- [\u003Cspan lang=\"en\">Headless UI\u003C/span>](https://headlessui.com/vue/dialog) (english) – Librairie de composants vue et react.\n- [Vie privée sexy](https://privacy.sexy) (english) – Outils de confidentialité pour windows et macos.\n- [33 concepts JavaScript](https://github.com/leonardomso/33-js-concepts) (english) – Articles.\n- [Formbricks](https://formbricks.com/) (english) – Alternative open source à google form/typeform.\n- [Animations de chargement SVG](https://github.com/n3r4zzurr0/svg-spinners) – Collection.\n- [a11yphant](https://a11yphant.com/) (english) – Challenges de code pour apprendre l'accessibilité.\n- [CSS moderne](https://moderncss.dev/) (english) – Fragments CSS.\n- [Conteneur moderne en CSS](https://twitter.com/KevinJPowell/status/1501555193799925761) (english) – Tweet de Kevin Powell ❤️","src/data/veille/2023.md","1135beec386f207f",{"html":1007,"metadata":1008},"\u003Cul>\n\u003Cli>\u003Ca href=\"https://build.mmm.page/\">mmm.page\u003C/a> - Éditeur de sites web très simples, en glisser-déposer, pour n’importe quoi.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.color.io/\">Color.io\u003C/a> - Éditeur photo en ligne.\u003C/li>\n\u003Cli>\u003Ca href=\"https://toolkit.addy.codes/\">Addy’s toolkit\u003C/a> - Outils et ressources pour les designers et développeurs sites web.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.sophie-drouvroy.com/blog/laccessibilite-nest-pas-une-variable-dajustement/\">L’accessibilité n’est pas une variable d’ajustement\u003C/a> — Sophie Drouvroy, intégratrice front-end, partage son quotidien en tant que personne sourde dans notre société.\n\u003Cblockquote>\n\u003Cp>L’accessibilité doit être au cœur du projet et pas une cerise sur le gâteau.\u003C/p>\n\u003C/blockquote>\n\u003C/li>\n\u003Cli>\u003Ca href=\"https://garden.bradwoods.io/notes/css/3d\">3D en CSS (english)\u003C/a> – Explications et exemples des propriétés 3D en CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lemonde.fr/podcasts/article/2022/06/21/climat-comment-ne-pas-deprimer_6131347_5463015.html\">Climat : Comment ne pas déprimer ?\u003C/a> – Podcast.\u003C/li>\n\u003Cli>\u003Ca href=\"https://fable.app\">Fable (english)\u003C/a> – Application de motion design.\u003C/li>\n\u003Cli>\u003Ca href=\"https://rive.app\">Rive (english)\u003C/a> – Application de motion design.\u003C/li>\n\u003Cli>\u003Ca href=\"https://cakedesk.app/\">Cake Desk\u003C/a> – Application de facturation.\u003C/li>\n\u003Cli>\u003Ca href=\"https://shadows.brumm.af/\">Ombre fluide en CSS\u003C/a> – Générateur.\u003C/li>\n\u003Cli>\u003Ca href=\"https://smolcss.dev/\">Smol CSS\u003C/a> – Collection de fragments CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://marvelapp.com/blog/optical-adjustment-logic-vs-designers/\">Ajustement optique\u003C/a> (english) – Aligner visuellement plutôt que techniquement.\u003C/li>\n\u003Cli>\u003Ca href=\"https://blog.datawrapper.de/category/datavis-dos-and-donts/\">Datawrapper\u003C/a> (english) – Conseils pour montrer de la donnée.\u003C/li>\n\u003Cli>\u003Ca href=\"https://assistivlabs.com/\">Assistivlabs\u003C/a> (english) – Service de test des technologies d’assistance (browserstack mais pour l’accessibilité).\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lalutineduweb.fr/detournement-unicode-emojis-accessibilite/\">Les caractères fantaisistes et l’accessibilité\u003C/a> – Explications et exemples de l’enfer que sont les caractères Unicode pour les technologies d’assistance.\u003C/li>\n\u003Cli>\u003Ca href=\"https://adamsilver.io/blog/designing-a-time-input-backed-by-research/\">Créer un champ \u003Ccode>time\u003C/code> sur le web\u003C/a> (english) – Article.\u003C/li>\n\u003Cli>\u003Ca href=\"https://la-cascade.io\">La cascade\u003C/a> – Collection d’articles sur le CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://tabby.sh\">Tabby\u003C/a> (english) – An alternative terminal app.\u003C/li>\n\u003Cli>\u003Ca href=\"https://newglyph.com/\">Newglyph\u003C/a> – Fonderie indépendante.\u003C/li>\n\u003Cli>\u003Ca href=\"https://headlessui.com/vue/dialog\">\u003Cspan lang=\"en\">Headless UI\u003C/span>\u003C/a> (english) – Librairie de composants vue et react.\u003C/li>\n\u003Cli>\u003Ca href=\"https://privacy.sexy\">Vie privée sexy\u003C/a> (english) – Outils de confidentialité pour windows et macos.\u003C/li>\n\u003Cli>\u003Ca href=\"https://github.com/leonardomso/33-js-concepts\">33 concepts JavaScript\u003C/a> (english) – Articles.\u003C/li>\n\u003Cli>\u003Ca href=\"https://formbricks.com/\">Formbricks\u003C/a> (english) – Alternative open source à google form/typeform.\u003C/li>\n\u003Cli>\u003Ca href=\"https://github.com/n3r4zzurr0/svg-spinners\">Animations de chargement SVG\u003C/a> – Collection.\u003C/li>\n\u003Cli>\u003Ca href=\"https://a11yphant.com/\">a11yphant\u003C/a> (english) – Challenges de code pour apprendre l’accessibilité.\u003C/li>\n\u003Cli>\u003Ca href=\"https://moderncss.dev/\">CSS moderne\u003C/a> (english) – Fragments CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/KevinJPowell/status/1501555193799925761\">Conteneur moderne en CSS\u003C/a> (english) – Tweet de Kevin Powell ❤️\u003C/li>\n\u003C/ul>",{"headings":1009,"imagePaths":1010,"frontmatter":1011},[],[],{"lang":16,"title":269,"updatedAt":1012},"2023-04-20T17:12:06.000Z"] \ No newline at end of file +[["Map",1,2,9,10,61,62,427,428,888,889,903,904],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.1.1","content-config-digest","8021b3469f132349","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://www.nardu.in\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[\"assets.nardu.in\"],\"remotePatterns\":[{\"protocol\":\"https\"}]},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":\"shiki\",\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"one-dark-pro\",\"themes\":{},\"wrap\":false,\"transformers\":[{\"name\":\"@shikijs/transformers:meta-highlight\"}]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"i18n\":{\"defaultLocale\":\"fr\",\"locales\":[\"fr\",\"en\"],\"routing\":{\"prefixDefaultLocale\":false,\"redirectToDefaultLocale\":true,\"fallbackType\":\"redirect\"}},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"responsiveImages\":false},\"legacy\":{\"collections\":false}}","references",["Map",11,12,25,26,39,40,50,51],"3w",{"id":11,"data":13,"filePath":21,"digest":22,"rendered":23},{"title":11,"subtitle":14,"url":15,"lang":16,"slug":11,"tags":17,"createdAt":20},"J'ai fait de la doc!","https://3-w.fr","fr",[18,19],"Front-end","documentation",["Date","2022-10-19T18:02:00.000Z"],"src/content/references/3w.md","0d3d94c8af754e1b",{"html":24},"","natureo",{"id":25,"data":27,"filePath":36,"digest":37,"rendered":38},{"title":28,"subtitle":29,"url":30,"lang":16,"slug":25,"tags":31,"createdAt":35},"Nature en Occitanie","La sobriété au naturel.","https://www.natureo.org/",[18,32,33,34],"accessibilité","éco-conception","CMS",["Date","2023-04-19T18:02:00.000Z"],"src/content/references/natureo.md","6a7169b855b57024",{"html":24},"parole-expression",{"id":39,"data":41,"filePath":47,"digest":48,"rendered":49},{"title":42,"subtitle":43,"url":44,"lang":16,"slug":39,"tags":45,"createdAt":46},"Parole Expression","Un nouveau site pour l'association.","https://www.paroleexpression.fr/",[18,33,34],["Date","2022-04-19T17:11:00.000Z"],"src/content/references/parole-expression.md","ec95a408f8c3e99c",{"html":24},"rose-primaire",{"id":50,"data":52,"filePath":58,"digest":59,"rendered":60},{"title":53,"subtitle":54,"url":55,"lang":16,"slug":50,"tags":56,"createdAt":57},"Rose Primaire","Une agence comme on l'aime.","https://roseprimaire.com/",[18,32,33,34],["Date","2023-04-19T17:11:00.000Z"],"src/content/references/rose-primaire.md","a0133200cf1bee58",{"html":24},"articles",["Map",63,64,76,77,89,90,102,103,113,114,124,125,134,135,171,172,205,206,224,225,239,240,269,270,298,299,315,316,366,367,410,411],"en-after-effects-expressions",{"id":63,"data":65,"body":73,"filePath":74,"digest":75,"deferredRender":72},{"title":66,"subtitle":67,"lang":68,"tags":69,"type":61,"slug":63,"createdAt":71,"code":72},"After Effects Expressions","Animation on steroïds.","en",[70],"Design",["Date","2019-04-24T09:00:00.000Z"],true,"import AstroImage from '../../../components/AstroImage.astro'\n\n## An ever lasting battle\n\nThere is very little documentation and the existing one is hard to find or very old. Very often I just don't have the time to dive into expression learning while animating even though it could help the entire project on the long term.\nSo the last time I had to do a complex animation, **I took the damn time!**\n\n## The begining of the end (of keyframes).\n\nEveryone uses expressions whether they know it or not. Most of the time it's a rather transparent process for the animator. For example: when parenting a property to another one, After Effects creates an expression for us.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/basic_expression_d81b12f1ac.jpeg'\n\twidth='728'\n\theight='80'\n\talt='Parenting the position of the form to a null creates an expression.'\n/>\n\nOver the last updates, Adobe has made an effort to make expressions more accessible to everyone. For example, the expression box is now resembling a code editor thanks to code-coloring and auto-completion features. After Effects expression feel like JavaScript with custom functions.\n\nThose custom functions can be called through a menu once you enabled the expressions on a property. It offers organized shortcut and proper syntax to all of AE native functions and a bunch of JavaScript standard ones.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/shortcut_39cc19d383.jpeg'\n\twidth='728'\n\theight='322'\n\talt='Alt + Click the stopwatch to access the shortcuts.'\n/>\n\n## So I need to learn javascript to do motion design now?\n\n### Why bother?\n\nI know that most animators don't have any kind of development background. However, if Adobe thought it best to let us use expressions, I think we ought to, at least, try.\n\n> A lot of incredible professionals like [Mt Mograph](https://www.mtmograph.com/) and [Video Copilot](https://videocopilot.net/) use expressions.\n\nLike every optimization process, building an expressions knowledge takes time. However, like all optimization process, you will benefit from it afterwards.\n\n### Where to learn\n\nI've gathered a list of my favourite learning grounds. Plenty more exist, **go get'em!**\n\n- [Adobe official expression starter guide (FR)](https://helpx.adobe.com/fr/after-effects/using/expression-language-reference.html)\n- [Adobe official expression basic (EN)](https://helpx.adobe.com/after-effects/using/expression-basics.html)\n- [Adobe forums for expressions](https://community.adobe.com/t5/after-effects/bd-p/after-effects?page=1&sort=latest_replies&filter=all&topics=label-expressions)\n- [Creative Cow expressions forums](https://creativecow.net/forums/forum/adobe-after-effects-expressions/)\n- [Youtube channel about expressions](https://www.youtube.com/playlist?list=PLvr5U5ZSt6IzHyvSL9fo0M9NRPsTvra31)\n- [All expressions explained](http://aescript.jecool.net/reference/)\n- [All expressions explained again](http://expressions.aenhancers.com/index.html)\n- [Nice examples of basic expressions](https://www.schoolofmotion.com/tutorials/amazing-expressions-in-after-effects)\n\n## Real world example\n\n### Number counter\n\nLet's say you need to animate a rather simple counter from 0% to 100%.\n\n- Start by creating a text layer. Define your typographic choices, colours, etc.\n- On the effect menu add expression options > slider control\n- Alt + Click the Source text property\n\n\u003Cvideo width='728' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/alt-counter.mp4' type='video/mp4' />\n\u003C/video>\n\n- Parent the source text to the slider control through the pickwhip.\n\n\u003Cvideo width='462' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/pickwhip.mp4' type='video/mp4' />\n\u003C/video>\n\nYou should get something like this in the expressions panel:\n\n```javascript\neffect(\"Slider Control\")(\"Slider\")​\n```\n\n- Set two keyframes on the slider from 0 to 100. The text should update accordingly.\n- By default, After Effects does not round numbers. In the expression panel, wrap your expression with the `Math.round()` function.\n\n\u003Cvideo width='728' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/round.mp4' type='video/mp4' />\n\u003C/video>\n\n```javascript\nMath.round(effect(\"Slider Control\")(\"Slider\"))​\n```\n\nGreat! We have a working counter. But we wanted a percentage counter. We could add a % glyph in another text layer but let's not.\n\nStill in the expression panel, we're going to add a string containing the % glyph, using basic JavaScript concatenation: `+ '%'`\n\n```javascript\nMath.round(effect(\"Slider Control\")(\"Slider\")) + '%'​\n```\n\n\u003Cvideo width='538' loop controls preload='metadata'>\n\t\u003Csource src='https://assets.nardu.in/percent.mp4' type='video/mp4' />\n\u003C/video>\n\n**And there we go!** A fully functioning and customizable counter using a slider controller and expressions.","src/content/articles/en/after-effects-expressions.mdx","3b6f88fbf35af1a4","en-sci-hub-unblock",{"id":76,"data":78,"body":86,"filePath":87,"digest":88,"deferredRender":72},{"title":79,"subtitle":80,"lang":68,"tags":81,"type":61,"slug":76,"createdAt":84,"updatedAt":85},"Access blocked Sci-hub","The science of sharing.",[82,83],"Internet","Science",["Date","2019-03-31T07:47:36.000Z"],["Date","2022-12-27T12:08:00.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\nThe current sci-hub address is: \u003Ca href=\"https://sci-hub.se\" rel=\"noreferer noopener\">sci-hub.se\u003C/a>\n\n## What is this about?\n\nNot being a researcher myself, here’s an [extremely well done explanatory video](https://youtu.be/rcgxY__YXEc) on the subject of scientific publication (french audio with auto subtitle).\n\n> “This is outrageous!”​\n\nI noticed that my ISP was indeed blocking access. I have not yet been able to check for the other suppliers, but I imagine that they have all complied with the court decision.\nThe restriction in place is quite basic. This is a “DNS” block. A DNS is a server that is used to link a domain name: **www.sci-hub.tw** to an IP address: **186.2.163.90**\nIt is, in a way, the Internet phone book. Without the address, it is impossible to contact the domain. What ISPs have certainly done: block requests to the [sci-hub.se.](http://sci-hub.se/) domain name. As a result, no IP address is returned and the site is not accessible.\n\n## How to bypass this?\n\n- Either by using a VPN\n- Either by modifying the DNS servers of your computers/Internet box\n\nI would recommend the second solution because it allows you to protect yourself against future blockages/filtering/censorship from your ISP and does not require any financial compensation.\nI will focus on change from a computer because it will be effective wherever you are and not only from your home.\n\n### MacOs\n\nGo to:\n\n1. System Preferences\n1. Network\n1. (wi-fi and/or ethernet)\n1. Advanced\n1. DNS\n\nFrom there, you can add DNS servers by clicking the + icon. Click ok and apply the new settings. You might need to restart your computer for the changes to work.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/ef5a4b8e82a046e6a466c73c2fd9e99e.jpg'\n\twidth='728'\n\theight='1060'\n\talt='MacOS network and DNS settings'\n/>\n\n### Windows (10)\n\nGo to:\n\n1. System Settings\n1. Network & Internet\n1. Change adapter options\n1. Right click your adapter then “properties”\n1. Select “internet protocol version 4” (and/or 6)\n1. Properties\n1. Use the following DNS server addresses\n\nFrom there, you can add DNS servers. Click save. You might need to restart your computer for the changes to work.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-settings.jpg'\n\twidth='728'\n\theight='319'\n\talt='Windows system settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-network.jpg'\n\twidth='728'\n\theight='803'\n\talt='Windows network settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter.jpg'\n\twidth='728'\n\theight='327'\n\talt='Windows network connections settings'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter-settings.jpg'\n\twidth='728'\n\theight='434'\n\talt='Windows network adapter settings'\n/>\n\n## Which DNS?\n\nThere are many DNS servers available. The best known are Google, Cloudflare and OpenDNS. If you really want to use Google’s, I’ll let you look up their address. Here are my recommendations in order of preference.\n\n### [FDN DNS](https://www.fdn.fr/actions/dns/)\n\nMy favorite since it is a [french association](https://www.fdn.fr/)\n\n1. IPV4\n - 80.67.169.12\n - 80.67.169.40\n2. IPV6\n - 2001:910:800::12\n - 2001:910:800::40\n\n### [Quad9](https://www.quad9.net)\n\nQuand9 is a non-profit foundation offering free public DNS servers. Their classic servers offer filtering of identified malicious domains. They do not collect data and are \u003Cabbr title=\"General Data Protection Regulation\">GDPR\u003C/abbr>-compliant.\n\n1. IPV4\n - 9.9.9.9\n - 149.112.112.112\n2. IPV6\n - 2620:fe::fe\n - 2620:fe::9\n\n## That's it.\n\nBy changing these settings, you are free from your ISPs and their content filtering rules.\n\nFor the moment, these restrictions are almost symbolic because if Sci-hub were to change its url, the block would no longer work. But the publishers’ victory in court shows that they have not had their last word. We are therefore not immune to a wider and stronger block in the future.\n\nIf you want to learn more about the struggle of the people who fight to ensure that research is not a paid commodity, I recommend [this documentary](https://youtu.be/y_CQATGOX2w) on Aaron Shwartz. Or [this article](https://arstechnica.com/tech-policy/2016/04/a-spiritual-successor-to-aaron-swartz-is-angering-publishers-all-over-again/) about the founder of Sci-hub.\n\nIn the meantime, good readings to all of you. We stand with you!","src/content/articles/en/sci-hub-blocage.mdx","8959506d941cdcc5","en-the-day-I-jamd",{"id":89,"data":91,"body":99,"filePath":100,"digest":101,"deferredRender":72},{"title":92,"subtitle":93,"lang":68,"tags":94,"type":61,"slug":89,"createdAt":97,"updatedAt":98},"The day I Jam’d","A story of unusual tools and fun gambles.",[95,96],"Dev","Jamstack",["Date","2020-10-08T09:00:00.000Z"],["Date","2022-12-27T15:40:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## The not so easy choice\n\nWhen I was still using Wordpress for my personal website, I thought it would be nice to try [OpenLiteSpeed](https://openlitespeed.org) webserver. Being a designer, I always like to have a graphical interface and I heard OLS had very nice caching and overall performances.\n\n## FIGHT!\n\nA few years later, I learned about Jamstack and its incredible potential. Not being impulsive at all, I chose to entirely remake my website with tools like [11ty](https://www.11ty.dev/) and [Strapi](https://strapi.io/).\n\nI remember Strapi still being in alpha/beta and colleagues telling me it was a risky gamble, especially since I was pretty new to the node.js world.\n\n> Open source and french? Sign me up!\n\nSo I started recreating my website identically with 11ty and Strapi. Same hosting on a Digital Ocean droplet, same webserver, same content. I had done a fair amout of performance optimizations on my wordpress install so I was eager to compare the results with the new static version.\n\nBoy did they exceed my expectations! With almost no optimization on the static side, I got the following results.\n\n### wordpress\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/wordpress_8ee6f54b98.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Performance score of 53/100 on Wordpress.'\n/>\n\nDespite a lot of efforts I could not do better. I’m no expert in caching, do not use CDN and relied on plugins to achieve a lot of stuff (php not being my strongest skill 😬).\n\n### 11ty + strapi\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/static_2c0d9f1eb8.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Performance score of 97/100 on jamstack.'\n/>\n\nAlmost **zero** special configuration (I was too anxious to test) and I reached an awesome score. I know lighthouse scores are not everything but hey, **53 vs 97**… I’ll take it!\n\n## Now kiss 🥰\n\nBoth of these approaches have their benefits and drawbacks. As a freelance, my clients often prefer or ask for Wordpress because of its reputation. I always present a Jamstack alternative when possible but it’s still scary to most compared to Wordpress. I feel however that it’s going to be easier to use Jamstack with time.\n\n## I did it again…\n\nHere we are now, a quarantine and a few months later and this website is running with… [Nuxt.js](https://nuxtjs.org/). I know, I’m sorry, I couldn’t resist the latest [nuxt content](https://content.nuxtjs.org/) functionnality.\n\nSo I re-did everything again… and let me just say: **wow**, what an experience!\nI **love** developing with Nuxt. Using nuxt content allowed me to focus on design and, well, content.\nNo more Apollo client and graphQL query, only markdown and a few promises.\n\nDon’t get me wrong, I really like working with Strapi and its graphQL capabilities but for the purpose of this website, nuxt content does it (extremely well).\n\nI’m still using Strapi as a way to upload, store and manage images, videos, gifs, etc. It might be too much for this use case but I like to know that I can still go back to it if I want to! Also, I spent quite a bit of time setting it up with OpenLiteSpeed and I’m still too attached to this accomplishment to let it go.\n\n## In the end\n\nWordpress, Jamstack, vanilla everything… Does it really matter? For me, the dev experience was far more enjoyable working with 11ty, nuxt.js and strapi than with Wordpress.\n\nOn the performance and accessibility side, it also seems to be the better/smarter choice. It might not be everytime! ¯\\\\\\_(ツ)\\_/¯\n\nCan’t wait to learn [astro](https://astro.build/) and start from scratch again!","src/content/articles/en/the-day-I-jamd.mdx","60b77e216e02f618","en-video-compression",{"id":102,"data":104,"body":110,"filePath":111,"digest":112,"deferredRender":72},{"title":105,"subtitle":106,"lang":68,"tags":107,"type":61,"slug":102,"createdAt":108,"updatedAt":109},"Video compression","Encode like you mean it.",[70],["Date","2021-05-05T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Let's play.\n\nVideos are everywhere. **EVERYWHERE!** But videos can and will be huge when 4k becomes an internet standard. Currently, 1920x1080 is king and we usually have no problem hosting or playing this resolution.\n\n## Because we can doesn't mean we should.\n\nRight now, the (good) trend of web performance is on the rise. Everyone wants a blazing fast loading website, which might not be possible if we send requests to 100mb (or even more) videos.\n\nWith a good connection, users will not see the difference. But if we go down that path, nor will they with a 300mb one. So the goal is to make every asset as small as possible. It's already the case with images. But it's simpler and faster than video encoding.\n\n## Small size, best quality.\n\nLet's say we exported​ a 1920x1080 video from Premiere Pro with these basic settings:\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-premiere-1.jpeg'\n\twidth='673'\n\theight='800'\n/>\n\nIt's gorgeous, it's Full HD, it's 1:30 minute of excellent editing but it's 50mb… What a shame.\n\n> We can already bring down the size from Premiere or Media Encoder by selecting CBR instead of VBR and using a low bitrate (like 2 or 3).\n\nLet's now use [Handbrake!](https://handbrake.fr/) It's free, open source and multi platform. You can also read this great article from [Ueno](https://loremipsum.ueno.co/dear-ueno-how-do-you-compress-videos-6657ebd9dd28?gi=930afecec398) on video encoding.\n\n**Please please PLEASE. Never export videos from within After Effects.**\n\n## Handbrake\n\n### Summary screen\n\nWhile it's not as nice as Premiere Pro, it has way more exporting capabilities. Follow these steps to use good standard settings:\n\n1. Open your source video\n1. Select a preset corresponding to your future usage like Fast 1080p30\n1. Check Web Optimized\n1. Keep MPEG-4 as the format\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-1.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Video screen\n\n1. Keep H.264 (x264) or use H.264 nvidia nvenc if you can (crazy fast encoding by nvidia)\n1. Choose Constant Quality and try a value between 20 and 30​ (higher = smaller size but lower quality)\n1. Choose Peak Framerate. If you don't know the framerate, keep the default setting\n1. Choose the type of video you are encoding (film, animation…)\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-2.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Audio screen\n\nIf you don't have audio, be sure to set the audio channel to none.\nIf you have an audio channel, these settings are great and will not influence the size much​:\n\n1. Codec AAC\n1. Samplerate 44.1\n1. Bitrate 192 to 256 (your choice)\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-3.jpeg'\n\twidth='728'\n\theight='337'\n/>\n\n### Export!\n\nI used a RF of 25 for this example and no audio.\n\n1. My Premiere Pro video was 50,6mb\n1. My Handbrake video is 5,5mb​\n\n> What a save!\n\n​I ended up dividing the original size by 10. Which is cool.\nI tried with a RF of 30. The video was still pretty good and only 3,3mb.\n\n## Exporting for the web\n\nNow that we know how to properly compress videos, let's go further. Say we have a website with a lot of videos on the same page. We still want to load the content as fast as possible. So our videos need to be as small as possible. We won't do better than previously seen using mp4/H.264. However, we can use **webm/VP9.**\nWebm is an html video format and VP9 is its latest codec.\n\nUsing Handbrake and webm/VP9, we can achieve really great compression without losing too much quality (or none at all depending on the settings). I was able to divide by 4 the size of a video using these presets:\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/video-handbrake-4.jpg'\n\twidth='728'\n\theight='313'\n\talt=''\n/>\n\nThe only down side is that it takes some time to encode. It will depend on the video length and your computing power.\n\nI tried various settings but I read [here](https://trac.ffmpeg.org/wiki/Encode/VP9) that VP9 is supposed to be used with two-pass encoding. You then have to find the right bitrate (here 1000) for your situation.","src/content/articles/en/video-compression.mdx","5bb9f69df6c651d1","sci-hub-blocage",{"id":113,"data":115,"body":121,"filePath":122,"digest":123,"deferredRender":72},{"title":116,"subtitle":117,"lang":16,"tags":118,"type":61,"slug":113,"createdAt":119,"updatedAt":120},"Sci-hub bloqué, comment contourner","La science du partage.",[82,83],["Date","2019-03-31T07:47:36.000Z"],["Date","2022-12-27T12:08:00.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\nL'adresse actuelle de sci-hub est : [sci-hub.se](https://sci-hub.se)\n\n## Résumé de la situation\n\nN’étant pas moi-même directement chercheur, je vous laisse regarder [cette vidéo](https://youtu.be/rcgxY__YXEc) explicative extrêmement bien faite sur le sujet de la publication scientifique.\n\n> “ Mais c’est scandaleux ! ”​\n\nJ’ai constaté que le blocage était actif chez SFR. Je n’ai pas encore pu vérifier pour les autres fournisseurs mais j’imagine qu’ils se sont tous conformés à la décision de justice.\nLe blocage mis en place est assez basique. Il s’agit d’un blocage “ DNS ”.\n\nUn DNS est un serveur qui sert à faire le lien entre un nom de domaine : **sci-hub.tw** et une adresse IP : **186.2.163.90**.\n\nC’est en quelque sorte l’annuaire d’internet. Sans l’adresse, impossible de contacter le domaine. Ce que les FAI ont certainement fait : bloquer les requêtes au nom de domaine [sci-hub.se.](http://sci-hub.se/) Ainsi, aucune adresse IP n’est renvoyée et le site n’est pas accessible.\n\n## Comment contourner ce blocage ?\n\n- Soit en utilisant un VPN\n- Soit en modifiant les serveurs DNS de vos ordinateurs/box internet\n\nJe recommande la deuxième solution car elle permet de se prémunir contre de futurs blocages/filtrages/censures de la part de votre FAI et ne nécessite pas de contrepartie financière.\nJe vais me focaliser sur le changement depuis un ordinateur car il sera effectif où que vous soyez.\n\n### Sur MacOs\n\nOuvrez :\n\n1. Préférences système\n1. Réseau\n1. Ethernet et/ou Wi-fi\n1. Avancé\n1. DNS\n1. Serveurs DNS\n\nDe là, vous pouvez ajouter des serveurs DNS en cliquant sur l'icône +. Cliquez sur ok et appliquez les nouveaux paramètres. Vous devrez peut-être redémarrer votre ordinateur pour que les changements fonctionnent.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/ef5a4b8e82a046e6a466c73c2fd9e99e.jpg'\n\twidth='728'\n\theight='1060'\n\talt='MacOS réglages réseau et DNS'\n/>\n\n### Sur Windows (ici 10)\n\nOuvrez :\n\n1. Réglages\n1. Réseau et internet\n1. Modifier les options de l'adaptateur\n1. Clic droit sur les propriétés de votre interface réseau\n1. Selectionnez « protocole Internet version 4 » (et/ou 6)\n1. Propriétés\n1. Utiliser l’adresse de serveur DNS suivante\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-settings.jpg'\n\twidth='728'\n\theight='319'\n\talt='Réglages windows'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-network.jpg'\n\twidth='728'\n\theight='803'\n\talt='Windows réglages réseaux'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter.jpg'\n\twidth='728'\n\theight='327'\n\talt='Windows régalges connections réseaux'\n/>\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/sci-hub-adapter-settings.jpg'\n\twidth='728'\n\theight='434'\n\talt='Windows options adaptateur réseau'\n/>\n\n## Quels serveurs DNS utiliser ?\n\nIl y a de nombreux serveurs DNS accessibles. Les plus connus étant ceux de Google, Cloudflare et OpenDNS. Si vous tenez vraiment à utiliser ceux de Google, je vous laisse chercher leur adresse. Voici mes recommandations par ordre de préférence.\n\nPlusieurs fournisseurs :\n\n### [FDN DNS](https://www.fdn.fr/actions/dns/)\n\nMes favoris puisqu’il s’agit d’une [association française.](https://www.fdn.fr/)\n\n1. IPV4\n - 80.67.169.12\n - 80.67.169.40\n2. IPV6\n - 2001:910:800::12\n - 2001:910:800::40\n\n### [Quad9](https://www.quad9.net/fr)\n\nQuand9 est une fondation à but non lucratif proposant des serveurs DNS publics et gratuits. Leurs serveur classiques offrent un filtrage de domaines malveillants identifiés. Ils ne collectent pas de données et sont conforment au \u003Cabbr title=\"Règlement général sur la protection des données\">RGPD\u003C/abbr>.\n\n1. IPV4\n - 9.9.9.9\n - 149.112.112.112\n2. IPV6\n - 2620:fe::fe\n - 2620:fe::9\n\n## C'est tout.\n\nEn modifiant ces réglages, vous vous affranchissez de vos fournisseurs d’accès et de leurs règles de filtrage du contenu.\n\nPour l’instant, ces blocages sont presque symboliques car si Sci-hub venait à changer d’url, le blocage ne fonctionnerait plus. Mais la victoire des éditeurs au tribunal montre qu’ils n’ont pas dit leur dernier mot. Nous ne sommes donc pas à l’abri d’un futur blocage plus large et plus dur à contrer.\n\nSi vous voulez en apprendre plus sur le combat de ces gens qui se battent pour que la recherche ne soit pas une marchandise, je vous conseille [ce documentaire](https://youtu.be/y_CQATGOX2w) sur Aaron Shwartz. Ou plus simplement [cet article](https://arstechnica.com/tech-policy/2016/04/a-spiritual-successor-to-aaron-swartz-is-angering-publishers-all-over-again/) sur la fondatrice de Sci-hub.\n\nEn attendant, bonnes lectures à tou·te·s. On est avec vous !","src/content/articles/fr/sci-hub-blocage.mdx","6438fdc02b91ec59","the-day-I-jamd",{"id":124,"data":126,"body":131,"filePath":132,"digest":133,"deferredRender":72},{"title":92,"subtitle":127,"lang":16,"tags":128,"type":61,"slug":124,"createdAt":129,"updatedAt":130},"Des paris, des outils et du fun.",[95,96],["Date","2020-10-08T07:47:36.000Z"],["Date","2022-12-27T15:40:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## La solution de non facilité\n\nLorsque j’utilisais encore Wordpress pour mon site web personnel, j’ai voulu essayer le serveur web \u003Ca href=\"https://openlitespeed.org\" lang=\"en\" hreflang=\"en\" rel=\"noopener noreferer\">OpenLiteSpeed (en anglais)\u003C/a>. En tant que designer, j’ai toujours aimé avoir une interface graphique et j’avais entendu dire qu’OLS jouissait de bonnes performances en général et de cache en particulier.\n\n## Battez-vous!\n\nQuelques années plus tard, je découvrais l’univers Jamstack et son incroyable potentiel. N’étant pas du tout impulsif, j’ai choisi de refaire entièrement mon site web avec des outils comme \u003Ca href=\"https://www.11ty.dev/\" lang=\"en\" hreflang=\"en\" rel=\"noopener noreferer\">11ty (en anglais)\u003C/a> et \u003Ca href=\"https://strapi.io/\" hreflang=\"en\">Strapi (en anglais)\u003C/a>.\n\nJe me souviens que Strapi était encore en alpha/beta et que certains collègues me disaient que c’était un pari risqué, surtout que je découvrais à peine le monde de node.js.\n\n> Open source et français ? Je dis banco !\n\nJ’ai donc commencé à recréer mon site web à l’identique avec 11ty et Strapi. Même hébergement chez Digital Ocean, même serveur web, même contenu. J’avais fait pas mal d’optimisations de performances sur mon installation wordpress, j’étais donc impatient de comparer les résultats avec la nouvelle version statique.\n\nJ’en suis resté pantois ! Quasiment sans optimisation du côté statique, j’ai obtenu les résultats ci-dessous.\n\n### wordpress\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/wordpress_8ee6f54b98.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Score de performance de 53/100 sur Wordpress.'\n/>\n\nMalgré beaucoup d’efforts, je n’ai pas pu faire mieux. Je ne suis pas un expert en cache, je n’utilise pas de CDN et je me suis appuyé sur des plugins pour réaliser beaucoup de choses (php n’étant pas ma spécialité 😬).\n\n### 11ty + strapi\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/static_2c0d9f1eb8.jpeg'\n\twidth='728'\n\theight='412'\n\talt='Score de performance de 97/100 en Jamstack.'\n/>\n\nPresque **zéro** configuration spéciale (j’étais trop impatient de tester) et j’ai atteint un score impressionnant. Je sais que les scores lighthouse ne font pas tout mais **53 contre 97**… Ça me va !\n\n## Embrassez-vous 🥰\n\nCes deux approches ont leurs avantages et leurs inconvénients. En tant que freelance, mes clients préfèrent ou demandent souvent Wordpress en raison de sa réputation. Je présente toujours une alternative Jamstack lorsque c’est possible, mais cela reste effrayant la plupart du temps par rapport à Wordpress. Je pense cependant qu’il sera plus facile d’utiliser la Jamstack avec le temps.\n\n## Encore et encore…\n\nNous voici maintenant une quarantaine et quelques mois plus tard et ce site fonctionne avec… [Nuxt.js](https://fr.nuxtjs.org/). Je sais, je suis désolé, je n’ai pas pu résister à la dernière fonctionnalité [\u003Cspan lang=\"en\">nuxt content\u003C/span>](https://content.nuxtjs.org/fr) de Nuxt.\n\nDu coup j’ai tout refait… et laissez-moi vous dire : **wow**, quelle expérience !\nJ’adore développer avec Nuxt. L’utilisation de \u003Cspan lang=\"en\">nuxt content\u003C/span> m’a permis de me concentrer sur le design et, évidemment, sur le contenu.\nPlus de client Apollo ni de requête graphQL, seulement du \u003Cspan lang=\"en\">markdown\u003C/span> et quelques promesses.\n\nAttention, j’aime beaucoup travailler avec Strapi et son interface graphQL mais pour les besoins de ce site, \u003Cspan lang=\"en\">nuxt content\u003C/span> fait le \u003Cspan lang=\"en\">job\u003C/span> (extrêmement bien).\n\nJ’utilise toujours Strapi pour téléverser, stocker et gérer les images, vidéos, gifs, etc. C’est peut-être trop pour ce que j’en fait mais j’aime savoir que je peux toujours y revenir si j’ai envie ! De plus, j’ai passé pas mal de temps à le mettre en place avec \u003Cspan lang=\"en\">OpenLiteSpeed\u003C/span> et je suis encore trop attaché à cette réussite pour la laisser tomber.\n\n## Et en fait à la fin\n\nWordpress, Jamstack, fait main… Est-ce vraiment important ? Pour moi, l’expérience de développement a été bien plus agréable en travaillant avec 11ty, nuxt.js et strapi qu’avec Wordpress.\n\nDu point de vue de la performance et de l’accessibilité, il semble également que ce soit le choix le plus judicieux. Ce n’est peut-être pas le cas à chaque fois ! ¯\\\\\\_(ツ)\\_/¯\n\nJ’ai hâte d’apprendre \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\" >astro\u003C/a> et de tout recommencer à zéro !","src/content/articles/fr/the-day-I-jamd.mdx","57bd292bda8b6632","en-2022",{"id":134,"data":136,"body":142,"filePath":143,"digest":144,"rendered":145},{"title":137,"subtitle":138,"lang":68,"tags":139,"type":61,"slug":134,"createdAt":141},"Nico v2.0","2022 update of many things.",[140],"Freelance",["Date","2022-06-08T14:24:06.000Z"],"After two years of full-time freelancing, I took a step back from my activity. I especially questioned my positioning and the services I was offering.\n\n## Services\n\n### No more print\n\nEven though I am trained in branding, I rarely do it and do not practice it in my free time. The same goes for \"classic\" graphic design. Posters, flyers and other leaflets have disappeared from my quotes for a long time. It seems logical to me to no longer explicitly offer these services because I consider that I am no longer sufficiently competent or interested.\n\n### Internet all the way\n\nOn the other hand, I spend my time **doing web stuff.** A lot of development, some design and a fait amout of server configuration. It is therefore obvious for me to offer **more specific web offerings,** in which I have specialised.\n\nThus, **accessibility** and **eco-design** become integrated expertises in my practice. They are no longer options on a quote but **my core business.**\n\n## The website\n\nI have reworked my website, especially the homepage and its content, to better reflect these decisions.\n\nI have also made several behavioural changes:\n\n- external links no longer open in a new window. I read \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\">this article\u003C/a> about opening links in a new window and I haven't found a good reason to continue using this behaviour;\n- I have removed the open graph and twitter card meta tags as I fully agree with \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\" rel=\"noopener noreferer\" hreflang=\"fr\">this opinion (in french)\u003C/a> by [@HTeuMeuLeu](https://twitter.com/HTeuMeuLeu);\n- \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\" rel=\"noopener noreferer\" hreflang=\"fr\">same for the favicon\u003C/a>;\n- I only trigger animations if the user has not asked the system to reduce the amount motion [(reference)](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion).\n\nI am working on reducing the weight of my pages as much as possible, although I will certainly have to change tools (again) (hello [astro](https://astro.build/) 👀).\n\n## Le Nico\n\nOn a personal level, I have committed myself to a more responsible digital world by joining the \u003Ca href=\"https://www.good-it.org/\" rel=\"noopener noreferer\" hreflang=\"fr\">Good-it! (in french)\u003C/a> collective and by actively participating in its development.\n\nI have also started teaching in several schools. I mainly intervene on digital courses by teaching design and development. I take this opportunity to to make future generations aware of accessibility and eco-design.","src/content/articles/en/2022.md","7b98592763cb0929",{"html":146,"metadata":147},"\u003Cp>After two years of full-time freelancing, I took a step back from my activity. I especially questioned my positioning and the services I was offering.\u003C/p>\n\u003Ch2 id=\"services\">Services\u003C/h2>\n\u003Ch3 id=\"no-more-print\">No more print\u003C/h3>\n\u003Cp>Even though I am trained in branding, I rarely do it and do not practice it in my free time. The same goes for “classic” graphic design. Posters, flyers and other leaflets have disappeared from my quotes for a long time. It seems logical to me to no longer explicitly offer these services because I consider that I am no longer sufficiently competent or interested.\u003C/p>\n\u003Ch3 id=\"internet-all-the-way\">Internet all the way\u003C/h3>\n\u003Cp>On the other hand, I spend my time \u003Cstrong>doing web stuff.\u003C/strong> A lot of development, some design and a fait amout of server configuration. It is therefore obvious for me to offer \u003Cstrong>more specific web offerings,\u003C/strong> in which I have specialised.\u003C/p>\n\u003Cp>Thus, \u003Cstrong>accessibility\u003C/strong> and \u003Cstrong>eco-design\u003C/strong> become integrated expertises in my practice. They are no longer options on a quote but \u003Cstrong>my core business.\u003C/strong>\u003C/p>\n\u003Ch2 id=\"the-website\">The website\u003C/h2>\n\u003Cp>I have reworked my website, especially the homepage and its content, to better reflect these decisions.\u003C/p>\n\u003Cp>I have also made several behavioural changes:\u003C/p>\n\u003Cul>\n\u003Cli>external links no longer open in a new window. I read \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\">this article\u003C/a> about opening links in a new window and I haven’t found a good reason to continue using this behaviour;\u003C/li>\n\u003Cli>I have removed the open graph and twitter card meta tags as I fully agree with \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\" rel=\"noopener noreferer\" hreflang=\"fr\">this opinion (in french)\u003C/a> by \u003Ca href=\"https://twitter.com/HTeuMeuLeu\">@HTeuMeuLeu\u003C/a>;\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\" rel=\"noopener noreferer\" hreflang=\"fr\">same for the favicon\u003C/a>;\u003C/li>\n\u003Cli>I only trigger animations if the user has not asked the system to reduce the amount motion \u003Ca href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion\">(reference)\u003C/a>.\u003C/li>\n\u003C/ul>\n\u003Cp>I am working on reducing the weight of my pages as much as possible, although I will certainly have to change tools (again) (hello \u003Ca href=\"https://astro.build/\">astro\u003C/a> 👀).\u003C/p>\n\u003Ch2 id=\"le-nico\">Le Nico\u003C/h2>\n\u003Cp>On a personal level, I have committed myself to a more responsible digital world by joining the \u003Ca href=\"https://www.good-it.org/\" rel=\"noopener noreferer\" hreflang=\"fr\">Good-it! (in french)\u003C/a> collective and by actively participating in its development.\u003C/p>\n\u003Cp>I have also started teaching in several schools. I mainly intervene on digital courses by teaching design and development. I take this opportunity to to make future generations aware of accessibility and eco-design.\u003C/p>",{"headings":148,"imagePaths":166,"frontmatter":167},[149,153,157,160,163],{"depth":150,"slug":151,"text":152},2,"services","Services",{"depth":154,"slug":155,"text":156},3,"no-more-print","No more print",{"depth":154,"slug":158,"text":159},"internet-all-the-way","Internet all the way",{"depth":150,"slug":161,"text":162},"the-website","The website",{"depth":150,"slug":164,"text":165},"le-nico","Le Nico",[],{"title":137,"subtitle":138,"lang":68,"slug":134,"excerpt":168,"tags":169,"type":61,"createdAt":170},"Changes in my services, the website and myself.",[140],"2022-06-08T14:24:06.000Z","en-2023",{"id":171,"data":173,"body":179,"filePath":180,"digest":181,"rendered":182},{"title":174,"subtitle":175,"lang":68,"tags":176,"type":61,"slug":171,"createdAt":177,"updatedAt":178},"Nico v2.5","Update 2023.",[140],["Date","2023-02-03T17:41:00.000Z"],["Date","2023-05-17T17:41:00.000Z"],"This article will be updated when I have something new to share during the year 2023.\n\n## The website\n\n### Technologies\n\nOops... I (re)did it again.\n\nI have completely redeveloped my site with \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, as predicted by myself [in 2022 !](/en/articles/2022/#the-website)\n\nI will definitely do an article or two about Astro and the extensions I used. It was a great experience. Nuxt v2 is not really up to date anymore, so the performance was not good. Astro has completely fixed that.\n\nMy \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\">PageSpeed\u003C/a> performance score had dropped to 77/100. Thanks to Astro I'm back to a solid **95/100** without any particular optimization. With some small efforts, I've reached the good old 100/100.\n\nI then did a work of modernization of the codebase. Hello CSS variables and goodbye `media queries`. In no particular order, here are some of the improvements I made:\n\n- `flexbox` and `grid` to adapt the layout to different screen sizes;\n- CSS variables for colors, font sizes and margins;\n- some `container queries`, just to try;\n- logical CSS properties (`inline` and `block` instead of `width` and `height` for example).\n\nI took this opportunity to publish [the source code](https://git.nardu.in/nardu.in/website-astro) on my git repository.\n\n**Update #1:** I've added [an RSS feed](/en/rss.xml) as I find myself using it more and more on other websites.\n\n### Analytics\n\nI removed the tracking on my pages. I was using \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\">umami\u003C/a> hosted on my own server. No personal data was collected and I rarely consulted the reports.\n\nIt's nice to see that your site is consulted, but if there is no other purpose behind it, it's an extra resource loaded for nothing by visitors. Maybe I'll reactivate the tracking when I have a use for it (other than flattering my ego).\n\nPrevious visit reports can be found at [this link.](https://stat.nardu.in/share/nJSt1tfS/nardu.in)\n\n### Content\n\n- I've added a [work](/en/work/) page to list some of my projects.\n- I've also added [a page](/en/veille/) where I list some interesting things from around the web.\n\n## Additional projects\n\nI'm still teaching web development this year. In order to expand my course materials, I have set up a mini documentation site available at [3-w.fr](https://3-w.fr/) (an address I am very proud of).\n\nI have to update it more regularly but I hope that the platform will help students progress!\n\n**More to come soon!**","src/content/articles/en/2023.md","489c650e66cced63",{"html":183,"metadata":184},"\u003Cp>This article will be updated when I have something new to share during the year 2023.\u003C/p>\n\u003Ch2 id=\"the-website\">The website\u003C/h2>\n\u003Ch3 id=\"technologies\">Technologies\u003C/h3>\n\u003Cp>Oops… I (re)did it again.\u003C/p>\n\u003Cp>I have completely redeveloped my site with \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, as predicted by myself \u003Ca href=\"/en/articles/2022/#the-website\">in 2022 !\u003C/a>\u003C/p>\n\u003Cp>I will definitely do an article or two about Astro and the extensions I used. It was a great experience. Nuxt v2 is not really up to date anymore, so the performance was not good. Astro has completely fixed that.\u003C/p>\n\u003Cp>My \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\">PageSpeed\u003C/a> performance score had dropped to 77/100. Thanks to Astro I’m back to a solid \u003Cstrong>95/100\u003C/strong> without any particular optimization. With some small efforts, I’ve reached the good old 100/100.\u003C/p>\n\u003Cp>I then did a work of modernization of the codebase. Hello CSS variables and goodbye \u003Ccode>media queries\u003C/code>. In no particular order, here are some of the improvements I made:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>flexbox\u003C/code> and \u003Ccode>grid\u003C/code> to adapt the layout to different screen sizes;\u003C/li>\n\u003Cli>CSS variables for colors, font sizes and margins;\u003C/li>\n\u003Cli>some \u003Ccode>container queries\u003C/code>, just to try;\u003C/li>\n\u003Cli>logical CSS properties (\u003Ccode>inline\u003C/code> and \u003Ccode>block\u003C/code> instead of \u003Ccode>width\u003C/code> and \u003Ccode>height\u003C/code> for example).\u003C/li>\n\u003C/ul>\n\u003Cp>I took this opportunity to publish \u003Ca href=\"https://git.nardu.in/nardu.in/website-astro\">the source code\u003C/a> on my git repository.\u003C/p>\n\u003Cp>\u003Cstrong>Update #1:\u003C/strong> I’ve added \u003Ca href=\"/en/rss.xml\">an RSS feed\u003C/a> as I find myself using it more and more on other websites.\u003C/p>\n\u003Ch3 id=\"analytics\">Analytics\u003C/h3>\n\u003Cp>I removed the tracking on my pages. I was using \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\">umami\u003C/a> hosted on my own server. No personal data was collected and I rarely consulted the reports.\u003C/p>\n\u003Cp>It’s nice to see that your site is consulted, but if there is no other purpose behind it, it’s an extra resource loaded for nothing by visitors. Maybe I’ll reactivate the tracking when I have a use for it (other than flattering my ego).\u003C/p>\n\u003Cp>Previous visit reports can be found at \u003Ca href=\"https://stat.nardu.in/share/nJSt1tfS/nardu.in\">this link.\u003C/a>\u003C/p>\n\u003Ch3 id=\"content\">Content\u003C/h3>\n\u003Cul>\n\u003Cli>I’ve added a \u003Ca href=\"/en/work/\">work\u003C/a> page to list some of my projects.\u003C/li>\n\u003Cli>I’ve also added \u003Ca href=\"/en/veille/\">a page\u003C/a> where I list some interesting things from around the web.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"additional-projects\">Additional projects\u003C/h2>\n\u003Cp>I’m still teaching web development this year. In order to expand my course materials, I have set up a mini documentation site available at \u003Ca href=\"https://3-w.fr/\">3-w.fr\u003C/a> (an address I am very proud of).\u003C/p>\n\u003Cp>I have to update it more regularly but I hope that the platform will help students progress!\u003C/p>\n\u003Cp>\u003Cstrong>More to come soon!\u003C/strong>\u003C/p>",{"headings":185,"imagePaths":199,"frontmatter":200},[186,187,190,193,196],{"depth":150,"slug":161,"text":162},{"depth":154,"slug":188,"text":189},"technologies","Technologies",{"depth":154,"slug":191,"text":192},"analytics","Analytics",{"depth":154,"slug":194,"text":195},"content","Content",{"depth":150,"slug":197,"text":198},"additional-projects","Additional projects",[],{"title":174,"subtitle":175,"lang":68,"slug":171,"excerpt":201,"tags":202,"type":61,"createdAt":203,"updatedAt":204},"New changes.",[140],"2023-02-03T17:41:00.000Z","2023-05-17T17:41:00.000Z","en-faq",{"id":205,"data":207,"body":212,"filePath":213,"digest":214,"rendered":215},{"title":208,"subtitle":209,"lang":68,"tags":210,"type":61,"slug":205,"createdAt":211,"draft":72},"Accessibility and sobriety","Translation in progress, stay tuned ;)",[140],["Date","2022-06-22T15:34:45.000Z"],"[Go back to available articles](/en/articles)","src/content/articles/en/faq.md","82d516449896f6ca",{"html":216,"metadata":217},"\u003Cp>\u003Ca href=\"/en/articles\">Go back to available articles\u003C/a>\u003C/p>",{"headings":218,"imagePaths":219,"frontmatter":220},[],[],{"title":208,"subtitle":209,"lang":68,"slug":205,"draft":72,"excerpt":221,"tags":222,"type":61,"createdAt":223},"Why, how et and especially what.",[140],"2022-06-22T15:34:45.000Z","en-gratuiste",{"id":224,"data":226,"body":212,"filePath":230,"digest":231,"rendered":232},{"title":227,"subtitle":209,"lang":68,"tags":228,"type":61,"slug":224,"createdAt":229,"draft":72},"Gratuiste",[70,140],["Date","2017-05-27T07:47:36.000Z"],"src/content/articles/en/gratuiste.md","ebec75d19f0ff741",{"html":216,"metadata":233},{"headings":234,"imagePaths":235,"frontmatter":236},[],[],{"title":227,"subtitle":209,"lang":68,"slug":224,"draft":72,"excerpt":209,"tags":237,"type":61,"createdAt":238},[70,140],"2017-05-27T07:47:36.000Z","2022",{"id":239,"data":241,"body":245,"filePath":246,"digest":247,"rendered":248},{"title":137,"subtitle":242,"lang":16,"tags":243,"type":61,"slug":239,"createdAt":244},"Mise à jour 2022 de plein de trucs.",[140],["Date","2022-06-08T14:24:06.000Z"],"Après deux ans de freelance à temps plein, j’ai pris du recul sur mon activité. J’ai surtout questionné mon positionnement et les prestations que je proposais.\n\n## Les services\n\n### J’arrête le print\n\nMême si je suis formé à l’identité visuelle, je n’en fais que très rarement et ne pratique pas la discipline sur mon temps libre. Idem pour le graphisme « classique ». Affiches, flyers et autres prospectus ont disparu de mes devis depuis bien longtemps. Il me semble ainsi logique de ne plus proposer explicitement ces services car je considère ne plus être suffisamment compétent ni intéressé.\n\n### J’internet à fond\n\nÀ l’inverse, je passe mon temps à **faire du web.** Énormément de développement, un peu de design et pas mal de configuration serveur. Il est de fait évident pour moi de proposer **des offres web plus précises,** dans lesquelles je me suis spécialisé.\n\nAinsi, **l’accessibilité numérique** et **l’éco-conception** deviennent des expertises intégrées à ma pratique. Ce ne sont plus des options sur un devis mais bien **mon cœur de métier.**\n\n## Le site\n\nJ’ai retravaillé mon site, notamment la page d’accueil et son contenu, pour l’accorder avec ces décisions.\n\nJ’ai également fait plusieurs changements de comportements :\n\n- les liens externes ne s’ouvrent plus dans une nouvelle fenêtre. Je suis tombé sur \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\" hreflang=\"en\">cet article (en anglais)\u003C/a> traitant de l’ouverture des liens dans une nouvelle fenêtre et je n’ai pas trouvé de bonne raison de continuer à utiliser ce comportement ;\n- j’ai supprimé les balises open graph et twitter card car je suis entièrement d’accord avec [cette analyse](https://twitter.com/HTeuMeuLeu/status/1370310316496728065) de [@HTeuMeuLeu](https://twitter.com/HTeuMeuLeu) ;\n- [idem pour la favicon](https://twitter.com/HTeuMeuLeu/status/1370310312214339586) ;\n- je ne déclenche les animations que si l'utilisateur n'a pas demandé au système de minimiser la quantité d'animation ou de mouvement [(référence de l'option)](https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-reduced-motion).\n\nJe suis en train de travailler pour réduire au maximum le poids de mes pages, même si je vais certainement devoir (encore) changer d’outil (coucou \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\" >astro\u003C/a> 👀).\n\n## Le Nico\n\nD’un point de vue personnel, je me suis engagé pour un numérique plus responsable en rejoignant le collectif [Good-it!](https://www.good-it.org/) et en participant activement à son développement.\n\nJ’ai également commencé à donner des cours dans plusieurs écoles. J’interviens essentiellement sur des cursus numériques en enseignant le design et le développement. J’en profite ainsi pour sensibiliser, dès la formation, les futures générations à l’accessibilité et l’éco-conception.","src/content/articles/fr/2022.md","2589166172138721",{"html":249,"metadata":250},"\u003Cp>Après deux ans de freelance à temps plein, j’ai pris du recul sur mon activité. J’ai surtout questionné mon positionnement et les prestations que je proposais.\u003C/p>\n\u003Ch2 id=\"les-services\">Les services\u003C/h2>\n\u003Ch3 id=\"jarrête-le-print\">J’arrête le print\u003C/h3>\n\u003Cp>Même si je suis formé à l’identité visuelle, je n’en fais que très rarement et ne pratique pas la discipline sur mon temps libre. Idem pour le graphisme « classique ». Affiches, flyers et autres prospectus ont disparu de mes devis depuis bien longtemps. Il me semble ainsi logique de ne plus proposer explicitement ces services car je considère ne plus être suffisamment compétent ni intéressé.\u003C/p>\n\u003Ch3 id=\"jinternet-à-fond\">J’internet à fond\u003C/h3>\n\u003Cp>À l’inverse, je passe mon temps à \u003Cstrong>faire du web.\u003C/strong> Énormément de développement, un peu de design et pas mal de configuration serveur. Il est de fait évident pour moi de proposer \u003Cstrong>des offres web plus précises,\u003C/strong> dans lesquelles je me suis spécialisé.\u003C/p>\n\u003Cp>Ainsi, \u003Cstrong>l’accessibilité numérique\u003C/strong> et \u003Cstrong>l’éco-conception\u003C/strong> deviennent des expertises intégrées à ma pratique. Ce ne sont plus des options sur un devis mais bien \u003Cstrong>mon cœur de métier.\u003C/strong>\u003C/p>\n\u003Ch2 id=\"le-site\">Le site\u003C/h2>\n\u003Cp>J’ai retravaillé mon site, notamment la page d’accueil et son contenu, pour l’accorder avec ces décisions.\u003C/p>\n\u003Cp>J’ai également fait plusieurs changements de comportements :\u003C/p>\n\u003Cul>\n\u003Cli>les liens externes ne s’ouvrent plus dans une nouvelle fenêtre. Je suis tombé sur \u003Ca href=\"https://css-tricks.com/use-target_blank/\" rel=\"noopener noreferer\" hreflang=\"en\">cet article (en anglais)\u003C/a> traitant de l’ouverture des liens dans une nouvelle fenêtre et je n’ai pas trouvé de bonne raison de continuer à utiliser ce comportement ;\u003C/li>\n\u003Cli>j’ai supprimé les balises open graph et twitter card car je suis entièrement d’accord avec \u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310316496728065\">cette analyse\u003C/a> de \u003Ca href=\"https://twitter.com/HTeuMeuLeu\">@HTeuMeuLeu\u003C/a> ;\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/HTeuMeuLeu/status/1370310312214339586\">idem pour la favicon\u003C/a> ;\u003C/li>\n\u003Cli>je ne déclenche les animations que si l’utilisateur n’a pas demandé au système de minimiser la quantité d’animation ou de mouvement \u003Ca href=\"https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-reduced-motion\">(référence de l’option)\u003C/a>.\u003C/li>\n\u003C/ul>\n\u003Cp>Je suis en train de travailler pour réduire au maximum le poids de mes pages, même si je vais certainement devoir (encore) changer d’outil (coucou \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">astro\u003C/a> 👀).\u003C/p>\n\u003Ch2 id=\"le-nico\">Le Nico\u003C/h2>\n\u003Cp>D’un point de vue personnel, je me suis engagé pour un numérique plus responsable en rejoignant le collectif \u003Ca href=\"https://www.good-it.org/\">Good-it!\u003C/a> et en participant activement à son développement.\u003C/p>\n\u003Cp>J’ai également commencé à donner des cours dans plusieurs écoles. J’interviens essentiellement sur des cursus numériques en enseignant le design et le développement. J’en profite ainsi pour sensibiliser, dès la formation, les futures générations à l’accessibilité et l’éco-conception.\u003C/p>",{"headings":251,"imagePaths":265,"frontmatter":266},[252,255,258,261,264],{"depth":150,"slug":253,"text":254},"les-services","Les services",{"depth":154,"slug":256,"text":257},"jarrête-le-print","J’arrête le print",{"depth":154,"slug":259,"text":260},"jinternet-à-fond","J’internet à fond",{"depth":150,"slug":262,"text":263},"le-site","Le site",{"depth":150,"slug":164,"text":165},[],{"title":137,"subtitle":242,"lang":16,"slug":239,"excerpt":267,"tags":268,"type":61,"createdAt":170},"Évolution des services, du site et de moi-même.",[140],"2023",{"id":269,"data":271,"body":276,"filePath":277,"digest":278,"rendered":279},{"title":174,"subtitle":272,"lang":16,"tags":273,"type":61,"slug":269,"createdAt":274,"updatedAt":275},"Mise à jour 2023.",[140],["Date","2023-02-03T17:41:00.000Z"],["Date","2023-05-17T17:41:00.000Z"],"Cet article sera mis à jour lorsque j'aurai des nouveautés à partager au cours de l'année 2023.\n\n## Le site\n\n### Technologies\n\nOups… je l'ai encore (re)fait.\n\nJ'ai entièrement re-développé mon site avec \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, comme prédit par moi-même [en 2022 !](/articles/2022/#le-site)\n\nJe ferai certainement un ou deux articles/fragments sur Astro et les extensions que j'ai utilisées. En tout cas c'était super comme expérience. Nuxt v2 n'étant plus vraiment à jour, les performances n'étaient plus au rendez-vous. Astro a complètement corrigé ça.\n\nMon score de performance \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\" hreflang=\"en\" lang=\"en\">PageSpeed\u003C/a> était tombé à 77/100. Grâce à Astro je retrouve un solide **95/100** sans optimisation particulière. Avec quelques efforts sur le poids des ressources, je retrouve ce bon vieux 100/100.\n\nJ'ai ensuite fait un travail de modernisation du code. Bonjour variables CSS et au-revoir les `media queries`. En vrac, voici certaines améliorations que j'ai mises en place :\n\n- `flexbox` et `grid` pour adapter la mise en page aux différentes tailles d'écran ;\n- variables CSS pour les couleurs, les tailles de polices et les marges ;\n- quelques \u003Cspan lang=\"en\">`container queries`\u003C/span> pour essayer ;\n- propriétés logiques CSS (\u003Cspan lang=\"en\">`inline`\u003C/span> et \u003Cspan lang=\"en\">`block`\u003C/span> à la place de \u003Cspan lang=\"en\">`width`\u003C/span> et \u003Cspan lang=\"en\">`height`\u003C/span> par exemple).\n\nJ'en ai profité pour publier [le code source](https://git.nardu.in/nardu.in/website-astro) sur mon dépôt git.\n\n**Mise à jour #1 :** J'ai ajouté [un flux RSS](/rss.xml) car j'utilise de plus en plus le RSS sur d'autres sites web.\n\n### Suivi des visites\n\nJ’ai supprimé le suivi des visites. J’utilisais \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\" hreflang=\"en\">umami\u003C/a> hébergé sur mon propre serveur. Aucune donnée personnelle n'était collectée et je consultais rarement les rapports.\n\nC'est sympa de voir que son site est visité, mais s'il n'y a aucun autre but derrière, c'est une ressource supplémentaire chargée pour rien par les visiteurs. Peut-être que je réactiverai le suivi lorsque j'en aurai l'utilité (autre que flatter mon égo).\n\nLes rapports de visites précédents sont consultables sur [ce lien.](https://stat.nardu.in/share/nJSt1tfS/nardu.in)\n\n### Contenu\n\n- J'ai ajouté une page [références](/references/) pour lister certains de mes projets.\n- J'ai également ajouté [une page](/veille/) où je répertorie des choses intéressantes trouvées sur le web.\n\n## Projets annexes\n\nJe continue d'enseigner le développement web cette année. Afin d'étoffer mes supports de cours, j'ai mis en place un mini site de documentation disponible à l'adresse [3-w.fr](https://3-w.fr/) (adresse dont je suis très fier).\n\nIl faut que j'arrive à être plus régulier dans sa mise à jour mais j'ai bon espoir que la plateforme aide les élèves à progresser !\n\n**Plus de trucs bientôt!**","src/content/articles/fr/2023.md","d97f4a5af975333f",{"html":280,"metadata":281},"\u003Cp>Cet article sera mis à jour lorsque j’aurai des nouveautés à partager au cours de l’année 2023.\u003C/p>\n\u003Ch2 id=\"le-site\">Le site\u003C/h2>\n\u003Ch3 id=\"technologies\">Technologies\u003C/h3>\n\u003Cp>Oups… je l’ai encore (re)fait.\u003C/p>\n\u003Cp>J’ai entièrement re-développé mon site avec \u003Ca href=\"https://astro.build/\" rel=\"noopener noreferer\" hreflang=\"en\">Astro\u003C/a>, comme prédit par moi-même \u003Ca href=\"/articles/2022/#le-site\">en 2022 !\u003C/a>\u003C/p>\n\u003Cp>Je ferai certainement un ou deux articles/fragments sur Astro et les extensions que j’ai utilisées. En tout cas c’était super comme expérience. Nuxt v2 n’étant plus vraiment à jour, les performances n’étaient plus au rendez-vous. Astro a complètement corrigé ça.\u003C/p>\n\u003Cp>Mon score de performance \u003Ca href=\"https://pagespeed.web.dev/analysis/https-nardu-in/06as4el7ed?form_factor=mobile\" rel=\"noopener noreferer\" hreflang=\"en\" lang=\"en\">PageSpeed\u003C/a> était tombé à 77/100. Grâce à Astro je retrouve un solide \u003Cstrong>95/100\u003C/strong> sans optimisation particulière. Avec quelques efforts sur le poids des ressources, je retrouve ce bon vieux 100/100.\u003C/p>\n\u003Cp>J’ai ensuite fait un travail de modernisation du code. Bonjour variables CSS et au-revoir les \u003Ccode>media queries\u003C/code>. En vrac, voici certaines améliorations que j’ai mises en place :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>flexbox\u003C/code> et \u003Ccode>grid\u003C/code> pour adapter la mise en page aux différentes tailles d’écran ;\u003C/li>\n\u003Cli>variables CSS pour les couleurs, les tailles de polices et les marges ;\u003C/li>\n\u003Cli>quelques \u003Cspan lang=\"en\">\u003Ccode>container queries\u003C/code>\u003C/span> pour essayer ;\u003C/li>\n\u003Cli>propriétés logiques CSS (\u003Cspan lang=\"en\">\u003Ccode>inline\u003C/code>\u003C/span> et \u003Cspan lang=\"en\">\u003Ccode>block\u003C/code>\u003C/span> à la place de \u003Cspan lang=\"en\">\u003Ccode>width\u003C/code>\u003C/span> et \u003Cspan lang=\"en\">\u003Ccode>height\u003C/code>\u003C/span> par exemple).\u003C/li>\n\u003C/ul>\n\u003Cp>J’en ai profité pour publier \u003Ca href=\"https://git.nardu.in/nardu.in/website-astro\">le code source\u003C/a> sur mon dépôt git.\u003C/p>\n\u003Cp>\u003Cstrong>Mise à jour #1 :\u003C/strong> J’ai ajouté \u003Ca href=\"/rss.xml\">un flux RSS\u003C/a> car j’utilise de plus en plus le RSS sur d’autres sites web.\u003C/p>\n\u003Ch3 id=\"suivi-des-visites\">Suivi des visites\u003C/h3>\n\u003Cp>J’ai supprimé le suivi des visites. J’utilisais \u003Ca href=\"https://umami.is/\" rel=\"noopener noreferer\" hreflang=\"en\">umami\u003C/a> hébergé sur mon propre serveur. Aucune donnée personnelle n’était collectée et je consultais rarement les rapports.\u003C/p>\n\u003Cp>C’est sympa de voir que son site est visité, mais s’il n’y a aucun autre but derrière, c’est une ressource supplémentaire chargée pour rien par les visiteurs. Peut-être que je réactiverai le suivi lorsque j’en aurai l’utilité (autre que flatter mon égo).\u003C/p>\n\u003Cp>Les rapports de visites précédents sont consultables sur \u003Ca href=\"https://stat.nardu.in/share/nJSt1tfS/nardu.in\">ce lien.\u003C/a>\u003C/p>\n\u003Ch3 id=\"contenu\">Contenu\u003C/h3>\n\u003Cul>\n\u003Cli>J’ai ajouté une page \u003Ca href=\"/references/\">références\u003C/a> pour lister certains de mes projets.\u003C/li>\n\u003Cli>J’ai également ajouté \u003Ca href=\"/veille/\">une page\u003C/a> où je répertorie des choses intéressantes trouvées sur le web.\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"projets-annexes\">Projets annexes\u003C/h2>\n\u003Cp>Je continue d’enseigner le développement web cette année. Afin d’étoffer mes supports de cours, j’ai mis en place un mini site de documentation disponible à l’adresse \u003Ca href=\"https://3-w.fr/\">3-w.fr\u003C/a> (adresse dont je suis très fier).\u003C/p>\n\u003Cp>Il faut que j’arrive à être plus régulier dans sa mise à jour mais j’ai bon espoir que la plateforme aide les élèves à progresser !\u003C/p>\n\u003Cp>\u003Cstrong>Plus de trucs bientôt!\u003C/strong>\u003C/p>",{"headings":282,"imagePaths":294,"frontmatter":295},[283,284,285,288,291],{"depth":150,"slug":262,"text":263},{"depth":154,"slug":188,"text":189},{"depth":154,"slug":286,"text":287},"suivi-des-visites","Suivi des visites",{"depth":154,"slug":289,"text":290},"contenu","Contenu",{"depth":150,"slug":292,"text":293},"projets-annexes","Projets annexes",[],{"title":174,"subtitle":272,"lang":16,"slug":269,"excerpt":296,"tags":297,"type":61,"createdAt":203,"updatedAt":204},"Suite des évolutions.",[140],"after-effects-expressions",{"id":298,"data":300,"body":304,"filePath":305,"digest":306,"rendered":307},{"title":66,"subtitle":301,"lang":16,"tags":302,"type":61,"slug":298,"createdAt":303,"draft":72},"En cours de traduction, revenez bientôt ;)",[70],["Date","2019-04-24T09:00:00.000Z"],"[Retour aux articles](/articles)","src/content/articles/fr/after-effects-expressions.md","884d725859a7bab5",{"html":308,"metadata":309},"\u003Cp>\u003Ca href=\"/articles\">Retour aux articles\u003C/a>\u003C/p>",{"headings":310,"imagePaths":311,"frontmatter":312},[],[],{"title":66,"subtitle":301,"lang":16,"draft":72,"slug":298,"excerpt":301,"tags":313,"type":61,"createdAt":314},[70],"2019-04-24T09:00:00.000Z","faq",{"id":315,"data":317,"body":322,"filePath":323,"digest":324,"rendered":325},{"title":318,"subtitle":319,"lang":16,"tags":320,"type":61,"slug":315,"createdAt":321},"Accessibilité, sobriété et F.A.Q.","Explications sur ma vision et mon fonctionnement.",[140],["Date","2022-06-22T15:34:45.000Z"],"## l'Accessibilité\n\n### Quèsaco ?\n\nD'après [access42 :](https://access42.net)\n\n> L’accessibilité numérique est un droit fondamental. C’est la possibilité pour toutes et tous d’utiliser les outils informatiques, quelle que soit leur façon d’y accéder.\n\nAinsi, lorsque je \u003Cspan lang=\"en\">design\u003C/span> ou développe un site web, je fais le maximum pour que **n'importe quel visiteur** puisse l'utiliser. On pourrait croire que cela rajoute une charge de travail ou un délai allongé de réalisation mais **ce n'est pas le cas !**\n\nLorsqu'un site est pensé et conçu avec l'accessibilité en tête, il ne prend **pas plus de temps** qu'un projet qui ne le fait pas. En revanche, **corriger** un site existant qui n'a pas bénéficié de cette réflexion en amont **demande beaucoup plus d'efforts.**\n\n### Pourquoi c'est important ?\n\nAprès avoir été sensibilisé à l'accessibilité et aux [situations frustrantes voire bloquantes](https://www.france24.com/fr/info-en-continu/20220520-internet-parcours-d-obstacles-pour-les-aveugles) que rencontrent les personnes handicapées sur le web, j'ai décidé de tout faire pour me former et travailler en connaissance de cause. Il m'a semblé que proposer des sites utilisables par le plus grand nombre devait être la norme.\n\n## l'Éco-conception\n\n### Quèsaco ?\n\nD'après le collectif [\u003Cspan lang=\"en\">green it\u003C/span> :](https://www.greenit.fr)\n\n> L’éco-conception de service numérique consiste à améliorer l’efficience des applications dès leur conception pour réduire les impacts environnementaux et économiques associés tout en améliorant significativement l’expérience utilisateur.\n\nIl s'agit ici pour moi de créer des produits les plus sobres possibles. C'est-à-dire de développer ou d'utiliser une fonctionnalité uniquement si elle est indispensable.\n\nPar exemple, mettre en place **un formulaire de contact** sur un site web implique plusieurs choses :\n\n- développer un formulaire\n- envoyer les données au serveur\n- vérifier les données envoyées\n- envoyer les données par mail\n- confirmer l'envoi du mail (en fournissant une copie)\n- gérer les erreurs à chaque étape\n\nUn site statique seul ne peut pas faire tout ça. Il faut obligatoirement un serveur et un langage capable d'effectuer ces opérations (ou un prestataire qui s'en charge). C'est pourquoi je recommande une adresse email et un numéro de téléphone comme moyen de contact plutôt qu'un formulaire. Dans le cas d'un questionnaire ou autre situation particulière, un formulaire est tout à fait envisageable.\n\n### Pourquoi c'est important ?\n\nL'éco-conception fait beaucoup de bien à la qualité globale d'un site et à l'expérience des visiteurs. En effet, étant réalisé uniquement avec ce dont il a besoin, il aura tendance à être plus léger, mieux optimisé, plus rapide, etc.\n\n## F.A.Q.\n\n### Cette démarche est-elle opportuniste ?\n\n**Non.** Il est vrai que l'accessibilité et, surtout, l'éco-conception, commencent à être « tendance ». On pourrait donc croire que j'en profite pour faire du \u003Cspan lang=\"en\">business\u003C/span>. Je considère cependant que c'est ma responsabilité de créer des sites web accessibles et éco-conçus **par défaut.**\n\n### Un site accessible est-il plus cher ?\n\n**Oui et non.** Oui car si on demande un audit, il faudra payer la société qui le réalise. De mon côté, je ne fais pas payer l'accessibilité plus cher sur mes factures étant donné que je travaille ainsi par défaut.\nEn revanche, j'augmente mes tarifs suite à l'obtention de certifications relatives à mon activité.\n\n### Mon site sera-t-il 100 % accessible ?\n\n**Non,** je ne suis pas en mesure de garantir ou de certifier la conformité totale d'un site au [référentiel général d'amélioration de l'accessibilité.](https://www.numerique.gouv.fr/publications/rgaa-accessibilite/) Seul un audit exécuté par une entreprise apte à le réaliser peut certifier la conformité d'un site. Cependant, je peux vous accompagner avant et après l'audit afin d'anticiper puis de corriger les critères d'accessibilité requis. [Access42](https://access42.net/) et [Tanaguru](https://www.tanaguru.com/) font parties de ces entreprises spécialisées.\n\n### Pourquoi ne pas utiliser un outil automatique ?\n\nCar ces outils dits de “surcouche” (dont il ne faut pas prononcer le nom [sous peine de procès](https://www.lalutineduweb.fr/aide-frais-avocate-proces-contre-faciliti/)), ne sont pas des solutions micracles. Lisez [cet article](https://www.lalutineduweb.fr/surcouche-accessibilite-web-mensonges-boules-gommes/) d'une experte en accessibilité et/ou [ce test](https://blog.empreintedigitale.fr/2021/06/01/outils-de-surcouche-daccessibilite-que-valent-ils-vraiment/) de différents outils pour en savoir plus.\n\n### Un site éco-conçu et accessible peut-il être beau ?\n\n**Oui, évidemment.** Je vous laisse juger par vous-même avec [cette liste](https://lowww.directory/) de sites éco-conçus. En ce qui concerne l'accessibilité, elle n'impacte que très peu le \u003Cspan lang=\"en\">design\u003C/span> global d'un site. Même si plusieurs critères visuels existent (contrastes, taille du texte, etc.), elle se concentre essentiellement sur le fonctionnement et l'utilisation d'un produit.","src/content/articles/fr/faq.md","65e9e60bcd00806c",{"html":326,"metadata":327},"\u003Ch2 id=\"laccessibilité\">l’Accessibilité\u003C/h2>\n\u003Ch3 id=\"quèsaco\">Quèsaco ?\u003C/h3>\n\u003Cp>D’après \u003Ca href=\"https://access42.net\">access42 :\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>L’accessibilité numérique est un droit fondamental. C’est la possibilité pour toutes et tous d’utiliser les outils informatiques, quelle que soit leur façon d’y accéder.\u003C/p>\n\u003C/blockquote>\n\u003Cp>Ainsi, lorsque je \u003Cspan lang=\"en\">design\u003C/span> ou développe un site web, je fais le maximum pour que \u003Cstrong>n’importe quel visiteur\u003C/strong> puisse l’utiliser. On pourrait croire que cela rajoute une charge de travail ou un délai allongé de réalisation mais \u003Cstrong>ce n’est pas le cas !\u003C/strong>\u003C/p>\n\u003Cp>Lorsqu’un site est pensé et conçu avec l’accessibilité en tête, il ne prend \u003Cstrong>pas plus de temps\u003C/strong> qu’un projet qui ne le fait pas. En revanche, \u003Cstrong>corriger\u003C/strong> un site existant qui n’a pas bénéficié de cette réflexion en amont \u003Cstrong>demande beaucoup plus d’efforts.\u003C/strong>\u003C/p>\n\u003Ch3 id=\"pourquoi-cest-important\">Pourquoi c’est important ?\u003C/h3>\n\u003Cp>Après avoir été sensibilisé à l’accessibilité et aux \u003Ca href=\"https://www.france24.com/fr/info-en-continu/20220520-internet-parcours-d-obstacles-pour-les-aveugles\">situations frustrantes voire bloquantes\u003C/a> que rencontrent les personnes handicapées sur le web, j’ai décidé de tout faire pour me former et travailler en connaissance de cause. Il m’a semblé que proposer des sites utilisables par le plus grand nombre devait être la norme.\u003C/p>\n\u003Ch2 id=\"léco-conception\">l’Éco-conception\u003C/h2>\n\u003Ch3 id=\"quèsaco-1\">Quèsaco ?\u003C/h3>\n\u003Cp>D’après le collectif \u003Ca href=\"https://www.greenit.fr\">\u003Cspan lang=\"en\">green it\u003C/span> :\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>L’éco-conception de service numérique consiste à améliorer l’efficience des applications dès leur conception pour réduire les impacts environnementaux et économiques associés tout en améliorant significativement l’expérience utilisateur.\u003C/p>\n\u003C/blockquote>\n\u003Cp>Il s’agit ici pour moi de créer des produits les plus sobres possibles. C’est-à-dire de développer ou d’utiliser une fonctionnalité uniquement si elle est indispensable.\u003C/p>\n\u003Cp>Par exemple, mettre en place \u003Cstrong>un formulaire de contact\u003C/strong> sur un site web implique plusieurs choses :\u003C/p>\n\u003Cul>\n\u003Cli>développer un formulaire\u003C/li>\n\u003Cli>envoyer les données au serveur\u003C/li>\n\u003Cli>vérifier les données envoyées\u003C/li>\n\u003Cli>envoyer les données par mail\u003C/li>\n\u003Cli>confirmer l’envoi du mail (en fournissant une copie)\u003C/li>\n\u003Cli>gérer les erreurs à chaque étape\u003C/li>\n\u003C/ul>\n\u003Cp>Un site statique seul ne peut pas faire tout ça. Il faut obligatoirement un serveur et un langage capable d’effectuer ces opérations (ou un prestataire qui s’en charge). C’est pourquoi je recommande une adresse email et un numéro de téléphone comme moyen de contact plutôt qu’un formulaire. Dans le cas d’un questionnaire ou autre situation particulière, un formulaire est tout à fait envisageable.\u003C/p>\n\u003Ch3 id=\"pourquoi-cest-important-1\">Pourquoi c’est important ?\u003C/h3>\n\u003Cp>L’éco-conception fait beaucoup de bien à la qualité globale d’un site et à l’expérience des visiteurs. En effet, étant réalisé uniquement avec ce dont il a besoin, il aura tendance à être plus léger, mieux optimisé, plus rapide, etc.\u003C/p>\n\u003Ch2 id=\"faq\">F.A.Q.\u003C/h2>\n\u003Ch3 id=\"cette-démarche-est-elle-opportuniste\">Cette démarche est-elle opportuniste ?\u003C/h3>\n\u003Cp>\u003Cstrong>Non.\u003C/strong> Il est vrai que l’accessibilité et, surtout, l’éco-conception, commencent à être « tendance ». On pourrait donc croire que j’en profite pour faire du \u003Cspan lang=\"en\">business\u003C/span>. Je considère cependant que c’est ma responsabilité de créer des sites web accessibles et éco-conçus \u003Cstrong>par défaut.\u003C/strong>\u003C/p>\n\u003Ch3 id=\"un-site-accessible-est-il-plus-cher\">Un site accessible est-il plus cher ?\u003C/h3>\n\u003Cp>\u003Cstrong>Oui et non.\u003C/strong> Oui car si on demande un audit, il faudra payer la société qui le réalise. De mon côté, je ne fais pas payer l’accessibilité plus cher sur mes factures étant donné que je travaille ainsi par défaut.\nEn revanche, j’augmente mes tarifs suite à l’obtention de certifications relatives à mon activité.\u003C/p>\n\u003Ch3 id=\"mon-site-sera-t-il-100-accessible\">Mon site sera-t-il 100 % accessible ?\u003C/h3>\n\u003Cp>\u003Cstrong>Non,\u003C/strong> je ne suis pas en mesure de garantir ou de certifier la conformité totale d’un site au \u003Ca href=\"https://www.numerique.gouv.fr/publications/rgaa-accessibilite/\">référentiel général d’amélioration de l’accessibilité.\u003C/a> Seul un audit exécuté par une entreprise apte à le réaliser peut certifier la conformité d’un site. Cependant, je peux vous accompagner avant et après l’audit afin d’anticiper puis de corriger les critères d’accessibilité requis. \u003Ca href=\"https://access42.net/\">Access42\u003C/a> et \u003Ca href=\"https://www.tanaguru.com/\">Tanaguru\u003C/a> font parties de ces entreprises spécialisées.\u003C/p>\n\u003Ch3 id=\"pourquoi-ne-pas-utiliser-un-outil-automatique\">Pourquoi ne pas utiliser un outil automatique ?\u003C/h3>\n\u003Cp>Car ces outils dits de “surcouche” (dont il ne faut pas prononcer le nom \u003Ca href=\"https://www.lalutineduweb.fr/aide-frais-avocate-proces-contre-faciliti/\">sous peine de procès\u003C/a>), ne sont pas des solutions micracles. Lisez \u003Ca href=\"https://www.lalutineduweb.fr/surcouche-accessibilite-web-mensonges-boules-gommes/\">cet article\u003C/a> d’une experte en accessibilité et/ou \u003Ca href=\"https://blog.empreintedigitale.fr/2021/06/01/outils-de-surcouche-daccessibilite-que-valent-ils-vraiment/\">ce test\u003C/a> de différents outils pour en savoir plus.\u003C/p>\n\u003Ch3 id=\"un-site-éco-conçu-et-accessible-peut-il-être-beau\">Un site éco-conçu et accessible peut-il être beau ?\u003C/h3>\n\u003Cp>\u003Cstrong>Oui, évidemment.\u003C/strong> Je vous laisse juger par vous-même avec \u003Ca href=\"https://lowww.directory/\">cette liste\u003C/a> de sites éco-conçus. En ce qui concerne l’accessibilité, elle n’impacte que très peu le \u003Cspan lang=\"en\">design\u003C/span> global d’un site. Même si plusieurs critères visuels existent (contrastes, taille du texte, etc.), elle se concentre essentiellement sur le fonctionnement et l’utilisation d’un produit.\u003C/p>",{"headings":328,"imagePaths":362,"frontmatter":363},[329,332,335,338,341,343,345,347,350,353,356,359],{"depth":150,"slug":330,"text":331},"laccessibilité","l’Accessibilité",{"depth":154,"slug":333,"text":334},"quèsaco","Quèsaco ?",{"depth":154,"slug":336,"text":337},"pourquoi-cest-important","Pourquoi c’est important ?",{"depth":150,"slug":339,"text":340},"léco-conception","l’Éco-conception",{"depth":154,"slug":342,"text":334},"quèsaco-1",{"depth":154,"slug":344,"text":337},"pourquoi-cest-important-1",{"depth":150,"slug":315,"text":346},"F.A.Q.",{"depth":154,"slug":348,"text":349},"cette-démarche-est-elle-opportuniste","Cette démarche est-elle opportuniste ?",{"depth":154,"slug":351,"text":352},"un-site-accessible-est-il-plus-cher","Un site accessible est-il plus cher ?",{"depth":154,"slug":354,"text":355},"mon-site-sera-t-il-100-accessible","Mon site sera-t-il 100 % accessible ?",{"depth":154,"slug":357,"text":358},"pourquoi-ne-pas-utiliser-un-outil-automatique","Pourquoi ne pas utiliser un outil automatique ?",{"depth":154,"slug":360,"text":361},"un-site-éco-conçu-et-accessible-peut-il-être-beau","Un site éco-conçu et accessible peut-il être beau ?",[],{"title":318,"subtitle":319,"lang":16,"slug":315,"excerpt":364,"tags":365,"type":61,"createdAt":223},"Pourquoi, comment et surtout quèsaco.",[140],"gratuiste",{"id":366,"data":368,"body":374,"filePath":375,"digest":376,"rendered":377},{"title":227,"subtitle":369,"lang":16,"tags":370,"type":61,"slug":366,"createdAt":372,"updatedAt":373},"Ou le travail gratuit.",[371,140],"Graphisme",["Date","2017-05-27T07:47:36.000Z"],["Date","2022-12-27T15:36:06.000Z"],"## Gratuiste, qu’est-ce que c’est ?\n\nDans le monde francophone du graphisme, le terme gratuiste est un terme péjoratif employé pour dénoncer certaines conditions de travail. Les plus répandues sont les concours d’affiche/de logo, les clients qui demandent que vous commenciez à travailler sans vous payer et qui paieront si ça leur convient, les appels d’offre non défrayés, etc. \nDe plus en plus, la communauté s’élève contre ces pratiques et les [dénonce.](https://twitter.com/PayeTonAffiche)\n\n> “ On n’est pas des gratuistes ! ”\n\nComprendre : nous exerçons un métier à part entière qui requiert de nombreuses connaissances et beaucoup de travail, payez-nous. Rien d’extravagant en somme. Regardez [cette vidéo](https://youtu.be/essNmNOrQto) qui transpose ces pratiques à des métiers “ standards ” et [celle-ci](https://youtu.be/DsstOs-K7gk) qui explique en détails le processus actuel.\n\n## T’es débile du coup ?\n\nJ’aime à penser que non. Je n’aspire pas à devenir gratuiste dans ce sens là du terme. J’aimerais lui en donner un nouveau, plus positif. Dans les conditions précédentes, gratuiste est en effet une situation que personne (graphiste ou autre) n’aimerait expérimenter et encore moins promouvoir. À part peut-être des “ clients ” sans scrupules.\n\nÉtant encore assez nouveau sur le marché du travail, je n’ai pas la solution de faire des dons à des associations, qu’ils soient financiers ou autre. \nNéanmoins, j’ai envie d’aider à mon échelle et selon mes capacités.\n\n## Le concept\n\nJe compte proposer mes services et mes compétences gratuitement à des associations caritatives/ONG qui viennent en aide aux personnes dans le besoin ou aux animaux. \nCe type de prestation porte le nom de “ **pro bono publico** ” – “ **pour le bien public** ”.\n\nCette pratique existe essentiellement dans les milieux juridiques. Je pense cependant qu’elle n’est pas incompatible avec le métier de graphiste.\n\n> Graphiste pro bono, pourquoi pas ?\n\n## Quels genres de services ?\n\nEn toute logique, le type qui rend service à l’association, qui peut faire une différence. À mes yeux, essentiellement des sites internet. Je pense qu’un site web aura bien plus d’intérêt qu’un nouveau logo. Pourquoi pas des flyers/des petits visuels pour des pin’s/badges.\n\n### En résumé :\n\n- maquette de site web\n- intégration front-end (en dur ou via wordpress) du site\n- gestion de la mise en ligne du site\n- newsletter (design et/ou intégration)\n- flyers\n- autres petites demandes\n\nVous pouvez avoir un aperçu de mon travail [sur ce même site.](/) J’ai déjà eu l’occasion de travailler pour :\n\n- [Cygnal](/projets/cygnal)\n- [OpenMole](https://openmole.org/)\n- [Good-it](https://good-it.org)\n\n## Dans quelles conditions ?\n\n- l’association doit être active\n- elle doit porter des valeurs que je partage\n- elle doit pouvoir me montrer ses actions\n- elle ne doit pas avoir les moyens de se payer un graphiste\n\n## C’est un peu trop beau pour être vrai ton truc…\n\nIl faut garder à l’esprit que je compte travailler bénévolement pendant mon temps libre. Je ne cherche pas une relation client habituelle puisqu’il n’y aura pas de client à proprement parler. Cela me permettra d’éviter des délais intenables, des retours par milliers et toute obligation de finir le travail en cas de coup fourré.\nJe préfère être franc là-dessus même si je ne me fais pas trop de soucis sur les mœurs du monde associatif. Aussi, faudra-t-il être un peu patient si jamais j’ai déjà une demande en cours.\n\nSi vous êtes intéressés, [envoyez-moi un mail !](mailto:contac@nardu.in)\n\n## Qu’est-ce que t’y gagnes toi ?\n\nSimplement la satisfaction d’avoir aidé, à mon échelle, des personnes en difficulté. Je ne fais pas ça pour me faire de la pub ou pour étayer mon portfolio. Cela me permettra en revanche de travailler sur d’autres sujets et dans un cadre différent.","src/content/articles/fr/gratuiste.md","80c20493583a842c",{"html":378,"metadata":379},"\u003Ch2 id=\"gratuiste-quest-ce-que-cest\">Gratuiste, qu’est-ce que c’est ?\u003C/h2>\n\u003Cp>Dans le monde francophone du graphisme, le terme gratuiste est un terme péjoratif employé pour dénoncer certaines conditions de travail. Les plus répandues sont les concours d’affiche/de logo, les clients qui demandent que vous commenciez à travailler sans vous payer et qui paieront si ça leur convient, les appels d’offre non défrayés, etc.\u003Cbr>\nDe plus en plus, la communauté s’élève contre ces pratiques et les \u003Ca href=\"https://twitter.com/PayeTonAffiche\">dénonce.\u003C/a>\u003C/p>\n\u003Cblockquote>\n\u003Cp>“ On n’est pas des gratuistes ! ”\u003C/p>\n\u003C/blockquote>\n\u003Cp>Comprendre : nous exerçons un métier à part entière qui requiert de nombreuses connaissances et beaucoup de travail, payez-nous. Rien d’extravagant en somme. Regardez \u003Ca href=\"https://youtu.be/essNmNOrQto\">cette vidéo\u003C/a> qui transpose ces pratiques à des métiers “ standards ” et \u003Ca href=\"https://youtu.be/DsstOs-K7gk\">celle-ci\u003C/a> qui explique en détails le processus actuel.\u003C/p>\n\u003Ch2 id=\"tes-débile-du-coup\">T’es débile du coup ?\u003C/h2>\n\u003Cp>J’aime à penser que non. Je n’aspire pas à devenir gratuiste dans ce sens là du terme. J’aimerais lui en donner un nouveau, plus positif. Dans les conditions précédentes, gratuiste est en effet une situation que personne (graphiste ou autre) n’aimerait expérimenter et encore moins promouvoir. À part peut-être des “ clients ” sans scrupules.\u003C/p>\n\u003Cp>Étant encore assez nouveau sur le marché du travail, je n’ai pas la solution de faire des dons à des associations, qu’ils soient financiers ou autre.\u003Cbr>\nNéanmoins, j’ai envie d’aider à mon échelle et selon mes capacités.\u003C/p>\n\u003Ch2 id=\"le-concept\">Le concept\u003C/h2>\n\u003Cp>Je compte proposer mes services et mes compétences gratuitement à des associations caritatives/ONG qui viennent en aide aux personnes dans le besoin ou aux animaux.\u003Cbr>\nCe type de prestation porte le nom de “ \u003Cstrong>pro bono publico\u003C/strong> ” – “ \u003Cstrong>pour le bien public\u003C/strong> ”.\u003C/p>\n\u003Cp>Cette pratique existe essentiellement dans les milieux juridiques. Je pense cependant qu’elle n’est pas incompatible avec le métier de graphiste.\u003C/p>\n\u003Cblockquote>\n\u003Cp>Graphiste pro bono, pourquoi pas ?\u003C/p>\n\u003C/blockquote>\n\u003Ch2 id=\"quels-genres-de-services\">Quels genres de services ?\u003C/h2>\n\u003Cp>En toute logique, le type qui rend service à l’association, qui peut faire une différence. À mes yeux, essentiellement des sites internet. Je pense qu’un site web aura bien plus d’intérêt qu’un nouveau logo. Pourquoi pas des flyers/des petits visuels pour des pin’s/badges.\u003C/p>\n\u003Ch3 id=\"en-résumé\">En résumé :\u003C/h3>\n\u003Cul>\n\u003Cli>maquette de site web\u003C/li>\n\u003Cli>intégration front-end (en dur ou via wordpress) du site\u003C/li>\n\u003Cli>gestion de la mise en ligne du site\u003C/li>\n\u003Cli>newsletter (design et/ou intégration)\u003C/li>\n\u003Cli>flyers\u003C/li>\n\u003Cli>autres petites demandes\u003C/li>\n\u003C/ul>\n\u003Cp>Vous pouvez avoir un aperçu de mon travail \u003Ca href=\"/\">sur ce même site.\u003C/a> J’ai déjà eu l’occasion de travailler pour :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/projets/cygnal\">Cygnal\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"https://openmole.org/\">OpenMole\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"https://good-it.org\">Good-it\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"dans-quelles-conditions\">Dans quelles conditions ?\u003C/h2>\n\u003Cul>\n\u003Cli>l’association doit être active\u003C/li>\n\u003Cli>elle doit porter des valeurs que je partage\u003C/li>\n\u003Cli>elle doit pouvoir me montrer ses actions\u003C/li>\n\u003Cli>elle ne doit pas avoir les moyens de se payer un graphiste\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"cest-un-peu-trop-beau-pour-être-vrai-ton-truc\">C’est un peu trop beau pour être vrai ton truc…\u003C/h2>\n\u003Cp>Il faut garder à l’esprit que je compte travailler bénévolement pendant mon temps libre. Je ne cherche pas une relation client habituelle puisqu’il n’y aura pas de client à proprement parler. Cela me permettra d’éviter des délais intenables, des retours par milliers et toute obligation de finir le travail en cas de coup fourré.\nJe préfère être franc là-dessus même si je ne me fais pas trop de soucis sur les mœurs du monde associatif. Aussi, faudra-t-il être un peu patient si jamais j’ai déjà une demande en cours.\u003C/p>\n\u003Cp>Si vous êtes intéressés, \u003Ca href=\"mailto:contac@nardu.in\">envoyez-moi un mail !\u003C/a>\u003C/p>\n\u003Ch2 id=\"quest-ce-que-ty-gagnes-toi\">Qu’est-ce que t’y gagnes toi ?\u003C/h2>\n\u003Cp>Simplement la satisfaction d’avoir aidé, à mon échelle, des personnes en difficulté. Je ne fais pas ça pour me faire de la pub ou pour étayer mon portfolio. Cela me permettra en revanche de travailler sur d’autres sujets et dans un cadre différent.\u003C/p>",{"headings":380,"imagePaths":405,"frontmatter":406},[381,384,387,390,393,396,399,402],{"depth":150,"slug":382,"text":383},"gratuiste-quest-ce-que-cest","Gratuiste, qu’est-ce que c’est ?",{"depth":150,"slug":385,"text":386},"tes-débile-du-coup","T’es débile du coup ?",{"depth":150,"slug":388,"text":389},"le-concept","Le concept",{"depth":150,"slug":391,"text":392},"quels-genres-de-services","Quels genres de services ?",{"depth":154,"slug":394,"text":395},"en-résumé","En résumé :",{"depth":150,"slug":397,"text":398},"dans-quelles-conditions","Dans quelles conditions ?",{"depth":150,"slug":400,"text":401},"cest-un-peu-trop-beau-pour-être-vrai-ton-truc","C’est un peu trop beau pour être vrai ton truc…",{"depth":150,"slug":403,"text":404},"quest-ce-que-ty-gagnes-toi","Qu’est-ce que t’y gagnes toi ?",[],{"title":227,"subtitle":369,"lang":16,"slug":366,"excerpt":407,"tags":408,"type":61,"createdAt":238,"updatedAt":409},"J’ai cherché un moyen de mettre mes compétences au service d’autrui et je pense avoir trouvé: je vais travailler gratuitement pour des associations.",[371,140],"2022-12-27T15:36:06.000Z","video-compression",{"id":410,"data":412,"body":304,"filePath":417,"digest":418,"rendered":419},{"title":413,"subtitle":301,"lang":16,"tags":414,"type":61,"slug":410,"createdAt":415,"updatedAt":416,"draft":72},"Compression vidéo",[70],["Date","2021-05-05T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"src/content/articles/fr/video-compression.md","2296c41874b23b3d",{"html":308,"metadata":420},{"headings":421,"imagePaths":422,"frontmatter":423},[],[],{"title":413,"subtitle":301,"lang":16,"draft":72,"slug":410,"excerpt":424,"tags":425,"type":61,"createdAt":426,"updatedAt":170},"Pas encore traduit",[70],"2021-05-05T09:00:00.000Z","fragments",["Map",429,430,440,441,451,452,462,463,473,474,484,485,502,503,517,518,570,571,634,635,696,697,713,714,748,749,782,783,806,807,848,849],"buttons",{"id":429,"data":431,"body":437,"filePath":438,"digest":439,"deferredRender":72},{"title":432,"subtitle":433,"lang":16,"tags":434,"type":427,"slug":429,"createdAt":436,"code":72,"draft":72},"Effets de survol de boutons","Simples mais efficaces.",[435],"CSS",["Date","2020-10-08T09:00:00.000Z"],"## Styles généraux\n\nTous les boutons présents utilisent ces styles comme base en guise de « reset » :\n\n> N'oubliez pas de préfixer si besoin !\n\n```css\n.btn {\n\tmargin: 20px 0;\n\tpadding: 12px 26px;\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tfont-size: 20rem; /* 20px */\n\tline-height: 1.6;\n\ttext-align: center;\n\ttext-decoration: none;\n\tfont-weight: bold;\n\tcursor: pointer;\n\tborder: none;\n\tborder-radius: 2px;\n\t-moz-appearance: none;\n\t-webkit-appearance: none;\n\tcolor: white;\n\tbackground-color: hotpink;\n\ttransition: background-color 0.3s ease;\n}\n```\n\n## Ajout d'icône\n\n\u003Cbutton role='none' class='btn btn-icon'>\n\t\u003Cspan>Icône\u003C/span>\n\u003C/button>\n\n```css\n.btn-icon {\n\tbackground-color: hotpink;\n}\n.btn-icon::before {\n\tcontent: url('./assets/svg/arrow-right-white.svg');\n\tposition: absolute;\n\twidth: 20px;\n\ttop: 50%;\n\tright: 0;\n\ttransform: translate(40px, -50%);\n\ttransition: transform ease 0.3s;\n}\n.btn-icon:hover,\n.btn-icon:focus {\n\tbackground-color: darkorchid;\n}\n.btn-icon:hover::before,\n.btn-icon:focus::before {\n\ttransform: translate(-10px, -50%);\n}\n.btn-icon > span {\n\tdisplay: inline-block;\n\twidth: 100%;\n\theight: 100%;\n\ttransition: transform 0.3s ease;\n}\n.btn-icon:hover > span,\n.btn-icon:focus > span {\n\ttransform: translateX(-10px);\n}\n```\n\n## Double volet\n\n\u003Cbutton role='none' class='btn btn-rideau'>\n\t\u003Cspan>Volet\u003C/span>\n\u003C/button>\n\n```css\n.btn-rideau {\n\tborder: 2px solid #10113a;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n\ttransition: color 0.3s ease;\n}\n.btn-rideau:hover {\n\tcolor: white;\n}\n.btn-rideau::before {\n\tbackground: hotpink;\n}\n.btn-rideau::after {\n\tbackground: darkorchid;\n}\n.btn-rideau::before,\n.btn-rideau::after {\n\tcontent: '';\n\tposition: absolute;\n\theight: 100%;\n\twidth: 100%;\n\tbottom: 100%;\n\tleft: 0;\n\tz-index: -1;\n\ttransition: transform 0.3s;\n\ttransition-timing-function: ease;\n\ttransition-timing-function: cubic-bezier(0.75, 0, 0.125, 1);\n}\n.btn-rideau:hover::before,\n.btn-rideau:hover::after,\n.btn-rideau:focus::before,\n.btn-rideau:focus::after {\n\ttransform: translateY(100%);\n}\n.btn-rideau:hover::after,\n.btn-rideau:focus::after {\n\ttransition-delay: 0.175s;\n}\n```\n\n## Dégradé animé\n\n\u003Cbutton role='none' class='btn btn-gradient'>\n\t\u003Cspan>Dégradé\u003C/span>\n\u003C/button>\n\n```css\n.btn-gradient {\n\tbackground: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);\n\tbackground-size: 400% 400%;\n\tbackground-position: 0% 50%;\n\tanimation: GradientReverse 0.5s ease 1 normal forwards;\n}\n.btn-gradient:hover,\n.btn-gradient:focus {\n\tanimation: Gradient 0.5s ease 1 normal forwards;\n}\n@keyframes Gradient {\n\t0% {\n\t\tbackground-position: 0% 50%;\n\t}\n\t100% {\n\t\tbackground-position: 100% 100%;\n\t}\n}\n@keyframes GradientReverse {\n\t0% {\n\t\tbackground-position: 100% 100%;\n\t}\n\t100% {\n\t\tbackground-position: 0% 50%;\n\t}\n}\n```\n\n## Échelle non desctructrice\n\n\u003Cbutton role='none' class='btn btn-scale'>\n\t\u003Cspan>Échelle\u003C/span>\n\u003C/button>\n\n```css\n.btn-scale {\n\toverflow: visible;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n}\n.btn-scale::after {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n\twidth: 100%;\n\tborder: 2px solid #10113a;\n\tborder-radius: 2px;\n\ttransition: transform 0.3s ease;\n}\n.btn-scale:hover::after,\n.btn-scale:focus::after {\n\ttransform: scale(1.1);\n}\n```","src/content/fragments/fr/buttons.mdx","f5d7b03520f96b04","image-full",{"id":440,"data":442,"body":448,"filePath":449,"digest":450,"deferredRender":72},{"title":443,"subtitle":444,"lang":16,"tags":445,"type":427,"slug":440,"createdAt":446,"updatedAt":447},"Image pleine largeur","Casser le conteneur.",[435],["Date","2020-09-15T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Image inline\n\nOn est parfois obligé d'utiliser des images dans des balises `img` plutôt que dans un `background` en css. Comment faire alors pour que l'image sorte de son conteneur pour en faire une bannière ? Exemple pratique à partir de ce même site.\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_container_9e3939b3ae.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Contexte\n\nConsidérons le html suivant :\n\n```html\n\u003Csection class=\"container\">\n\t\u003Cdiv class=\"hero\">\n\t\t\u003Cimg class=\"hero__image\" src=\"hero.img\" />\n\t\u003C/div>\n\u003C/section>\n```\n\nEt le style suivant :\n\n```css\n.container {\n\tpadding: 0 14px;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tmax-width: 1040px;\n}\nimg {\n\tmax-width: 100%;\n\theight: auto;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_original_d49f0d11bf.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Déborder du conteneur\n\nAfin de faire prendre à l'image toute la largeur, on agit sur son conteneur :\n\n```css\n.hero {\n\tmargin-left: calc(50% - 50vw);\n\tposition: relative;\n\twidth: 100vw;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_full_2a902f9539.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\n### Faire une bannière\n\nOn peut alors réduire la hauteur du conteneur pour obtenir une bannière plutôt que l'image entière et faire correspondre la hauteur de l'image à la hauteur du conteneur :\n\n```css\n.hero {\n\theight: 200px;\n}\n.hero__image {\n\theight: 100%;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_height_81b4ce969a.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nIl faut ensuite forcer l'image à prendre toute la largeur du conteneur :\n\n```css\n.hero__image {\n\twidth: 100%;\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_deformed_479046d2cb.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nPas top…\n\n### J'ai cassé l'image…\n\n**ENFIN** le code magique pour redonner son ratio à l'image sans la déformer :\n\n```css\n.hero__image {\n\tobject-fit: cover;\n\tobject-position: center; /* à positionner comme on veut */\n}\n```\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/image_bleed_6c164e82b3.jpeg'\n\twidth='320'\n\theight='568'\n/>\n\nCette technique s'apparente à l'utilisation d'une image de background mais en dur 😁\n\n## TL;DR\n\nLe code complet :\n\n```css\n.hero {\n\tmargin-left: calc(50% - 50vw);\n\tposition: relative;\n\twidth: 100vw;\n\theight: 200px;\n}\n.hero__image {\n\twidth: 100%;\n\theight: 100%;\n\t-o-object-fit: cover;\n\tobject-fit: cover;\n\t-o-object-position: center;\n\tobject-position: center;\n}\n```","src/content/fragments/fr/image-full.mdx","91ebd97eef5cb8a4","super-cookies",{"id":451,"data":453,"body":459,"filePath":460,"digest":461,"deferredRender":72},{"title":454,"subtitle":455,"lang":16,"tags":456,"type":427,"slug":451,"createdAt":458},"Les meilleurs cookies","Des gâteaux sans consentement.",[457],"cuisine",["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Version végétalienne\n\n### Ingrédients\n\n- 250 grammes de farine\n- 70 grammes de sucre muscovado/vergeoise (non raffiné)\n- 20 grammes de cassonade\n- 1 pincée de sel\n- 1 cuillère à soupe de levure\n- 3/4 de l'aquafaba de 400g de pois chiche (l'eau des pois chiche)\n- 125 grammes d'huile de noix de coco\n- 2 cuillères à café de sirop d'érable\n- 1 plaquette de chocolat (noir) coupée en “ chunks ”\n\n### Méthode\n\n- faire fondre si besoin l'huile de noix de coco à feu doux\n- mélanger tous les ingrédients secs pendant ce temps\n- ajouter tous les ingrédients liquides (huile, aquafaba, sirop d'érable)\n- bien mélanger\n- ajouter le chocolat\n- bien mélanger (fig. 1)\n\n### Cuisson\n\nRéaliser des boules avec la mixture obtenue sur une plaque de cuisson.\nCuire 9 minutes à 210 degrés (celsius) - chaleur tournante (fig. 2).\n\n## Version non végétalienne\n\n### Ingrédients\n\n- 250 grammes de farine\n- 70 grammes de sucre muscovado/vergeoise (non raffiné)\n- 20 grammes de cassonade\n- 1 pincée de sel\n- 1 cuillère à soupe de levure\n- 1 œuf\n- 125 grammes de beurre fondu\n- 2 cuillères à café de miel\n- 1 plaquette de chocolat (noir/blanc/les deux) coupée en “ chunks ”\n\n### Méthode\n\n- faire fondre le beurre à feu doux\n- mélanger tous les ingrédients secs pendant ce temps\n- ajouter tous les ingrédients liquides (beurre fondu, œuf, miel)\n- bien mélanger\n- ajouter le chocolat\n- bien mélanger (fig. 1)\n\n### Cuisson\n\nRéaliser des boules avec la mixture obtenue sur une plaque de cuisson.\nCuire 9 minutes à 210 degrés (celsius) - chaleur tournante (fig. 2).\n\n## Notes\n\nLe chocolat peut-être remplacé par n'importe quoi comme des noix, des raisins secs, des légos… (mangez pas des légos soyez sérieux).\n\n## Figures\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-1.jpg'\n\twidth='753'\n\theight='1248'\n\talt='Tous les ingrédients mélangés forment une pâte marron.'\n/>\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-2.jpg'\n\twidth='753'\n\theight='1248'\n\talt='Les cookies cuits sont bombés et très moelleux.'\n/>","src/content/fragments/fr/super-cookies.mdx","f7a802e0b68cb04a","en-image-full",{"id":462,"data":464,"body":470,"filePath":471,"digest":472,"deferredRender":72},{"title":465,"subtitle":209,"lang":68,"tags":466,"type":467,"slug":462,"createdAt":468,"updatedAt":469,"draft":72},"Full width image",[435],"snippets",["Date","2020-09-15T09:00:00.000Z"],["Date","2022-06-08T14:24:06.000Z"],"[Go back to available snippets](/en/snippets)","src/content/fragments/en/image-full.mdx","2e3dddf593f6d72f","en-super-cookies",{"id":473,"data":475,"body":481,"filePath":482,"digest":483,"deferredRender":72},{"title":476,"subtitle":477,"lang":68,"tags":478,"type":467,"slug":473,"createdAt":480},"The best cookies","Consentless biscuits.",[479],"food",["Date","2022-06-08T14:24:06.000Z"],"import AstroImage from '../../../components/AstroImage.astro'\n\n## Vegetalian version\n\n### Ingredients\n\n- 250 grams of flour\n- 70 grams of muscovado/vergeoise sugar (unrefined)\n- 20 grams of brown sugar\n- 1 pinch of salt\n- 1 tablespoon of baking powder\n- 3/4 of aquafaba from 400g of chickpea (chickpea water)\n- 125 grams of coconut oil\n- 2 teaspoons of maple syrup\n- 1 chocolate bar (black) cut in “ chunks ”\n\n### Method\n\n- if necessary, melt the coconut oil over low heat\n- meanwhile, mix all the dry ingredients\n- add all liquid ingredients (oil, aquafaba, maple syrup)\n- mix well\n- add the chocolate\n- mix well (fig. 1)\n\n### Baking\n\nForm balls with the obtained mixture on a baking sheet.\nBake for 9 minutes at 210 degrees (Celsius) - fan setting (fig. 2).\n\n## Non vegetalian version\n\n### Ingredients\n\n- 250 grams of flour\n- 70 grams of muscovado/vergeoise sugar (unrefined)\n- 20 grams of brown sugar\n- 1 pinch of salt\n- 1 table spoon of baking powder\n- 1 egg\n- 125 grams of melted butter\n- 2 teaspoons of honey\n- 1 chocolate bar (black) cut in “ chunks ”\n\n### Method\n\n- melt butter over low heat\n- meanwhile, mix all dry ingredients\n- add all liquid ingredients (melted butter, egg, honey)\n- mix well\n- add the chocolate\n- mix well (fig. 1)\n\n### Baking\n\nForm balls with the obtained mixture on a baking sheet.\nBake for 9 minutes at 210 degrees (Celsius) - fan setting (fig. 2).\n\n## Notes\n\nChocolate can be replaced by anything like nuts, raisins, legos... (don't eat legos be reasonable).\n\n## Figures\n\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-1.jpg'\n\twidth='753'\n\theight='1248'\n\talt='All ingredients mixed together to form a brown paste.'\n/>\n\u003CAstroImage\n\tsrc='https://assets.nardu.in/cookies-fig-2.jpg'\n\twidth='753'\n\theight='1248'\n\talt='The cookies are round and soft after baking.'\n/>","src/content/fragments/en/super-cookies.mdx","b0c67adad40c177c","array-vs-array",{"id":484,"data":486,"body":492,"filePath":493,"digest":494,"rendered":495},{"title":487,"subtitle":488,"lang":16,"tags":489,"type":427,"slug":484,"createdAt":491,"draft":72},"Filtrer un array avec un autre array","En cours de traduction.",[490],"nuxt.js",["Date","2022-06-08T14:24:06.000Z"],"[Voir les fragments disponibles](/fragments)","src/content/fragments/fr/array-vs-array.md","7321d444177c3841",{"html":496,"metadata":497},"\u003Cp>\u003Ca href=\"/fragments\">Voir les fragments disponibles\u003C/a>\u003C/p>",{"headings":498,"imagePaths":499,"frontmatter":500},[],[],{"title":487,"subtitle":488,"lang":16,"draft":72,"slug":484,"createdAt":170,"excerpt":488,"tags":501,"type":427},[490],"toulouse-fun",{"id":502,"data":504,"body":492,"filePath":509,"digest":510,"rendered":511},{"title":505,"subtitle":488,"lang":16,"tags":506,"type":427,"slug":502,"createdAt":508,"draft":72},"Toulouse yourself",[507],"lifestyle",["Date","2022-06-22T15:34:45.000Z"],"src/content/fragments/fr/toulouse-fun.md","a0c25b438b34c05e",{"html":496,"metadata":512},{"headings":513,"imagePaths":514,"frontmatter":515},[],[],{"title":505,"subtitle":488,"lang":16,"draft":72,"slug":502,"createdAt":223,"excerpt":488,"tags":516,"type":427},[507],"en-toulouse-fun",{"id":517,"data":519,"body":523,"filePath":524,"digest":525,"rendered":526},{"title":505,"subtitle":520,"lang":68,"tags":521,"type":467,"slug":517,"createdAt":522},"Only the bestest",[507],["Date","2022-06-22T15:34:45.000Z"],"Here is my list of great places to go to when in Toulouse. There are of course a lot of other great places to go to, these are just my all time favourite. \n**It's always a good idea to make a reservation!**\n\n## Restaurants\n\n### French cuisine\n\n- [Solides](https://www.solides.fr/) — semi-gastronomic\n- [Les impulsifs](https://les-impulsifs-toulouse.eatbu.com/?lang=en) — semi-gastronomic\n- [Sixta](https://sixta-toulouse.fr/) — vege/vegan/gluten friendly\n- [Attila](https://attila.site-solocal.com/) — great **fish restaurant,** just above the Victor Hugo market\n- [Chez Emile](https://www.restaurant-emile.com/) - best [cassoulet](https://en.wikipedia.org/wiki/Cassoulet) in town (or so I'm told)\n\n### Korean\n\n- [Le ptit Louis](https://leptitlouis.fr/) — best of its kind, **only for lunch**\n- [Kongbap](https://kong-bap.com/) — street-food like\n\n### Japanese\n\n- [Iori](https://www.iori.fr/) — best ramen\n- [Japoyaki](https://www.qwant.com/maps/place/osm:node:2447719414@Japoyaki#map=16.50/43.6061725/1.4473402) — best sushi/sashimis\n\n## Drinks and snacks\n\n### Bars\n\n- [Le Bièrographe](https://www.qwant.com/maps/place/osm:node:1532531236@Le_Bi%C3%A8rographe#map=16.50/43.5986892/1.4428327) — all time favourite, **check out the typical toulouse basement**\n- [A Taula](https://www.facebook.com/ataulatolosa/) — all time favourite in summer, **amazing terrace,** also: great tapas\n- [The Hopscotch Pub](https://www.qwant.com/maps/place/osm:node:5592180378@The_Hopscotch#map=18.14/43.6006796/1.4431385) — good beers, good whiskies, good cocktials, good food\n\n### Cafés & tea rooms\n\n- [Bapz](https://www.bapz.fr/contact) — Excellent pastries / hot beverages\n- [Ô thé divin](https://fr-fr.facebook.com/%C3%94-Th%C3%A9-Divin-245018828864405/) — nice lunch options\n- [Les Rêveries d’Hercule](https://www.lesreveriesdhercule.com/) — Pottery Café, relaxing activity (ceramics need to be baked, there'll be a delay to get them back)\n- Bonus: the best bakeries in [Carmes](https://www.qwant.com/maps/place/osm:node:450165912@Boulangerie_des_Carmes#map=16.37/43.6022638/1.4439872) and [Saint-Aubin](https://www.qwant.com/maps/place/osm:node:456844404@La_P%C3%A9trie#map=18.84/43.6045088/1.4544694) — croissants, baguettes **traditions**, chocolatines and more\n\n### Wine shops\n\n- [l'envie du sud](https://www.qwant.com/maps/place/osm:node:3861692629@LEnvie#map=19.57/43.5978194/1.4443930) — amazing selection of wines and other spirits, excellent advice from the staff\n- [enoteca](https://www.qwant.com/maps/place/osm:node:3751077562@Enoteca_31#map=16.50/43.6045636/1.4531952) — smaller selection but more beers and great advice from the staff as well\n\n## Other delights\n\n### Ice creams\n\n- [Forno gusto](https://www.qwant.com/maps/place/osm:node:2462248749@Caf%C3%A9t%C3%A9ria_Gelateria#map=20.00/43.6027626/1.4421450) — only in the summer\n- [Moustache](https://www.qwant.com/maps/place/osm:node:2165543146@Glaces_Moustache#map=16.50/43.6036985/1.4350540) — lots of flavours\n\n### Cheese shop\n\n- [Xavier](https://xavier.fr/) — one of the **best of the country**, two shops in Toulouse, including one at Victor Hugo market\n- [Massembea](https://www.qwant.com/maps/place/osm:node:6164095797@Massembea#map=16.50/43.6043930/1.4539490) — a serious contender in Toulouse (weird hours)\n\n### Delicatessen\n\n- [Café Bacquié](http://cafe-bacquie.com/) — stock up on fine foods, coffees, teas and other great quality products","src/content/fragments/en/toulouse-fun.md","370491cc68079e8c",{"html":527,"metadata":528},"\u003Cp>Here is my list of great places to go to when in Toulouse. There are of course a lot of other great places to go to, these are just my all time favourite.\u003Cbr>\n\u003Cstrong>It’s always a good idea to make a reservation!\u003C/strong>\u003C/p>\n\u003Ch2 id=\"restaurants\">Restaurants\u003C/h2>\n\u003Ch3 id=\"french-cuisine\">French cuisine\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.solides.fr/\">Solides\u003C/a> — semi-gastronomic\u003C/li>\n\u003Cli>\u003Ca href=\"https://les-impulsifs-toulouse.eatbu.com/?lang=en\">Les impulsifs\u003C/a> — semi-gastronomic\u003C/li>\n\u003Cli>\u003Ca href=\"https://sixta-toulouse.fr/\">Sixta\u003C/a> — vege/vegan/gluten friendly\u003C/li>\n\u003Cli>\u003Ca href=\"https://attila.site-solocal.com/\">Attila\u003C/a> — great \u003Cstrong>fish restaurant,\u003C/strong> just above the Victor Hugo market\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.restaurant-emile.com/\">Chez Emile\u003C/a> - best \u003Ca href=\"https://en.wikipedia.org/wiki/Cassoulet\">cassoulet\u003C/a> in town (or so I’m told)\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"korean\">Korean\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://leptitlouis.fr/\">Le ptit Louis\u003C/a> — best of its kind, \u003Cstrong>only for lunch\u003C/strong>\u003C/li>\n\u003Cli>\u003Ca href=\"https://kong-bap.com/\">Kongbap\u003C/a> — street-food like\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"japanese\">Japanese\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.iori.fr/\">Iori\u003C/a> — best ramen\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2447719414@Japoyaki#map=16.50/43.6061725/1.4473402\">Japoyaki\u003C/a> — best sushi/sashimis\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"drinks-and-snacks\">Drinks and snacks\u003C/h2>\n\u003Ch3 id=\"bars\">Bars\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:1532531236@Le_Bi%C3%A8rographe#map=16.50/43.5986892/1.4428327\">Le Bièrographe\u003C/a> — all time favourite, \u003Cstrong>check out the typical toulouse basement\u003C/strong>\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.facebook.com/ataulatolosa/\">A Taula\u003C/a> — all time favourite in summer, \u003Cstrong>amazing terrace,\u003C/strong> also: great tapas\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:5592180378@The_Hopscotch#map=18.14/43.6006796/1.4431385\">The Hopscotch Pub\u003C/a> — good beers, good whiskies, good cocktials, good food\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"cafés--tea-rooms\">Cafés & tea rooms\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.bapz.fr/contact\">Bapz\u003C/a> — Excellent pastries / hot beverages\u003C/li>\n\u003Cli>\u003Ca href=\"https://fr-fr.facebook.com/%C3%94-Th%C3%A9-Divin-245018828864405/\">Ô thé divin\u003C/a> — nice lunch options\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lesreveriesdhercule.com/\">Les Rêveries d’Hercule\u003C/a> — Pottery Café, relaxing activity (ceramics need to be baked, there’ll be a delay to get them back)\u003C/li>\n\u003Cli>Bonus: the best bakeries in \u003Ca href=\"https://www.qwant.com/maps/place/osm:node:450165912@Boulangerie_des_Carmes#map=16.37/43.6022638/1.4439872\">Carmes\u003C/a> and \u003Ca href=\"https://www.qwant.com/maps/place/osm:node:456844404@La_P%C3%A9trie#map=18.84/43.6045088/1.4544694\">Saint-Aubin\u003C/a> — croissants, baguettes \u003Cstrong>traditions\u003C/strong>, chocolatines and more\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"wine-shops\">Wine shops\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:3861692629@LEnvie#map=19.57/43.5978194/1.4443930\">l’envie du sud\u003C/a> — amazing selection of wines and other spirits, excellent advice from the staff\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:3751077562@Enoteca_31#map=16.50/43.6045636/1.4531952\">enoteca\u003C/a> — smaller selection but more beers and great advice from the staff as well\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"other-delights\">Other delights\u003C/h2>\n\u003Ch3 id=\"ice-creams\">Ice creams\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2462248749@Caf%C3%A9t%C3%A9ria_Gelateria#map=20.00/43.6027626/1.4421450\">Forno gusto\u003C/a> — only in the summer\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:2165543146@Glaces_Moustache#map=16.50/43.6036985/1.4350540\">Moustache\u003C/a> — lots of flavours\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"cheese-shop\">Cheese shop\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://xavier.fr/\">Xavier\u003C/a> — one of the \u003Cstrong>best of the country\u003C/strong>, two shops in Toulouse, including one at Victor Hugo market\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.qwant.com/maps/place/osm:node:6164095797@Massembea#map=16.50/43.6043930/1.4539490\">Massembea\u003C/a> — a serious contender in Toulouse (weird hours)\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"delicatessen\">Delicatessen\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Ca href=\"http://cafe-bacquie.com/\">Café Bacquié\u003C/a> — stock up on fine foods, coffees, teas and other great quality products\u003C/li>\n\u003C/ul>",{"headings":529,"imagePaths":566,"frontmatter":567},[530,533,536,539,542,545,548,551,554,557,560,563],{"depth":150,"slug":531,"text":532},"restaurants","Restaurants",{"depth":154,"slug":534,"text":535},"french-cuisine","French cuisine",{"depth":154,"slug":537,"text":538},"korean","Korean",{"depth":154,"slug":540,"text":541},"japanese","Japanese",{"depth":150,"slug":543,"text":544},"drinks-and-snacks","Drinks and snacks",{"depth":154,"slug":546,"text":547},"bars","Bars",{"depth":154,"slug":549,"text":550},"cafés--tea-rooms","Cafés & tea rooms",{"depth":154,"slug":552,"text":553},"wine-shops","Wine shops",{"depth":150,"slug":555,"text":556},"other-delights","Other delights",{"depth":154,"slug":558,"text":559},"ice-creams","Ice creams",{"depth":154,"slug":561,"text":562},"cheese-shop","Cheese shop",{"depth":154,"slug":564,"text":565},"delicatessen","Delicatessen",[],{"title":505,"subtitle":520,"lang":68,"slug":517,"excerpt":568,"tags":569,"type":467,"createdAt":223},"Gonna have to trust me on this ¯\\_(ツ)_/¯",[507],"acme-sh-tls-cert",{"id":570,"data":572,"body":578,"filePath":579,"digest":580,"rendered":581},{"title":573,"subtitle":574,"lang":16,"tags":575,"type":427,"slug":570,"createdAt":577},"Certificates TLS robustes avec acme.sh","384-bit de https",[576],"sécurité",["Date","2022-06-08T14:24:06.000Z"],"## Attention\n\nJe ne suis pas du tout un expert en sécurité. J'aime juste les trucs nouveaux et stylés des internets. \nC'est pourquoi j'ai modifié mes certificats TLS par défaut pour utiliser la cryptographie à courbe elliptique (ECC) au lieu de RSA. J'ai maintenant un joli 100/100 sur [tls.imirhil.fr](https://tls.imirhil.fr/)\n\nVous pouvez en apprendre (beaucoup) plus [ici](https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa) et sur les liens cités (en anglais).\n\n## Prérequis\n\n### Installer acme.sh\n\nPour des raisons de simplicité et d'automatisation, j'utilise [acme.sh](https://github.com/acmesh-official/acme.sh)\n\n```bash\n# pour utiliser le mode standalone, il peut être nécessaire d'installer en sudo\ncurl https://get.acme.sh | sh -s email=mail@domain.tld\n```\n\n### Changer l'authorité par défaut\n\nPar défaut, acme.sh utilise ZeroSSL pour signer les certificats. Il faut changer ce paramètre pour Let's Encrypt car, d'après acme.sh, ils sont les seuls à proposer des certificats ECC.\n\n```bash\nacme.sh --set-default-ca --server letsencrypt\n```\n\n## Utiliser l'api DNS\n\nSi vous en avez la possibilité, la façon la plus simple de générer un certificat est via l'api de votre fournisseur DNS. acme.sh supporte [énormément](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) de fournisseurs DNS.\n\n### Definir la clé api\n\nSuivez la [documentation](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) pour votre fournisseur DNS, généralement:\n\n```bash\nexport PROVIDER_Key=\"YOUR_API_KEY\"\n```\n\n### Émettre le certificat\n\n```bash\nacme.sh --issue -d domain.tld --dns dns_provider --keylength ec-384\n```\n\n## Utiliser le mode standalone\n\nSi vous n'avez pas accès aux réglages DNS, le mode standalone permet de lancer un serveur web temporaire qui s'occupe de toutes les vérifications.\n\nLe port `80` doit être disponible.\n\n```bash\nacme.sh --issue --standalone -d domain.tld --keylength ec-384\n```\n\n## Exemples\n\n### Multi domaines standalone\n\n```bash\nacme.sh --issue --standalone -d domain.tld -d www.domain.tld -d subdomain.domain.tld --keylength ec-384\n```\n\n### Wildcard domaine DNS\n\n```bash\nacme.sh --issue -d domain.tld -d '*.domain.tld' --dns dns_provider --keylength ec-384\n```\n\n## Étapes supplémentaires\n\nLe certificat ECC seul ne suffira pas à obtenir un score élevé/parfait.\n\n### Version TLS\n\nLimiter la version TLS à 1.2 et 1.3 (voire uniquement 1.3 vu [la différence de compatibilité de 5%](https://caniuse.com/?search=tls%201.) avec 1.2).\n\n### HSTS\n\nUtiliser le header [strict transport security](https://scotthelme.co.uk/hsts-the-missing-link-in-tls/).\n\n```\nStrict-Transport-Security: max-age=31536000; includeSubDomains\n```\n\n### Suite cryptographique\n\nUtiliser une suite cryptographique récente et robuste. C'est ici que mes connaissances deviennent limitées… J'ai encore un peu de mal à comprendre quelles suites fonctionnent bien et pourquoi.\n\nJ'avais basé ma première suite sur [cette liste](https://tls.imirhil.fr/ciphers), en la comparant avec celle de la compatibilité (d'anciens ?) [navigateurs](https://tls.imirhil.fr/suite).\n\nJ'ai ensuite demandé à [Aeris](https://twitter.com/aeris22), le créateur de [tls.imirhil.fr](https://tls.imirhil.fr), ses conseils sur cette suite. Il m'a recommandé d'utiliser :\n\n```\nECDHE+AES:ECDHE+CHACHA20\n```\n\nAfin d'atteindre un score de 100/100, il est possible de restreindre un peu plus la suite comme ceci :\n\n```\nECDHE+AES256:ECDHE+CHACHA20\n```","src/content/fragments/fr/acme-sh-tls-cert.md","82e6d91747c28ea5",{"html":582,"metadata":583},"\u003Ch2 id=\"attention\">Attention\u003C/h2>\n\u003Cp>Je ne suis pas du tout un expert en sécurité. J’aime juste les trucs nouveaux et stylés des internets.\u003Cbr>\nC’est pourquoi j’ai modifié mes certificats TLS par défaut pour utiliser la cryptographie à courbe elliptique (ECC) au lieu de RSA. J’ai maintenant un joli 100/100 sur \u003Ca href=\"https://tls.imirhil.fr/\">tls.imirhil.fr\u003C/a>\u003C/p>\n\u003Cp>Vous pouvez en apprendre (beaucoup) plus \u003Ca href=\"https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa\">ici\u003C/a> et sur les liens cités (en anglais).\u003C/p>\n\u003Ch2 id=\"prérequis\">Prérequis\u003C/h2>\n\u003Ch3 id=\"installer-acmesh\">Installer acme.sh\u003C/h3>\n\u003Cp>Pour des raisons de simplicité et d’automatisation, j’utilise \u003Ca href=\"https://github.com/acmesh-official/acme.sh\">acme.sh\u003C/a>\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\"># pour utiliser le mode standalone, il peut être nécessaire d'installer en sudo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">curl\u003C/span>\u003Cspan style=\"color:#98C379\"> https://get.acme.sh\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> | \u003C/span>\u003Cspan style=\"color:#61AFEF\">sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> -s\u003C/span>\u003Cspan style=\"color:#98C379\"> email=mail@domain.tld\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"changer-lauthorité-par-défaut\">Changer l’authorité par défaut\u003C/h3>\n\u003Cp>Par défaut, acme.sh utilise ZeroSSL pour signer les certificats. Il faut changer ce paramètre pour Let’s Encrypt car, d’après acme.sh, ils sont les seuls à proposer des certificats ECC.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --set-default-ca\u003C/span>\u003Cspan style=\"color:#D19A66\"> --server\u003C/span>\u003Cspan style=\"color:#98C379\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"utiliser-lapi-dns\">Utiliser l’api DNS\u003C/h2>\n\u003Cp>Si vous en avez la possibilité, la façon la plus simple de générer un certificat est via l’api de votre fournisseur DNS. acme.sh supporte \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">énormément\u003C/a> de fournisseurs DNS.\u003C/p>\n\u003Ch3 id=\"definir-la-clé-api\">Definir la clé api\u003C/h3>\n\u003Cp>Suivez la \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">documentation\u003C/a> pour votre fournisseur DNS, généralement:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">export\u003C/span>\u003Cspan style=\"color:#E06C75\"> PROVIDER_Key\u003C/span>\u003Cspan style=\"color:#56B6C2\">=\u003C/span>\u003Cspan style=\"color:#98C379\">\"YOUR_API_KEY\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"émettre-le-certificat\">Émettre le certificat\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --dns\u003C/span>\u003Cspan style=\"color:#98C379\"> dns_provider\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"utiliser-le-mode-standalone\">Utiliser le mode standalone\u003C/h2>\n\u003Cp>Si vous n’avez pas accès aux réglages DNS, le mode standalone permet de lancer un serveur web temporaire qui s’occupe de toutes les vérifications.\u003C/p>\n\u003Cp>Le port \u003Ccode>80\u003C/code> doit être disponible.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> --standalone\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"exemples\">Exemples\u003C/h2>\n\u003Ch3 id=\"multi-domaines-standalone\">Multi domaines standalone\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> --standalone\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> www.domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> subdomain.domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"wildcard-domaine-dns\">Wildcard domaine DNS\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> '*.domain.tld'\u003C/span>\u003Cspan style=\"color:#D19A66\"> --dns\u003C/span>\u003Cspan style=\"color:#98C379\"> dns_provider\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"étapes-supplémentaires\">Étapes supplémentaires\u003C/h2>\n\u003Cp>Le certificat ECC seul ne suffira pas à obtenir un score élevé/parfait.\u003C/p>\n\u003Ch3 id=\"version-tls\">Version TLS\u003C/h3>\n\u003Cp>Limiter la version TLS à 1.2 et 1.3 (voire uniquement 1.3 vu \u003Ca href=\"https://caniuse.com/?search=tls%201.\">la différence de compatibilité de 5%\u003C/a> avec 1.2).\u003C/p>\n\u003Ch3 id=\"hsts\">HSTS\u003C/h3>\n\u003Cp>Utiliser le header \u003Ca href=\"https://scotthelme.co.uk/hsts-the-missing-link-in-tls/\">strict transport security\u003C/a>.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>Strict-Transport-Security: max-age=31536000; includeSubDomains\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"suite-cryptographique\">Suite cryptographique\u003C/h3>\n\u003Cp>Utiliser une suite cryptographique récente et robuste. C’est ici que mes connaissances deviennent limitées… J’ai encore un peu de mal à comprendre quelles suites fonctionnent bien et pourquoi.\u003C/p>\n\u003Cp>J’avais basé ma première suite sur \u003Ca href=\"https://tls.imirhil.fr/ciphers\">cette liste\u003C/a>, en la comparant avec celle de la compatibilité (d’anciens ?) \u003Ca href=\"https://tls.imirhil.fr/suite\">navigateurs\u003C/a>.\u003C/p>\n\u003Cp>J’ai ensuite demandé à \u003Ca href=\"https://twitter.com/aeris22\">Aeris\u003C/a>, le créateur de \u003Ca href=\"https://tls.imirhil.fr\">tls.imirhil.fr\u003C/a>, ses conseils sur cette suite. Il m’a recommandé d’utiliser :\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Afin d’atteindre un score de 100/100, il est possible de restreindre un peu plus la suite comme ceci :\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES256:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":584,"imagePaths":630,"frontmatter":631},[585,588,591,594,597,600,603,606,609,612,615,618,621,624,627],{"depth":150,"slug":586,"text":587},"attention","Attention",{"depth":150,"slug":589,"text":590},"prérequis","Prérequis",{"depth":154,"slug":592,"text":593},"installer-acmesh","Installer acme.sh",{"depth":154,"slug":595,"text":596},"changer-lauthorité-par-défaut","Changer l’authorité par défaut",{"depth":150,"slug":598,"text":599},"utiliser-lapi-dns","Utiliser l’api DNS",{"depth":154,"slug":601,"text":602},"definir-la-clé-api","Definir la clé api",{"depth":154,"slug":604,"text":605},"émettre-le-certificat","Émettre le certificat",{"depth":150,"slug":607,"text":608},"utiliser-le-mode-standalone","Utiliser le mode standalone",{"depth":150,"slug":610,"text":611},"exemples","Exemples",{"depth":154,"slug":613,"text":614},"multi-domaines-standalone","Multi domaines standalone",{"depth":154,"slug":616,"text":617},"wildcard-domaine-dns","Wildcard domaine DNS",{"depth":150,"slug":619,"text":620},"étapes-supplémentaires","Étapes supplémentaires",{"depth":154,"slug":622,"text":623},"version-tls","Version TLS",{"depth":154,"slug":625,"text":626},"hsts","HSTS",{"depth":154,"slug":628,"text":629},"suite-cryptographique","Suite cryptographique",[],{"title":573,"subtitle":574,"lang":16,"slug":570,"createdAt":170,"excerpt":632,"tags":633,"type":427},"La sécurité avec des courbes.",[576],"en-acme-sh-tls-cert",{"id":634,"data":636,"body":642,"filePath":643,"digest":644,"rendered":645},{"title":637,"subtitle":638,"lang":68,"tags":639,"type":467,"slug":634,"createdAt":641},"Strong TLS certificates with acme.sh","384-bit of https",[640],"security",["Date","2022-06-08T14:24:06.000Z"],"## Disclaimer\n\nI'm, in absolutely no regards, a security expert. I just fancy shiny new things of the interwebs. \nThis is why I've switched my default TLS certificates to use elliptic curve cryptography (ECC) instead of RSA. Now I have a sweet 100/100 on [tls.imirhil.fr](https://tls.imirhil.fr/)\n\nYou can learn (far) more by reading [this topic](https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa) and its linked resources.\n\n## Requirements\n\n### Installing acme.sh\n\nFor automation and ease of use purposes, I'm using [acme.sh](https://github.com/acmesh-official/acme.sh)\n\n```bash\n# for using standalone mode, you might have to install as sudo\ncurl https://get.acme.sh | sh -s email=mail@domain.tld\n```\n\n### Changing default authority\n\nBy default, acme.sh uses ZeroSSL to sign certificates. We need to change this to Let's Encrypt because according to acme.sh, they're the only ones offering ECC capabilities.\n\n```bash\nacme.sh --set-default-ca --server letsencrypt\n```\n\n## Using your DNS api\n\nIf available, the easiest way to issue a certificate is to use the DNS api of your DNS provider. acme.sh supports [a lot](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) of DNS providers.\n\n### Define an api key\n\nFollow the [docs](https://github.com/acmesh-official/acme.sh/wiki/dnsapi) for your DNS provider, usually:\n\n```bash\nexport PROVIDER_Key=\"YOUR_API_KEY\"\n```\n\n### Issue the cert\n\n```bash\nacme.sh --issue -d domain.tld --dns dns_provider --keylength ec-384\n```\n\n## Using standalone mode\n\nIf you don't have access to the DNS provider, we can use the standalone mode to spin up a temporary web server that will handle all the verifications.\n\nPort `80` must be free.\n\n```bash\nacme.sh --issue --standalone -d domain.tld --keylength ec-384\n```\n\n## Examples\n\n### Multi domains standalone\n\n```bash\nacme.sh --issue --standalone -d domain.tld -d www.domain.tld -d subdomain.domain.tld --keylength ec-384\n```\n\n### Wildcard domain DNS\n\n```bash\nacme.sh --issue -d domain.tld -d '*.domain.tld' --dns dns_provider --keylength ec-384\n```\n\n## Next steps\n\nThe ECC certificate alone will not grant you a high/perfect score.\n\n### TLS version\n\nLimit TLS version to 1.2 and 1.3 (or just 1.3 as there is only a [5% compatibility gap](https://caniuse.com/?search=tls%201.) with 1.2).\n\n### HSTS\n\nUse the [strict transport security](https://scotthelme.co.uk/hsts-the-missing-link-in-tls/) header.\n\n```\nStrict-Transport-Security: max-age=31536000; includeSubDomains\n```\n\n### Cipher suite\n\nUse recent and strong ciphers. This is where my knowledge hits its limit… I'm having a really hard time understanding what to use and why.\n\nI've based my initial choices of ciphers on [this list](https://tls.imirhil.fr/ciphers), cross referencing it with (older?) [browser compatibility](https://tls.imirhil.fr/suite).\n\nI then asked [Aeris](https://twitter.com/aeris22), the creator of [tls.imirhil.fr](https://tls.imirhil.fr), about it and he advised me to use the following:\n\n```\nECDHE+AES:ECDHE+CHACHA20\n```\n\nIn order to achieve a perfect score, we can be a little more restrictive with:\n\n```\nECDHE+AES256:ECDHE+CHACHA20\n```","src/content/fragments/en/acme-sh-tls-cert.md","41577e8aee884f85",{"html":646,"metadata":647},"\u003Ch2 id=\"disclaimer\">Disclaimer\u003C/h2>\n\u003Cp>I’m, in absolutely no regards, a security expert. I just fancy shiny new things of the interwebs.\u003Cbr>\nThis is why I’ve switched my default TLS certificates to use elliptic curve cryptography (ECC) instead of RSA. Now I have a sweet 100/100 on \u003Ca href=\"https://tls.imirhil.fr/\">tls.imirhil.fr\u003C/a>\u003C/p>\n\u003Cp>You can learn (far) more by reading \u003Ca href=\"https://crypto.stackexchange.com/questions/1190/why-is-elliptic-curve-cryptography-not-widely-used-compared-to-rsa\">this topic\u003C/a> and its linked resources.\u003C/p>\n\u003Ch2 id=\"requirements\">Requirements\u003C/h2>\n\u003Ch3 id=\"installing-acmesh\">Installing acme.sh\u003C/h3>\n\u003Cp>For automation and ease of use purposes, I’m using \u003Ca href=\"https://github.com/acmesh-official/acme.sh\">acme.sh\u003C/a>\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\"># for using standalone mode, you might have to install as sudo\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">curl\u003C/span>\u003Cspan style=\"color:#98C379\"> https://get.acme.sh\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> | \u003C/span>\u003Cspan style=\"color:#61AFEF\">sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> -s\u003C/span>\u003Cspan style=\"color:#98C379\"> email=mail@domain.tld\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"changing-default-authority\">Changing default authority\u003C/h3>\n\u003Cp>By default, acme.sh uses ZeroSSL to sign certificates. We need to change this to Let’s Encrypt because according to acme.sh, they’re the only ones offering ECC capabilities.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --set-default-ca\u003C/span>\u003Cspan style=\"color:#D19A66\"> --server\u003C/span>\u003Cspan style=\"color:#98C379\"> letsencrypt\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"using-your-dns-api\">Using your DNS api\u003C/h2>\n\u003Cp>If available, the easiest way to issue a certificate is to use the DNS api of your DNS provider. acme.sh supports \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">a lot\u003C/a> of DNS providers.\u003C/p>\n\u003Ch3 id=\"define-an-api-key\">Define an api key\u003C/h3>\n\u003Cp>Follow the \u003Ca href=\"https://github.com/acmesh-official/acme.sh/wiki/dnsapi\">docs\u003C/a> for your DNS provider, usually:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">export\u003C/span>\u003Cspan style=\"color:#E06C75\"> PROVIDER_Key\u003C/span>\u003Cspan style=\"color:#56B6C2\">=\u003C/span>\u003Cspan style=\"color:#98C379\">\"YOUR_API_KEY\"\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"issue-the-cert\">Issue the cert\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --dns\u003C/span>\u003Cspan style=\"color:#98C379\"> dns_provider\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"using-standalone-mode\">Using standalone mode\u003C/h2>\n\u003Cp>If you don’t have access to the DNS provider, we can use the standalone mode to spin up a temporary web server that will handle all the verifications.\u003C/p>\n\u003Cp>Port \u003Ccode>80\u003C/code> must be free.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> --standalone\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"examples\">Examples\u003C/h2>\n\u003Ch3 id=\"multi-domains-standalone\">Multi domains standalone\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> --standalone\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> www.domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> subdomain.domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"wildcard-domain-dns\">Wildcard domain DNS\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"bash\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\">acme.sh\u003C/span>\u003Cspan style=\"color:#D19A66\"> --issue\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> domain.tld\u003C/span>\u003Cspan style=\"color:#D19A66\"> -d\u003C/span>\u003Cspan style=\"color:#98C379\"> '*.domain.tld'\u003C/span>\u003Cspan style=\"color:#D19A66\"> --dns\u003C/span>\u003Cspan style=\"color:#98C379\"> dns_provider\u003C/span>\u003Cspan style=\"color:#D19A66\"> --keylength\u003C/span>\u003Cspan style=\"color:#98C379\"> ec-384\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"next-steps\">Next steps\u003C/h2>\n\u003Cp>The ECC certificate alone will not grant you a high/perfect score.\u003C/p>\n\u003Ch3 id=\"tls-version\">TLS version\u003C/h3>\n\u003Cp>Limit TLS version to 1.2 and 1.3 (or just 1.3 as there is only a \u003Ca href=\"https://caniuse.com/?search=tls%201.\">5% compatibility gap\u003C/a> with 1.2).\u003C/p>\n\u003Ch3 id=\"hsts\">HSTS\u003C/h3>\n\u003Cp>Use the \u003Ca href=\"https://scotthelme.co.uk/hsts-the-missing-link-in-tls/\">strict transport security\u003C/a> header.\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>Strict-Transport-Security: max-age=31536000; includeSubDomains\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"cipher-suite\">Cipher suite\u003C/h3>\n\u003Cp>Use recent and strong ciphers. This is where my knowledge hits its limit… I’m having a really hard time understanding what to use and why.\u003C/p>\n\u003Cp>I’ve based my initial choices of ciphers on \u003Ca href=\"https://tls.imirhil.fr/ciphers\">this list\u003C/a>, cross referencing it with (older?) \u003Ca href=\"https://tls.imirhil.fr/suite\">browser compatibility\u003C/a>.\u003C/p>\n\u003Cp>I then asked \u003Ca href=\"https://twitter.com/aeris22\">Aeris\u003C/a>, the creator of \u003Ca href=\"https://tls.imirhil.fr\">tls.imirhil.fr\u003C/a>, about it and he advised me to use the following:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>In order to achieve a perfect score, we can be a little more restrictive with:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"plaintext\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan>ECDHE+AES256:ECDHE+CHACHA20\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":648,"imagePaths":692,"frontmatter":693},[649,652,655,658,661,664,667,670,673,676,679,682,685,688,689],{"depth":150,"slug":650,"text":651},"disclaimer","Disclaimer",{"depth":150,"slug":653,"text":654},"requirements","Requirements",{"depth":154,"slug":656,"text":657},"installing-acmesh","Installing acme.sh",{"depth":154,"slug":659,"text":660},"changing-default-authority","Changing default authority",{"depth":150,"slug":662,"text":663},"using-your-dns-api","Using your DNS api",{"depth":154,"slug":665,"text":666},"define-an-api-key","Define an api key",{"depth":154,"slug":668,"text":669},"issue-the-cert","Issue the cert",{"depth":150,"slug":671,"text":672},"using-standalone-mode","Using standalone mode",{"depth":150,"slug":674,"text":675},"examples","Examples",{"depth":154,"slug":677,"text":678},"multi-domains-standalone","Multi domains standalone",{"depth":154,"slug":680,"text":681},"wildcard-domain-dns","Wildcard domain DNS",{"depth":150,"slug":683,"text":684},"next-steps","Next steps",{"depth":154,"slug":686,"text":687},"tls-version","TLS version",{"depth":154,"slug":625,"text":626},{"depth":154,"slug":690,"text":691},"cipher-suite","Cipher suite",[],{"title":637,"subtitle":638,"lang":68,"slug":634,"createdAt":170,"excerpt":694,"tags":695,"type":467},"Real cert have curves.",[640],"en-visited-links",{"id":696,"data":698,"body":470,"filePath":702,"digest":703,"rendered":704},{"title":699,"subtitle":209,"lang":68,"tags":700,"type":467,"slug":696,"createdAt":701,"draft":72},"Visited links and visuel aid",[18],["Date","2023-06-06T18:34:00.000Z"],"src/content/fragments/en/visited-links.md","cb7c11c12c25067e",{"html":705,"metadata":706},"\u003Cp>\u003Ca href=\"/en/snippets\">Go back to available snippets\u003C/a>\u003C/p>",{"headings":707,"imagePaths":708,"frontmatter":709},[],[],{"title":699,"subtitle":209,"lang":68,"draft":72,"slug":696,"excerpt":710,"tags":711,"type":467,"createdAt":712},"Petit hack CSS",[18],"2023-06-06T18:34:00.000Z","visited-links",{"id":713,"data":715,"body":721,"filePath":722,"digest":723,"rendered":724},{"title":716,"subtitle":717,"lang":16,"tags":718,"type":467,"slug":713,"createdAt":719,"draft":720},"Liens visités et indication visuelle","Comment différencier les liens déjà cliqués",[18],["Date","2023-06-06T18:34:00.000Z"],false,"## La théorie\n\nIl est possible sur le web d'appliquer un style différent aux liens déjà visités par un utilisateur. Par défaut, un lien non visité est bleu tandis qu'un lien visité est violet.\n\nGénéralement, ces styles sont modifiés, voire supprimés dans le cas des liens visités. L'information qu'un lien a déjà été visité ne semble pas indispensable à la navigation. C'est sûrement vrai, mais personnellement, je suis assez content d'avoir un rappel des pages que j'ai déjà consultées lorsque je navigue.\n\nUne information uniquement communiquée par la couleur est faillible, car certaines personnes ne distinguent pas les couleurs correctement. J'ai alors cherché un moyen d'ajouter un élément graphique supplémentaire aux liens visités/non visités. La solution démontrée ici n'est certainement pas idéale, elle se rapproche plus d'une expérience, à priori inoffensive pour l'internaute.\n\n## La spécification\n\nQuand je me suis intéressé à ce qu'il était possible de faire avec les liens déjà visités, j'ai découvert qu'extrêmement peu de propriétés \u003Cabbr>CSS\u003C/abbr> étaient autorisées. En effet, seulement des changements de couleurs sont disponibles. Ceci est dû au fait qu'il était possible de récupérer l'historique de navigation d'un utilisateur grâce aux styles des liens visités. Le sélecteur `:visited` a donc été restreint par les navigateurs afin de lutter contre cette brèche de la vie privée. [Plus d'informations dans cet article.](https://developer.mozilla.org/fr/docs/Web/CSS/Privacy_and_the_:visited_selector)\n\n## La pratique\n\nQue faire alors, en terme de style, quand on ne peut changer que des couleurs ?\n\nD'après MDN, les propriétés suivantes sont modifiables :\n\n- `color`\n- `background-color`\n- `border-color` (et les propriétés détaillées associées),\n- `column-rule-color`\n- `outline-color`\n- `text-decoration-color`\n- `text-emphasis-color`\n- Les composantes de couleur liées aux attributs SVG `fill` et `stroke`.\n\nChanger la couleur d'un lien visité ne sera pas compris par les internautes, à moins de garder une colorimétrie proche de celle par défaut (bleu et violet).\n\nEn revanche, il est possible de \" masquer \" un élément en modifiant sa couleur pour qu'elle corresponde à la couleur du fond de la page ou de l'élément parent. On pourrait ainsi imaginer masquer une `border` ou un `outline`.\n\nJ'ai personnellement choisi de faire différemment. J'ai décidé d'utiliser un pseudo-élément `::before` sur l'état non visité du lien puis de le masquer quand celui-ci devient visité.\n\n### Le code\n\n```css {1,4-6}\na {\n\tposition: relative;\n\ttext-decoration: none;\n}\na::before {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 50%;\n\tleft: 0;\n\tinline-size: 2px;\n\tblock-size: 2px;\n\tborder-radius: 4px;\n\ttransform: translate(-6px, 0);\n\tbackground-color: grey;\n}\na:visited::before {\n\tbackground-color: white;\n}\n```\n\nCes règles, utilisées dans la table des matières de mes articles, ajoutent une sorte de petite puce ou pastille au début du lien. Cette puce est ensuite passée en blanc sur fond blanc une fois que le lien est visité, ce qui la masque visuellement.\n\n### Accessibilité\n\nOn pourrait simplifier la règle et utiliser le caractère de puce directement dans la propriété `content` mais les lecteurs d'écran annonceront alors ce caractère lors de leur retranscription du lien. De plus, les lecteurs d'écrans annoncent déjà si un lien est visité avant de lire son intitulé.\n\n## Aller plus loin\n\nAfin de pousser l'expérience un peu plus loin, j'ai tenté d'utiliser des éléments plus explicites pour signifier l'état visité du lien. Bien qu'encore assez imparfait, il est possible de créer un indicateur plus complet de lien visité.\n\nL'idée est d'avoir un `::before` et un `::after`, chacun contenant une icône en base 64 blanche en tant qu'image de fond. Quand le lien est non visité, le `::before` contient un fond coloré qui fait apparaître l'icône. Quand le lien passe en visité, le fond du `::before` devient blanc et celui du `::after` devient coloré, ce qui masque la première icône et affiche la deuxième.\n\nIl est nécessaire de positionner les icônes côte à côte sinon elles se retrouveront l'une sur l'autre.\n\n[Voir la démo sur codepen.](https://codepen.io/narduin/pen/VwVwmrO)","src/content/fragments/fr/visited-links.md","8398f96220bc4ff2",{"html":725,"metadata":726},"\u003Ch2 id=\"la-théorie\">La théorie\u003C/h2>\n\u003Cp>Il est possible sur le web d’appliquer un style différent aux liens déjà visités par un utilisateur. Par défaut, un lien non visité est bleu tandis qu’un lien visité est violet.\u003C/p>\n\u003Cp>Généralement, ces styles sont modifiés, voire supprimés dans le cas des liens visités. L’information qu’un lien a déjà été visité ne semble pas indispensable à la navigation. C’est sûrement vrai, mais personnellement, je suis assez content d’avoir un rappel des pages que j’ai déjà consultées lorsque je navigue.\u003C/p>\n\u003Cp>Une information uniquement communiquée par la couleur est faillible, car certaines personnes ne distinguent pas les couleurs correctement. J’ai alors cherché un moyen d’ajouter un élément graphique supplémentaire aux liens visités/non visités. La solution démontrée ici n’est certainement pas idéale, elle se rapproche plus d’une expérience, à priori inoffensive pour l’internaute.\u003C/p>\n\u003Ch2 id=\"la-spécification\">La spécification\u003C/h2>\n\u003Cp>Quand je me suis intéressé à ce qu’il était possible de faire avec les liens déjà visités, j’ai découvert qu’extrêmement peu de propriétés \u003Cabbr>CSS\u003C/abbr> étaient autorisées. En effet, seulement des changements de couleurs sont disponibles. Ceci est dû au fait qu’il était possible de récupérer l’historique de navigation d’un utilisateur grâce aux styles des liens visités. Le sélecteur \u003Ccode>:visited\u003C/code> a donc été restreint par les navigateurs afin de lutter contre cette brèche de la vie privée. \u003Ca href=\"https://developer.mozilla.org/fr/docs/Web/CSS/Privacy_and_the_:visited_selector\">Plus d’informations dans cet article.\u003C/a>\u003C/p>\n\u003Ch2 id=\"la-pratique\">La pratique\u003C/h2>\n\u003Cp>Que faire alors, en terme de style, quand on ne peut changer que des couleurs ?\u003C/p>\n\u003Cp>D’après MDN, les propriétés suivantes sont modifiables :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ccode>color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>background-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>border-color\u003C/code> (et les propriétés détaillées associées),\u003C/li>\n\u003Cli>\u003Ccode>column-rule-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>outline-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>text-decoration-color\u003C/code>\u003C/li>\n\u003Cli>\u003Ccode>text-emphasis-color\u003C/code>\u003C/li>\n\u003Cli>Les composantes de couleur liées aux attributs SVG \u003Ccode>fill\u003C/code> et \u003Ccode>stroke\u003C/code>.\u003C/li>\n\u003C/ul>\n\u003Cp>Changer la couleur d’un lien visité ne sera pas compris par les internautes, à moins de garder une colorimétrie proche de celle par défaut (bleu et violet).\u003C/p>\n\u003Cp>En revanche, il est possible de ” masquer ” un élément en modifiant sa couleur pour qu’elle corresponde à la couleur du fond de la page ou de l’élément parent. On pourrait ainsi imaginer masquer une \u003Ccode>border\u003C/code> ou un \u003Ccode>outline\u003C/code>.\u003C/p>\n\u003Cp>J’ai personnellement choisi de faire différemment. J’ai décidé d’utiliser un pseudo-élément \u003Ccode>::before\u003C/code> sur l’état non visité du lien puis de le masquer quand celui-ci devient visité.\u003C/p>\n\u003Ch3 id=\"le-code\">Le code\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line highlighted\">\u003Cspan style=\"color:#E06C75\">a\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">relative\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttext-decoration: \u003C/span>\u003Cspan style=\"color:#D19A66\">none\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line highlighted\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line highlighted\">\u003Cspan style=\"color:#E06C75\">a\u003C/span>\u003Cspan style=\"color:#56B6C2\">::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line highlighted\">\u003Cspan style=\"color:#ABB2BF\">\tcontent: \u003C/span>\u003Cspan style=\"color:#98C379\">''\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">absolute\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttop: \u003C/span>\u003Cspan style=\"color:#D19A66\">50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tleft: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tinline-size: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tblock-size: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder-radius: \u003C/span>\u003Cspan style=\"color:#D19A66\">4\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">translate\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">-6\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: grey;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">a\u003C/span>\u003Cspan style=\"color:#56B6C2\">:visited::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: \u003C/span>\u003Cspan style=\"color:#D19A66\">white\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Ces règles, utilisées dans la table des matières de mes articles, ajoutent une sorte de petite puce ou pastille au début du lien. Cette puce est ensuite passée en blanc sur fond blanc une fois que le lien est visité, ce qui la masque visuellement.\u003C/p>\n\u003Ch3 id=\"accessibilité\">Accessibilité\u003C/h3>\n\u003Cp>On pourrait simplifier la règle et utiliser le caractère de puce directement dans la propriété \u003Ccode>content\u003C/code> mais les lecteurs d’écran annonceront alors ce caractère lors de leur retranscription du lien. De plus, les lecteurs d’écrans annoncent déjà si un lien est visité avant de lire son intitulé.\u003C/p>\n\u003Ch2 id=\"aller-plus-loin\">Aller plus loin\u003C/h2>\n\u003Cp>Afin de pousser l’expérience un peu plus loin, j’ai tenté d’utiliser des éléments plus explicites pour signifier l’état visité du lien. Bien qu’encore assez imparfait, il est possible de créer un indicateur plus complet de lien visité.\u003C/p>\n\u003Cp>L’idée est d’avoir un \u003Ccode>::before\u003C/code> et un \u003Ccode>::after\u003C/code>, chacun contenant une icône en base 64 blanche en tant qu’image de fond. Quand le lien est non visité, le \u003Ccode>::before\u003C/code> contient un fond coloré qui fait apparaître l’icône. Quand le lien passe en visité, le fond du \u003Ccode>::before\u003C/code> devient blanc et celui du \u003Ccode>::after\u003C/code> devient coloré, ce qui masque la première icône et affiche la deuxième.\u003C/p>\n\u003Cp>Il est nécessaire de positionner les icônes côte à côte sinon elles se retrouveront l’une sur l’autre.\u003C/p>\n\u003Cp>\u003Ca href=\"https://codepen.io/narduin/pen/VwVwmrO\">Voir la démo sur codepen.\u003C/a>\u003C/p>",{"headings":727,"imagePaths":745,"frontmatter":746},[728,731,734,737,740,742],{"depth":150,"slug":729,"text":730},"la-théorie","La théorie",{"depth":150,"slug":732,"text":733},"la-spécification","La spécification",{"depth":150,"slug":735,"text":736},"la-pratique","La pratique",{"depth":154,"slug":738,"text":739},"le-code","Le code",{"depth":154,"slug":32,"text":741},"Accessibilité",{"depth":150,"slug":743,"text":744},"aller-plus-loin","Aller plus loin",[],{"title":716,"subtitle":717,"lang":16,"draft":720,"slug":713,"excerpt":710,"tags":747,"type":467,"createdAt":712},[18],"en-buttons",{"id":748,"data":750,"body":755,"filePath":756,"digest":757,"rendered":758},{"title":751,"subtitle":752,"lang":68,"tags":753,"type":467,"slug":748,"createdAt":754,"code":72,"draft":72},"Buttons hover","Simple, but nice.",[435],["Date","2020-10-08T09:00:00.000Z"],"## General rules\n\nAll the buttons use these styles as a “reset”:\n\n> Don't forget to prefix if necessary!\n\n```css\n.btn {\n\tmargin: 20px 0;\n\tpadding: 12px 26px;\n\tposition: relative;\n\tdisplay: inline-block;\n\toverflow: hidden;\n\tfont-size: 20rem; /* 20px */\n\tline-height: 1.6;\n\ttext-align: center;\n\ttext-decoration: none;\n\tfont-weight: bold;\n\tcursor: pointer;\n\tborder: none;\n\tborder-radius: 2px;\n\t-moz-appearance: none;\n\t-webkit-appearance: none;\n\tcolor: white;\n\tbackground-color: hotpink;\n\ttransition: background-color 0.3s ease;\n}\n```\n\n## Add an icon\n\n\u003Cbutton role=\"none\" class=\"btn btn-icon\">\n \u003Cspan>Icon\u003C/span>\n\u003C/button>\n\n```css\n.btn-icon {\n\tbackground-color: hotpink;\n}\n.btn-icon::before {\n\tcontent: url('~assets/svg/arrow-right-white.svg');\n\tposition: absolute;\n\twidth: 20px;\n\ttop: 50%;\n\tright: 0;\n\ttransform: translate(40px, -50%);\n\ttransition: transform ease 0.3s;\n}\n.btn-icon:hover,\n.btn-icon:focus {\n\tbackground-color: darkorchid;\n}\n.btn-icon:hover::before,\n.btn-icon:focus::before {\n\ttransform: translate(-10px, -50%);\n}\n.btn-icon > span {\n\tdisplay: inline-block;\n\twidth: 100%;\n\theight: 100%;\n\ttransition: transform 0.3s ease;\n}\n.btn-icon:hover > span,\n.btn-icon:focus > span {\n\ttransform: translateX(-10px);\n}\n```\n\n## Double shutter down\n\n\u003Cbutton role=\"none\" class=\"btn btn-rideau\">\n \u003Cspan>Shutter\u003C/span>\n\u003C/button>\n\n```css\n.btn-rideau {\n\tborder: 2px solid #10113a;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n\ttransition: color 0.3s ease;\n}\n.btn-rideau:hover {\n\tcolor: white;\n}\n.btn-rideau::before {\n\tbackground: hotpink;\n}\n.btn-rideau::after {\n\tbackground: darkorchid;\n}\n.btn-rideau::before,\n.btn-rideau::after {\n\tcontent: '';\n\tposition: absolute;\n\theight: 100%;\n\twidth: 100%;\n\tbottom: 100%;\n\tleft: 0;\n\tz-index: -1;\n\ttransition: transform 0.3s;\n\ttransition-timing-function: ease;\n\ttransition-timing-function: cubic-bezier(0.75, 0, 0.125, 1);\n}\n.btn-rideau:hover::before,\n.btn-rideau:hover::after,\n.btn-rideau:focus::before,\n.btn-rideau:focus::after {\n\ttransform: translateY(100%);\n}\n.btn-rideau:hover::after,\n.btn-rideau:focus::after {\n\ttransition-delay: 0.175s;\n}\n```\n\n## Animated gradient\n\n\u003Cbutton role=\"none\" class=\"btn btn-gradient\">\n \u003Cspan>Gradient\u003C/span>\n\u003C/button>\n\n```css\n.btn-gradient {\n\tbackground: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);\n\tbackground-size: 400% 400%;\n\tbackground-position: 0% 50%;\n\tanimation: GradientReverse 0.5s ease 1 normal forwards;\n}\n.btn-gradient:hover,\n.btn-gradient:focus {\n\tanimation: Gradient 0.5s ease 1 normal forwards;\n}\n@keyframes Gradient {\n\t0% {\n\t\tbackground-position: 0% 50%;\n\t}\n\t100% {\n\t\tbackground-position: 100% 100%;\n\t}\n}\n@keyframes GradientReverse {\n\t0% {\n\t\tbackground-position: 100% 100%;\n\t}\n\t100% {\n\t\tbackground-position: 0% 50%;\n\t}\n}\n```\n\n## Non destructive scale\n\n\u003Cbutton role=\"none\" class=\"btn btn-scale\">\n \u003Cspan>Scale\u003C/span>\n\u003C/button>\n\n```css\n.btn-scale {\n\toverflow: visible;\n\tcolor: #10113a;\n\tbackground-color: transparent;\n}\n.btn-scale::after {\n\tcontent: '';\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbottom: 0;\n\twidth: 100%;\n\tborder: 2px solid #10113a;\n\tborder-radius: 2px;\n\ttransition: transform 0.3s ease;\n}\n.btn-scale:hover::after,\n.btn-scale:focus::after {\n\ttransform: scale(1.1);\n}\n```","src/content/fragments/en/buttons.md","ea9a5513a5a4cef4",{"html":759,"metadata":760},"\u003Ch2 id=\"general-rules\">General rules\u003C/h2>\n\u003Cp>All the buttons use these styles as a “reset”:\u003C/p>\n\u003Cblockquote>\n\u003Cp>Don’t forget to prefix if necessary!\u003C/p>\n\u003C/blockquote>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tmargin: \u003C/span>\u003Cspan style=\"color:#D19A66\">20\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#D19A66\"> 0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tpadding: \u003C/span>\u003Cspan style=\"color:#D19A66\">12\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#D19A66\"> 26\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">relative\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tdisplay: \u003C/span>\u003Cspan style=\"color:#D19A66\">inline-block\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\toverflow: \u003C/span>\u003Cspan style=\"color:#D19A66\">hidden\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tfont-size: \u003C/span>\u003Cspan style=\"color:#D19A66\">20\u003C/span>\u003Cspan style=\"color:#E06C75\">rem\u003C/span>\u003Cspan style=\"color:#ABB2BF\">; \u003C/span>\u003Cspan style=\"color:#7F848E;font-style:italic\">/* 20px */\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tline-height: \u003C/span>\u003Cspan style=\"color:#D19A66\">1.6\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttext-align: \u003C/span>\u003Cspan style=\"color:#D19A66\">center\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttext-decoration: \u003C/span>\u003Cspan style=\"color:#D19A66\">none\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tfont-weight: \u003C/span>\u003Cspan style=\"color:#D19A66\">bold\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcursor: \u003C/span>\u003Cspan style=\"color:#D19A66\">pointer\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder: \u003C/span>\u003Cspan style=\"color:#D19A66\">none\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder-radius: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#56B6C2\">\t-moz-appearance\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#D19A66\">none\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#56B6C2\">\t-webkit-appearance\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#D19A66\">none\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcolor: \u003C/span>\u003Cspan style=\"color:#D19A66\">white\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: hotpink;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: background-color \u003C/span>\u003Cspan style=\"color:#D19A66\">0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"add-an-icon\">Add an icon\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-icon\">\n \u003Cspan>Icon\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: hotpink;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcontent: \u003C/span>\u003Cspan style=\"color:#56B6C2\">url\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#98C379\">'~assets/svg/arrow-right-white.svg'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">absolute\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\twidth: \u003C/span>\u003Cspan style=\"color:#D19A66\">20\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttop: \u003C/span>\u003Cspan style=\"color:#D19A66\">50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tright: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">translate\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">40\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">-50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: transform \u003C/span>\u003Cspan style=\"color:#D19A66\">ease\u003C/span>\u003Cspan style=\"color:#D19A66\"> 0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: darkorchid;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">translate\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">-10\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">-50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> >\u003C/span>\u003Cspan style=\"color:#E06C75\"> span\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tdisplay: \u003C/span>\u003Cspan style=\"color:#D19A66\">inline-block\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\twidth: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\theight: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: transform \u003C/span>\u003Cspan style=\"color:#D19A66\">0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> >\u003C/span>\u003Cspan style=\"color:#E06C75\"> span\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-icon\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> >\u003C/span>\u003Cspan style=\"color:#E06C75\"> span\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">translateX\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">-10\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"double-shutter-down\">Double shutter down\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-rideau\">\n \u003Cspan>Shutter\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#D19A66\"> solid\u003C/span>\u003Cspan style=\"color:#D19A66\"> #10113a\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcolor: \u003C/span>\u003Cspan style=\"color:#D19A66\">#10113a\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: \u003C/span>\u003Cspan style=\"color:#D19A66\">transparent\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: \u003C/span>\u003Cspan style=\"color:#D19A66\">color\u003C/span>\u003Cspan style=\"color:#D19A66\"> 0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcolor: \u003C/span>\u003Cspan style=\"color:#D19A66\">white\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground: hotpink;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground: darkorchid;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcontent: \u003C/span>\u003Cspan style=\"color:#98C379\">''\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">absolute\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\theight: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\twidth: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbottom: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tleft: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tz-index: \u003C/span>\u003Cspan style=\"color:#D19A66\">-1\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: transform \u003C/span>\u003Cspan style=\"color:#D19A66\">0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition-timing-function: \u003C/span>\u003Cspan style=\"color:#D19A66\">ease\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition-timing-function: \u003C/span>\u003Cspan style=\"color:#56B6C2\">cubic-bezier\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">0.75\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">0.125\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">1\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus::before\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">translateY\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-rideau\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition-delay: \u003C/span>\u003Cspan style=\"color:#D19A66\">0.175\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"animated-gradient\">Animated gradient\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-gradient\">\n \u003Cspan>Gradient\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-gradient\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground: \u003C/span>\u003Cspan style=\"color:#56B6C2\">linear-gradient\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">-45\u003C/span>\u003Cspan style=\"color:#E06C75\">deg\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">#ee7752\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">#e73c7e\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">#23a6d5\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#D19A66\">#23d5ab\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-size: \u003C/span>\u003Cspan style=\"color:#D19A66\">400\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 400\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-position: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tanimation: GradientReverse \u003C/span>\u003Cspan style=\"color:#D19A66\">0.5\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#D19A66\"> 1\u003C/span>\u003Cspan style=\"color:#D19A66\"> normal\u003C/span>\u003Cspan style=\"color:#D19A66\"> forwards\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-gradient\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-gradient\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tanimation: Gradient \u003C/span>\u003Cspan style=\"color:#D19A66\">0.5\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#D19A66\"> 1\u003C/span>\u003Cspan style=\"color:#D19A66\"> normal\u003C/span>\u003Cspan style=\"color:#D19A66\"> forwards\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">@keyframes\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\"> Gradient\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t0% {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\tbackground-position: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t100% {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\tbackground-position: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">@keyframes\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\"> GradientReverse\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t0% {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\tbackground-position: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t100% {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\tbackground-position: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#D19A66\"> 50\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch2 id=\"non-destructive-scale\">Non destructive scale\u003C/h2>\n\u003Cbutton role=\"none\" class=\"btn btn-scale\">\n \u003Cspan>Scale\u003C/span>\n\u003C/button>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"css\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-scale\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\toverflow: \u003C/span>\u003Cspan style=\"color:#D19A66\">visible\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcolor: \u003C/span>\u003Cspan style=\"color:#D19A66\">#10113a\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbackground-color: \u003C/span>\u003Cspan style=\"color:#D19A66\">transparent\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-scale\u003C/span>\u003Cspan style=\"color:#56B6C2\">::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tcontent: \u003C/span>\u003Cspan style=\"color:#98C379\">''\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tposition: \u003C/span>\u003Cspan style=\"color:#D19A66\">absolute\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttop: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tleft: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tbottom: \u003C/span>\u003Cspan style=\"color:#D19A66\">0\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\twidth: \u003C/span>\u003Cspan style=\"color:#D19A66\">100\u003C/span>\u003Cspan style=\"color:#E06C75\">%\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#D19A66\"> solid\u003C/span>\u003Cspan style=\"color:#D19A66\"> #10113a\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\tborder-radius: \u003C/span>\u003Cspan style=\"color:#D19A66\">2\u003C/span>\u003Cspan style=\"color:#E06C75\">px\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransition: transform \u003C/span>\u003Cspan style=\"color:#D19A66\">0.3\u003C/span>\u003Cspan style=\"color:#E06C75\">s\u003C/span>\u003Cspan style=\"color:#D19A66\"> ease\u003C/span>\u003Cspan style=\"color:#ABB2BF\">;\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-scale\u003C/span>\u003Cspan style=\"color:#56B6C2\">:hover::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#D19A66\">.btn-scale\u003C/span>\u003Cspan style=\"color:#56B6C2\">:focus::after\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\ttransform: \u003C/span>\u003Cspan style=\"color:#56B6C2\">scale\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#D19A66\">1.1\u003C/span>\u003Cspan style=\"color:#ABB2BF\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":761,"imagePaths":777,"frontmatter":778},[762,765,768,771,774],{"depth":150,"slug":763,"text":764},"general-rules","General rules",{"depth":150,"slug":766,"text":767},"add-an-icon","Add an icon",{"depth":150,"slug":769,"text":770},"double-shutter-down","Double shutter down",{"depth":150,"slug":772,"text":773},"animated-gradient","Animated gradient",{"depth":150,"slug":775,"text":776},"non-destructive-scale","Non destructive scale",[],{"title":751,"subtitle":752,"lang":68,"slug":748,"draft":72,"excerpt":779,"tags":780,"code":72,"type":467,"createdAt":781},"Easy to grab and use hover effects.",[435],"2020-10-08T09:00:00.000Z","en-array-vs-array",{"id":782,"data":784,"body":789,"filePath":790,"digest":791,"rendered":792},{"title":785,"subtitle":786,"lang":68,"tags":787,"type":467,"slug":782,"createdAt":788},"Filter an array against another array","Array vs Array.",[490],["Date","2022-06-08T14:24:06.000Z"],"## Context\n\nFor a project, I had to come up with a way to filter an array of objects based on another array of strings.\n\nIn other words, I needed to include every object which `user` property was found in the second array.\n\nHere is an example:\n\n```javascript\nconst skills = [\n\t{\n\t\tname: 'Be awesome',\n\t\tuser: 'Jean'\n\t},\n\t{\n\t\tname: 'Great jokes',\n\t\tuser: 'Jacques'\n\t},\n\t{\n\t\tname: 'Heavy sleeper',\n\t\tuser: 'Jean'\n\t},\n\t{\n\t\tname: 'Heavy sleeper',\n\t\tuser: 'Beatriz'\n\t}\n]\n\nconst selectedUsers = ['Jean', 'Beatriz']\n```\n\nI thought it would be pretty easy but I guess I'm not familiar enough with javascript 😬\n\n## My solution\n\nAfter a bit of thinking, I came up with the following statement:\n\n> I need to filter the skills based on which users are selected. So I need to loop over the `selectedUsers` array and filter the skills according to their `user` value.\n\nAfter a bit more trials and errors, this is the code I ended up using in a `computed property`:\n\n```javascript\n// index.vue\nconst filteredSkills = selectedUsers.map((user) => {\n\treturn skills.filter((skill) => {\n\t\treturn skill.user === user\n\t})\n})\n```\n\nI used `map()` in order to loop on the second array and used its string value to only include the corresponding skills with `filter()`.\n\nI'm pretty sure there is a better way to do it though…","src/content/fragments/en/array-vs-array.md","c63ba57b1049cf4c",{"html":793,"metadata":794},"\u003Ch2 id=\"context\">Context\u003C/h2>\n\u003Cp>For a project, I had to come up with a way to filter an array of objects based on another array of strings.\u003C/p>\n\u003Cp>In other words, I needed to include every object which \u003Ccode>user\u003C/code> property was found in the second array.\u003C/p>\n\u003Cp>Here is an example:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">const\u003C/span>\u003Cspan style=\"color:#E5C07B\"> skills\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tname\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Be awesome'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tuser\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Jean'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tname\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Great jokes'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tuser\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Jacques'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tname\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Heavy sleeper'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tuser\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Jean'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tname\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Heavy sleeper'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tuser\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Beatriz'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">]\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">const\u003C/span>\u003Cspan style=\"color:#E5C07B\"> selectedUsers\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> [\u003C/span>\u003Cspan style=\"color:#98C379\">'Jean'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#98C379\">'Beatriz'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">]\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>I thought it would be pretty easy but I guess I’m not familiar enough with javascript 😬\u003C/p>\n\u003Ch2 id=\"my-solution\">My solution\u003C/h2>\n\u003Cp>After a bit of thinking, I came up with the following statement:\u003C/p>\n\u003Cblockquote>\n\u003Cp>I need to filter the skills based on which users are selected. So I need to loop over the \u003Ccode>selectedUsers\u003C/code> array and filter the skills according to their \u003Ccode>user\u003C/code> value.\u003C/p>\n\u003C/blockquote>\n\u003Cp>After a bit more trials and errors, this is the code I ended up using in a \u003Ccode>computed property\u003C/code>:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">const\u003C/span>\u003Cspan style=\"color:#E5C07B\"> filteredSkills\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#E5C07B\"> selectedUsers\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">map\u003C/span>\u003Cspan style=\"color:#ABB2BF\">((\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">user\u003C/span>\u003Cspan style=\"color:#ABB2BF\">) \u003C/span>\u003Cspan style=\"color:#C678DD\">=>\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">\treturn\u003C/span>\u003Cspan style=\"color:#E5C07B\"> skills\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">filter\u003C/span>\u003Cspan style=\"color:#ABB2BF\">((\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">skill\u003C/span>\u003Cspan style=\"color:#ABB2BF\">) \u003C/span>\u003Cspan style=\"color:#C678DD\">=>\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">\t\treturn\u003C/span>\u003Cspan style=\"color:#E5C07B\"> skill\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">user\u003C/span>\u003Cspan style=\"color:#56B6C2\"> ===\u003C/span>\u003Cspan style=\"color:#E06C75\"> user\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t})\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">})\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>I used \u003Ccode>map()\u003C/code> in order to loop on the second array and used its string value to only include the corresponding skills with \u003Ccode>filter()\u003C/code>.\u003C/p>\n\u003Cp>I’m pretty sure there is a better way to do it though…\u003C/p>",{"headings":795,"imagePaths":802,"frontmatter":803},[796,799],{"depth":150,"slug":797,"text":798},"context","Context",{"depth":150,"slug":800,"text":801},"my-solution","My solution",[],{"title":785,"subtitle":786,"lang":68,"slug":782,"createdAt":170,"excerpt":804,"tags":805,"type":467},"My peak javascript",[490],"nuxt-graphql-static",{"id":806,"data":808,"body":814,"filePath":815,"digest":816,"rendered":817},{"title":809,"subtitle":810,"lang":16,"tags":811,"type":427,"slug":806,"createdAt":812,"updatedAt":813},"Site statique et requêtes GraphQL avec Nuxt.js","Le client graphql est roi.",[490],["Date","2022-06-08T14:24:06.000Z"],["Date","2022-09-08T13:43:33.000Z"],"## Le problème\n\nJe me suis heurté à un villain bug en utilisant Nuxt en mode génération statique complète et le client [nuxt apollo](https://github.com/nuxt-community/apollo-module 'Dépôt github du module nuxt apollo (nouvel onglet)').\nAprès quelques recherches, voici [le bug constaté par quelqu'un d'autre](https://github.com/nuxt-community/apollo-module/issues/339 'Bug visible sur le dépôt github du module nuxt/apollo (nouvel onglet)') sur github.\n\nIl semblerait que le module en l'état ne gère pas correctement la génération statique avec `nuxt generate`.\n\nJe trouvais toujours des appels à mon API locale après la génération statique et la navigation depuis les `\u003Cnuxt-link>` ne fonctionnait pas.\n\n## La solution 🙌\n\nHeureusement, il existe un autre module Nuxt pour gérer les requêtes GraphQL !\n\n[Nuxt graphql request à la rescousse !](https://github.com/gomah/nuxt-graphql-request 'Dépôt github du module (nouvel onglet)')\n\n### La conf\n\n```javascript\n// nuxt.config.js\nbuildModules: [\n 'nuxt-graphql-request',\n],\ngraphql: {\n clients: {\n default: {\n endpoint: 'http://API_URL/graphql',\n options: {\n headers: {\n authorization: 'Bearer API_TOKEN',\n },\n },\n },\n },\n},\n```\n\n### La requête\n\nLa meilleure méthode à ce jour est d'utiliser `asyncData` dans les pages et `fetch` dans les composants. Utiliser `fetch` dans les pages ne fonctionne pas bien du tout avec `nuxt generate`.\n\nJ'installe également le paquet `graphql-tag` (uniquement en `devDependencies`) afin de pouvoir importer directement des fichiers `.gql`\n\nExemple de fichier :\n\n```graphql\n# homepage.gql\nquery {\n\thomepage {\n\t\ttitle\n\t\tsubtitle\n\t\thero {\n\t\t\tid\n\t\t\talt\n\t\t}\n\t}\n}\n```\n\n#### Dans une page\n\n```javascript\n// index.vue\n\u003Cscript>\nimport homepageQuery from '~/graphql/queries/singles/homepage'\n\nexport default {\n async asyncData({ $graphql }) {\n const data = await $graphql.default.request(homepageQuery)\n return { data }\n },\n}\n\u003C/script>\n```\n\n#### Dans un composant\n\nIl est plus prudent d'attendre que `fetch` ait reçu une réponse avant d'afficher quoi que ce soit. On peut utiliser `$fetchState` afin d'être tranquille ([documentation](https://fr.nuxtjs.org/docs/2.x/components-glossary/pages-fetch 'Documentation sur la méthode fetch (nouvel onglet)')).\n\n```javascript\n// Header.vue\n\u003Ctemplate>\n \u003Cheader v-if=\"!$fetchState.pending\">\n …\n \u003C/header>\n\u003C/template>\n\n\u003Cscript>\nimport headerQuery from '~/graphql/queries/singles/header'\n\nexport default {\n data() {\n return {\n data: {},\n }\n },\n async fetch() {\n try {\n const data = await this.$graphql.default.request(headerQuery)\n this.data = data\n } catch (error) {\n console.error(JSON.stringify(error, undefined, 2))\n }\n },\n}\n\u003C/script>\n```\n\n### Les options\n\nPour passer des options à la requête, par exemple pour une version multilingue avec [nuxt/i18n](https://i18n.nuxtjs.org/ 'Documentation de nuxt i18n (nouvel onglet)') et/ou un paramètre d'url dans le cadre d'une page dynamique :\n\n```javascript\n// _slug.vue\n\u003Cscript>\nimport articleQuery from '~/graphql/queries/articles'\n\nexport default {\n async asyncData({ $graphql, app, params }) {\n const locale = app.i18n.localeProperties.iso\n const data = await $graphql.default.request(articleQuery, {\n code: locale,\n slug: params.slug,\n })\n return { data }\n },\n}\n\u003C/script>\n```","src/content/fragments/fr/nuxt-graphql-static.md","73b6cc6b4fed04f5",{"html":818,"metadata":819},"\u003Ch2 id=\"le-problème\">Le problème\u003C/h2>\n\u003Cp>Je me suis heurté à un villain bug en utilisant Nuxt en mode génération statique complète et le client \u003Ca href=\"https://github.com/nuxt-community/apollo-module\" title=\"Dépôt github du module nuxt apollo (nouvel onglet)\">nuxt apollo\u003C/a>.\nAprès quelques recherches, voici \u003Ca href=\"https://github.com/nuxt-community/apollo-module/issues/339\" title=\"Bug visible sur le dépôt github du module nuxt/apollo (nouvel onglet)\">le bug constaté par quelqu’un d’autre\u003C/a> sur github.\u003C/p>\n\u003Cp>Il semblerait que le module en l’état ne gère pas correctement la génération statique avec \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>Je trouvais toujours des appels à mon API locale après la génération statique et la navigation depuis les \u003Ccode><nuxt-link>\u003C/code> ne fonctionnait pas.\u003C/p>\n\u003Ch2 id=\"la-solution\">La solution 🙌\u003C/h2>\n\u003Cp>Heureusement, il existe un autre module Nuxt pour gérer les requêtes GraphQL !\u003C/p>\n\u003Cp>\u003Ca href=\"https://github.com/gomah/nuxt-graphql-request\" title=\"Dépôt github du module (nouvel onglet)\">Nuxt graphql request à la rescousse !\u003C/a>\u003C/p>\n\u003Ch3 id=\"la-conf\">La conf\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// nuxt.config.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">buildModules\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#98C379\"> 'nuxt-graphql-request'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> clients\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> endpoint\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'http://API_URL/graphql'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> options\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> headers\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> authorization\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Bearer API_TOKEN'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">},\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"la-requête\">La requête\u003C/h3>\n\u003Cp>La meilleure méthode à ce jour est d’utiliser \u003Ccode>asyncData\u003C/code> dans les pages et \u003Ccode>fetch\u003C/code> dans les composants. Utiliser \u003Ccode>fetch\u003C/code> dans les pages ne fonctionne pas bien du tout avec \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>J’installe également le paquet \u003Ccode>graphql-tag\u003C/code> (uniquement en \u003Ccode>devDependencies\u003C/code>) afin de pouvoir importer directement des fichiers \u003Ccode>.gql\u003C/code>\u003C/p>\n\u003Cp>Exemple de fichier :\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"graphql\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\"># homepage.gql\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">query\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\thomepage\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\ttitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tsubtitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\thero\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\t\tid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\t\talt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"dans-une-page\">Dans une page\u003C/h4>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import homepageQuery from '~/graphql/queries/singles/homepage'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> asyncData\u003C/span>\u003Cspan style=\"color:#ABB2BF\">({ \u003C/span>\u003Cspan style=\"color:#E06C75\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> $graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">homepageQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return { \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"dans-un-composant\">Dans un composant\u003C/h4>\n\u003Cp>Il est plus prudent d’attendre que \u003Ccode>fetch\u003C/code> ait reçu une réponse avant d’afficher quoi que ce soit. On peut utiliser \u003Ccode>$fetchState\u003C/code> afin d’être tranquille (\u003Ca href=\"https://fr.nuxtjs.org/docs/2.x/components-glossary/pages-fetch\" title=\"Documentation sur la méthode fetch (nouvel onglet)\">documentation\u003C/a>).\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// Header.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">template\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> <\u003C/span>\u003Cspan style=\"color:#E06C75\">header\u003C/span>\u003Cspan style=\"color:#D19A66;font-style:italic\"> v-if\u003C/span>\u003Cspan style=\"color:#56B6C2\">=\u003C/span>\u003Cspan style=\"color:#98C379\">\"!$fetchState.pending\"\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> …\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> </\u003C/span>\u003Cspan style=\"color:#E06C75\">header\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">template\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import headerQuery from '~/graphql/queries/singles/header'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\"> data\u003C/span>\u003Cspan style=\"color:#ABB2BF\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> data\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> fetch\u003C/span>\u003Cspan style=\"color:#ABB2BF\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> try {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> const\u003C/span>\u003Cspan style=\"color:#E5C07B\"> data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> this\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">headerQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E5C07B\"> this\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#E06C75\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> } catch (error) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> console.\u003C/span>\u003Cspan style=\"color:#61AFEF\">error\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(JSON.stringify(\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">error\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">undefined\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, 2))\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> }\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"les-options\">Les options\u003C/h3>\n\u003Cp>Pour passer des options à la requête, par exemple pour une version multilingue avec \u003Ca href=\"https://i18n.nuxtjs.org/\" title=\"Documentation de nuxt i18n (nouvel onglet)\">nuxt/i18n\u003C/a> et/ou un paramètre d’url dans le cadre d’une page dynamique :\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// _slug.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import articleQuery from '~/graphql/queries/articles'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> asyncData\u003C/span>\u003Cspan style=\"color:#ABB2BF\">({ \u003C/span>\u003Cspan style=\"color:#E06C75\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75\">app\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75\">params\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">locale\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#E5C07B\"> app\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">i18n\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">localeProperties\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">iso\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> $graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">articleQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> code\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#E06C75\">locale\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> slug\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#E5C07B\">params\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">slug\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> })\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return { \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":820,"imagePaths":843,"frontmatter":844},[821,824,827,830,833,837,840],{"depth":150,"slug":822,"text":823},"le-problème","Le problème",{"depth":150,"slug":825,"text":826},"la-solution","La solution 🙌",{"depth":154,"slug":828,"text":829},"la-conf","La conf",{"depth":154,"slug":831,"text":832},"la-requête","La requête",{"depth":834,"slug":835,"text":836},4,"dans-une-page","Dans une page",{"depth":834,"slug":838,"text":839},"dans-un-composant","Dans un composant",{"depth":154,"slug":841,"text":842},"les-options","Les options",[],{"title":809,"subtitle":810,"lang":16,"slug":806,"createdAt":170,"updatedAt":845,"excerpt":846,"tags":847,"type":427},"2022-09-08T13:43:33.000Z","Quand le module gql le plus utilisé ne fonctionne pas…",[490],"en-nuxt-graphql-static",{"id":848,"data":850,"body":856,"filePath":857,"digest":858,"rendered":859},{"title":851,"subtitle":852,"lang":68,"tags":853,"type":467,"slug":848,"createdAt":854,"updatedAt":855},"Static website and GraphQL queries with Nuxt.js","Graphql client is king.",[490],["Date","2022-06-08T14:24:06.000Z"],["Date","2022-09-08T13:43:33.000Z"],"## The problem\n\nI encountered a nasty bug while using static generation with Nuxt and [nuxt apollo](https://github.com/nuxt-community/apollo-module 'Dépôt github du module nuxt apollo (new tab)') client.\nI found [the issue](https://github.com/nuxt-community/apollo-module/issues/339 'Github issue on nuxt/apollo repository (new tab)') already reported on github.\n\nIt seems the module doesn't handle static generation correctly with `nuxt generate`.\n\nI could find request to my local API url after the static generation. Moreover, it also seemed like `\u003Cnuxt-link>` navigation was broken.\n\n## The solution 🙌\n\nFortunately, there is another Nuxt module that handles GraphQL requests!\n\n[Nuxt graphql request to the rescue!](https://github.com/gomah/nuxt-graphql-request)\n\n### The conf\n\n```javascript\n// nuxt.config.js\nbuildModules: [\n 'nuxt-graphql-request',\n],\ngraphql: {\n clients: {\n default: {\n endpoint: 'http://API_URL/graphql',\n options: {\n headers: {\n authorization: 'Bearer API_TOKEN',\n },\n },\n },\n },\n},\n```\n\n### The request\n\nThe best approach so far is to use `asyncData` in pages and `fetch` in components. Using `fetch` in pages does not work well at all with `nuxt generate`.\n\nI also install the `graphql-tag` package (only in `devDependencies`) to be able to import directly `.gql` files.\n\nQuery example:\n\n```graphql\n# homepage.gql\nquery {\n\thomepage {\n\t\ttitle\n\t\tsubtitle\n\t\thero {\n\t\t\tid\n\t\t\talt\n\t\t}\n\t}\n}\n```\n\n#### Inside a page\n\n```javascript\n// index.vue\n\u003Cscript>\nimport homepageQuery from '~/graphql/queries/singles/homepage'\n\nexport default {\n async asyncData({ $graphql }) {\n const data = await $graphql.default.request(homepageQuery)\n return { data }\n },\n}\n\u003C/script>\n```\n\n#### Inside a component\n\nIt is safer to wait until `fetch` has received a response before displaying anything. You can use `$fetchState` to be sure ([documentation](https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch 'Documentation on the fetch hook (new tab)')).\n\n```javascript\n// Header.vue\n\u003Ctemplate>\n \u003Cheader v-if=\"!$fetchState.pending\">\n …\n \u003C/header>\n\u003C/template>\n\n\u003Cscript>\nimport headerQuery from '~/graphql/queries/singles/header'\n\nexport default {\n data() {\n return {\n data: {},\n }\n },\n async fetch() {\n try {\n const data = await this.$graphql.default.request(headerQuery)\n this.data = data\n } catch (error) {\n console.error(JSON.stringify(error, undefined, 2))\n }\n },\n}\n\u003C/script>\n```\n\n### Options\n\nTo pass options to the request, for example for a multilingual version with [nuxt/i18n](https://i18n.nuxtjs.org/) and/or a url parameter in a dynamic page:\n\n```javascript\n// _slug.vue\n\u003Cscript>\nimport articleQuery from '~/graphql/queries/articles'\n\nexport default {\n async asyncData({ $graphql, app, params }) {\n const locale = app.i18n.localeProperties.iso\n const data = await $graphql.default.request(articleQuery, {\n code: locale,\n slug: params.slug,\n })\n return { data }\n },\n}\n\u003C/script>\n```","src/content/fragments/en/nuxt-graphql-static.md","181e8091294eb858",{"html":860,"metadata":861},"\u003Ch2 id=\"the-problem\">The problem\u003C/h2>\n\u003Cp>I encountered a nasty bug while using static generation with Nuxt and \u003Ca href=\"https://github.com/nuxt-community/apollo-module\" title=\"Dépôt github du module nuxt apollo (new tab)\">nuxt apollo\u003C/a> client.\nI found \u003Ca href=\"https://github.com/nuxt-community/apollo-module/issues/339\" title=\"Github issue on nuxt/apollo repository (new tab)\">the issue\u003C/a> already reported on github.\u003C/p>\n\u003Cp>It seems the module doesn’t handle static generation correctly with \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>I could find request to my local API url after the static generation. Moreover, it also seemed like \u003Ccode><nuxt-link>\u003C/code> navigation was broken.\u003C/p>\n\u003Ch2 id=\"the-solution\">The solution 🙌\u003C/h2>\n\u003Cp>Fortunately, there is another Nuxt module that handles GraphQL requests!\u003C/p>\n\u003Cp>\u003Ca href=\"https://github.com/gomah/nuxt-graphql-request\">Nuxt graphql request to the rescue!\u003C/a>\u003C/p>\n\u003Ch3 id=\"the-conf\">The conf\u003C/h3>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// nuxt.config.js\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">buildModules\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: [\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#98C379\"> 'nuxt-graphql-request'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">],\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> clients\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> endpoint\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'http://API_URL/graphql'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> options\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> headers\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> authorization\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#98C379\">'Bearer API_TOKEN'\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">},\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"the-request\">The request\u003C/h3>\n\u003Cp>The best approach so far is to use \u003Ccode>asyncData\u003C/code> in pages and \u003Ccode>fetch\u003C/code> in components. Using \u003Ccode>fetch\u003C/code> in pages does not work well at all with \u003Ccode>nuxt generate\u003C/code>.\u003C/p>\n\u003Cp>I also install the \u003Ccode>graphql-tag\u003C/code> package (only in \u003Ccode>devDependencies\u003C/code>) to be able to import directly \u003Ccode>.gql\u003C/code> files.\u003C/p>\n\u003Cp>Query example:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"graphql\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\"># homepage.gql\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">query\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\thomepage\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\ttitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\tsubtitle\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\thero\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\t\tid\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\">\t\t\talt\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">\t}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"inside-a-page\">Inside a page\u003C/h4>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// index.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import homepageQuery from '~/graphql/queries/singles/homepage'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> asyncData\u003C/span>\u003Cspan style=\"color:#ABB2BF\">({ \u003C/span>\u003Cspan style=\"color:#E06C75\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> $graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">homepageQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return { \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch4 id=\"inside-a-component\">Inside a component\u003C/h4>\n\u003Cp>It is safer to wait until \u003Ccode>fetch\u003C/code> has received a response before displaying anything. You can use \u003Ccode>$fetchState\u003C/code> to be sure (\u003Ca href=\"https://nuxtjs.org/docs/2.x/components-glossary/pages-fetch\" title=\"Documentation on the fetch hook (new tab)\">documentation\u003C/a>).\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// Header.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">template\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> <\u003C/span>\u003Cspan style=\"color:#E06C75\">header\u003C/span>\u003Cspan style=\"color:#D19A66;font-style:italic\"> v-if\u003C/span>\u003Cspan style=\"color:#56B6C2\">=\u003C/span>\u003Cspan style=\"color:#98C379\">\"!$fetchState.pending\"\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> …\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> </\u003C/span>\u003Cspan style=\"color:#E06C75\">header\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">template\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import headerQuery from '~/graphql/queries/singles/header'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#61AFEF\"> data\u003C/span>\u003Cspan style=\"color:#ABB2BF\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> data\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: {},\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> fetch\u003C/span>\u003Cspan style=\"color:#ABB2BF\">() {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> try {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> const\u003C/span>\u003Cspan style=\"color:#E5C07B\"> data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> this\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">headerQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">)\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E5C07B\"> this\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#E06C75\"> data\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> } catch (error) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> console.\u003C/span>\u003Cspan style=\"color:#61AFEF\">error\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(JSON.stringify(\u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">error\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75;font-style:italic\">undefined\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, 2))\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\"> }\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Ch3 id=\"options\">Options\u003C/h3>\n\u003Cp>To pass options to the request, for example for a multilingual version with \u003Ca href=\"https://i18n.nuxtjs.org/\">nuxt/i18n\u003C/a> and/or a url parameter in a dynamic page:\u003C/p>\n\u003Cpre class=\"astro-code one-dark-pro\" style=\"background-color:#282c34;color:#abb2bf; overflow-x: auto;\" tabindex=\"0\" data-language=\"javascript\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#7F848E;font-style:italic\">// _slug.vue\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"><\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">import articleQuery from '~/graphql/queries/articles'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\">export default \u003C/span>\u003Cspan style=\"color:#C678DD\">{\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> async\u003C/span>\u003Cspan style=\"color:#61AFEF\"> asyncData\u003C/span>\u003Cspan style=\"color:#ABB2BF\">({ \u003C/span>\u003Cspan style=\"color:#E06C75\">$graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75\">app\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, \u003C/span>\u003Cspan style=\"color:#E06C75\">params\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">locale\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#E5C07B\"> app\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">i18n\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">localeProperties\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">iso\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> const \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#56B6C2\"> =\u003C/span>\u003Cspan style=\"color:#C678DD\"> await\u003C/span>\u003Cspan style=\"color:#E5C07B\"> $graphql\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E5C07B\">default\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#61AFEF\">request\u003C/span>\u003Cspan style=\"color:#ABB2BF\">(\u003C/span>\u003Cspan style=\"color:#E06C75\">articleQuery\u003C/span>\u003Cspan style=\"color:#ABB2BF\">, {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> code\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#E06C75\">locale\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E06C75\"> slug\u003C/span>\u003Cspan style=\"color:#ABB2BF\">: \u003C/span>\u003Cspan style=\"color:#E5C07B\">params\u003C/span>\u003Cspan style=\"color:#ABB2BF\">.\u003C/span>\u003Cspan style=\"color:#E06C75\">slug\u003C/span>\u003Cspan style=\"color:#ABB2BF\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> })\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> return { \u003C/span>\u003Cspan style=\"color:#E06C75\">data\u003C/span>\u003Cspan style=\"color:#ABB2BF\"> }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"> },\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#C678DD\">}\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#ABB2BF\"></\u003C/span>\u003Cspan style=\"color:#E06C75\">script\u003C/span>\u003Cspan style=\"color:#ABB2BF\">>\u003C/span>\u003C/span>\u003C/code>\u003C/pre>",{"headings":862,"imagePaths":884,"frontmatter":885},[863,866,869,872,875,878,881],{"depth":150,"slug":864,"text":865},"the-problem","The problem",{"depth":150,"slug":867,"text":868},"the-solution","The solution 🙌",{"depth":154,"slug":870,"text":871},"the-conf","The conf",{"depth":154,"slug":873,"text":874},"the-request","The request",{"depth":834,"slug":876,"text":877},"inside-a-page","Inside a page",{"depth":834,"slug":879,"text":880},"inside-a-component","Inside a component",{"depth":154,"slug":882,"text":883},"options","Options",[],{"title":851,"subtitle":852,"lang":68,"slug":848,"createdAt":170,"updatedAt":845,"excerpt":886,"tags":887,"type":467},"When the most used gql module doesn't work…",[490],"veille",["Map",269,890],{"id":269,"data":891,"body":893,"filePath":894,"digest":895,"rendered":896},{"lang":16,"title":269,"updatedAt":892},["Date","2023-04-20T17:12:06.000Z"],"- [mmm.page](https://build.mmm.page/) - Éditeur de sites web très simples, en glisser-déposer, pour n'importe quoi.\n- [Color.io](https://www.color.io/) - Éditeur photo en ligne.\n- [Addy's toolkit](https://toolkit.addy.codes/) - Outils et ressources pour les designers et développeurs sites web.\n- [L’accessibilité n’est pas une variable d’ajustement](https://www.sophie-drouvroy.com/blog/laccessibilite-nest-pas-une-variable-dajustement/) — Sophie Drouvroy, intégratrice front-end, partage son quotidien en tant que personne sourde dans notre société.\n > L’accessibilité doit être au cœur du projet et pas une cerise sur le gâteau.\n- [3D en CSS (english)](https://garden.bradwoods.io/notes/css/3d) – Explications et exemples des propriétés 3D en CSS.\n- [Climat : Comment ne pas déprimer ?](https://www.lemonde.fr/podcasts/article/2022/06/21/climat-comment-ne-pas-deprimer_6131347_5463015.html) – Podcast.\n- [Fable (english)](https://fable.app) – Application de motion design.\n- [Rive (english)](https://rive.app) – Application de motion design.\n- [Cake Desk](https://cakedesk.app/) – Application de facturation.\n- [Ombre fluide en CSS](https://shadows.brumm.af/) – Générateur.\n- [Smol CSS](https://smolcss.dev/) – Collection de fragments CSS.\n- [Ajustement optique](https://marvelapp.com/blog/optical-adjustment-logic-vs-designers/) (english) – Aligner visuellement plutôt que techniquement.\n- [Datawrapper](https://blog.datawrapper.de/category/datavis-dos-and-donts/) (english) – Conseils pour montrer de la donnée.\n- [Assistivlabs](https://assistivlabs.com/) (english) – Service de test des technologies d'assistance (browserstack mais pour l'accessibilité).\n- [Les caractères fantaisistes et l'accessibilité](https://www.lalutineduweb.fr/detournement-unicode-emojis-accessibilite/) – Explications et exemples de l'enfer que sont les caractères Unicode pour les technologies d'assistance.\n- [Créer un champ `time` sur le web](https://adamsilver.io/blog/designing-a-time-input-backed-by-research/) (english) – Article.\n- [La cascade](https://la-cascade.io) – Collection d'articles sur le CSS.\n- [Tabby](https://tabby.sh) (english) – An alternative terminal app.\n- [Newglyph](https://newglyph.com/) – Fonderie indépendante.\n- [\u003Cspan lang=\"en\">Headless UI\u003C/span>](https://headlessui.com/vue/dialog) (english) – Librairie de composants vue et react.\n- [Vie privée sexy](https://privacy.sexy) (english) – Outils de confidentialité pour windows et macos.\n- [33 concepts JavaScript](https://github.com/leonardomso/33-js-concepts) (english) – Articles.\n- [Formbricks](https://formbricks.com/) (english) – Alternative open source à google form/typeform.\n- [Animations de chargement SVG](https://github.com/n3r4zzurr0/svg-spinners) – Collection.\n- [a11yphant](https://a11yphant.com/) (english) – Challenges de code pour apprendre l'accessibilité.\n- [CSS moderne](https://moderncss.dev/) (english) – Fragments CSS.\n- [Conteneur moderne en CSS](https://twitter.com/KevinJPowell/status/1501555193799925761) (english) – Tweet de Kevin Powell ❤️","src/data/veille/2023.md","1135beec386f207f",{"html":897,"metadata":898},"\u003Cul>\n\u003Cli>\u003Ca href=\"https://build.mmm.page/\">mmm.page\u003C/a> - Éditeur de sites web très simples, en glisser-déposer, pour n’importe quoi.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.color.io/\">Color.io\u003C/a> - Éditeur photo en ligne.\u003C/li>\n\u003Cli>\u003Ca href=\"https://toolkit.addy.codes/\">Addy’s toolkit\u003C/a> - Outils et ressources pour les designers et développeurs sites web.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.sophie-drouvroy.com/blog/laccessibilite-nest-pas-une-variable-dajustement/\">L’accessibilité n’est pas une variable d’ajustement\u003C/a> — Sophie Drouvroy, intégratrice front-end, partage son quotidien en tant que personne sourde dans notre société.\n\u003Cblockquote>\n\u003Cp>L’accessibilité doit être au cœur du projet et pas une cerise sur le gâteau.\u003C/p>\n\u003C/blockquote>\n\u003C/li>\n\u003Cli>\u003Ca href=\"https://garden.bradwoods.io/notes/css/3d\">3D en CSS (english)\u003C/a> – Explications et exemples des propriétés 3D en CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lemonde.fr/podcasts/article/2022/06/21/climat-comment-ne-pas-deprimer_6131347_5463015.html\">Climat : Comment ne pas déprimer ?\u003C/a> – Podcast.\u003C/li>\n\u003Cli>\u003Ca href=\"https://fable.app\">Fable (english)\u003C/a> – Application de motion design.\u003C/li>\n\u003Cli>\u003Ca href=\"https://rive.app\">Rive (english)\u003C/a> – Application de motion design.\u003C/li>\n\u003Cli>\u003Ca href=\"https://cakedesk.app/\">Cake Desk\u003C/a> – Application de facturation.\u003C/li>\n\u003Cli>\u003Ca href=\"https://shadows.brumm.af/\">Ombre fluide en CSS\u003C/a> – Générateur.\u003C/li>\n\u003Cli>\u003Ca href=\"https://smolcss.dev/\">Smol CSS\u003C/a> – Collection de fragments CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://marvelapp.com/blog/optical-adjustment-logic-vs-designers/\">Ajustement optique\u003C/a> (english) – Aligner visuellement plutôt que techniquement.\u003C/li>\n\u003Cli>\u003Ca href=\"https://blog.datawrapper.de/category/datavis-dos-and-donts/\">Datawrapper\u003C/a> (english) – Conseils pour montrer de la donnée.\u003C/li>\n\u003Cli>\u003Ca href=\"https://assistivlabs.com/\">Assistivlabs\u003C/a> (english) – Service de test des technologies d’assistance (browserstack mais pour l’accessibilité).\u003C/li>\n\u003Cli>\u003Ca href=\"https://www.lalutineduweb.fr/detournement-unicode-emojis-accessibilite/\">Les caractères fantaisistes et l’accessibilité\u003C/a> – Explications et exemples de l’enfer que sont les caractères Unicode pour les technologies d’assistance.\u003C/li>\n\u003Cli>\u003Ca href=\"https://adamsilver.io/blog/designing-a-time-input-backed-by-research/\">Créer un champ \u003Ccode>time\u003C/code> sur le web\u003C/a> (english) – Article.\u003C/li>\n\u003Cli>\u003Ca href=\"https://la-cascade.io\">La cascade\u003C/a> – Collection d’articles sur le CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://tabby.sh\">Tabby\u003C/a> (english) – An alternative terminal app.\u003C/li>\n\u003Cli>\u003Ca href=\"https://newglyph.com/\">Newglyph\u003C/a> – Fonderie indépendante.\u003C/li>\n\u003Cli>\u003Ca href=\"https://headlessui.com/vue/dialog\">\u003Cspan lang=\"en\">Headless UI\u003C/span>\u003C/a> (english) – Librairie de composants vue et react.\u003C/li>\n\u003Cli>\u003Ca href=\"https://privacy.sexy\">Vie privée sexy\u003C/a> (english) – Outils de confidentialité pour windows et macos.\u003C/li>\n\u003Cli>\u003Ca href=\"https://github.com/leonardomso/33-js-concepts\">33 concepts JavaScript\u003C/a> (english) – Articles.\u003C/li>\n\u003Cli>\u003Ca href=\"https://formbricks.com/\">Formbricks\u003C/a> (english) – Alternative open source à google form/typeform.\u003C/li>\n\u003Cli>\u003Ca href=\"https://github.com/n3r4zzurr0/svg-spinners\">Animations de chargement SVG\u003C/a> – Collection.\u003C/li>\n\u003Cli>\u003Ca href=\"https://a11yphant.com/\">a11yphant\u003C/a> (english) – Challenges de code pour apprendre l’accessibilité.\u003C/li>\n\u003Cli>\u003Ca href=\"https://moderncss.dev/\">CSS moderne\u003C/a> (english) – Fragments CSS.\u003C/li>\n\u003Cli>\u003Ca href=\"https://twitter.com/KevinJPowell/status/1501555193799925761\">Conteneur moderne en CSS\u003C/a> (english) – Tweet de Kevin Powell ❤️\u003C/li>\n\u003C/ul>",{"headings":899,"imagePaths":900,"frontmatter":901},[],[],{"lang":16,"title":269,"updatedAt":902},"2023-04-20T17:12:06.000Z","HPsections",["Map",905,906,926,927,943,944,960,961,985,986],"011-offre",{"id":905,"data":907,"body":914,"filePath":915,"digest":916,"rendered":917},{"type":908,"lang":16,"uid":909,"image":910,"order":911,"quickTitle":912,"quickImage":913,"reference":39},"section","offre","/assets/images/home/offre-1.1.svg",1.1,"Mes offres en freelance","/assets/images/home/icon-desktop.svg","## L'offre site web classique\n\nCette offre est destinée à un public souhaitant **se doter d'un site web**, sans forcément intégrer l'accessibilité au cœur du projet. Le site sera malgré tout développé au plus proche des règles du [référentiel général d'amélioration de l'accessibilité](https://accessibilite.numerique.gouv.fr/) (\u003Cabbr>RGAA\u003C/abbr>).\n\nL'objectif principal de cette offre étant d'**établir une présence en ligne** pour le client. Que cette dernière ait un but informatif et/ou éditorial.\n\n\u003C!-- \u003Ca href=\"/offres/web-classique\" class=\"btn\">L'offre classique en détails\u003C/a> -->","src/data/HP/011-offre.md","290ecd1ed94a1087",{"html":918,"metadata":919},"\u003Ch2 id=\"loffre-site-web-classique\">L’offre site web classique\u003C/h2>\n\u003Cp>Cette offre est destinée à un public souhaitant \u003Cstrong>se doter d’un site web\u003C/strong>, sans forcément intégrer l’accessibilité au cœur du projet. Le site sera malgré tout développé au plus proche des règles du \u003Ca href=\"https://accessibilite.numerique.gouv.fr/\">référentiel général d’amélioration de l’accessibilité\u003C/a> (\u003Cabbr>RGAA\u003C/abbr>).\u003C/p>\n\u003Cp>L’objectif principal de cette offre étant d’\u003Cstrong>établir une présence en ligne\u003C/strong> pour le client. Que cette dernière ait un but informatif et/ou éditorial.\u003C/p>\n\u003C!-- \u003Ca href=\"/offres/web-classique\" class=\"btn\">L'offre classique en détails\u003C/a> -->",{"headings":920,"imagePaths":924,"frontmatter":925},[921],{"depth":150,"slug":922,"text":923},"loffre-site-web-classique","L’offre site web classique",[],{"type":908,"uid":909,"lang":16,"image":910,"order":911,"quickTitle":912,"quickImage":913,"reference":39},"012-offre",{"id":926,"data":928,"body":931,"filePath":932,"digest":933,"rendered":934},{"type":908,"lang":16,"image":929,"order":930,"reference":50},"/assets/images/home/offre-1.2.svg",1.2,"## L'offre accessibilité avancée\n\nCette offre s'adresse plus spécifiquement aux entités pour lesquelles **l'accessibilité du site est un critère majeur.** Qu'il s'agisse d'une création ou d'une mise en conformité après un audit d'accessibilité.\n\nLorsque le projet le nécessite, je fais appel à des partenaires talentueux partageant les mêmes valeurs :\n\n- [Rose Primaire](https://roseprimaire.com/) pour le conseil et l'accompagnement du projet ;\n- [Sylvain Plantier](https://jedessinebien.com/) et/ou [Benoît Etchevery](http://ben-etche.com/) pour l'illustration et la direction artistique.\n\n\u003C!-- \u003Ca href=\"/offres/accessibilite\" class=\"btn\">L'offre accessibilité en détails\u003C/a> -->","src/data/HP/012-offre.md","2a3bf3411b3c171b",{"html":935,"metadata":936},"\u003Ch2 id=\"loffre-accessibilité-avancée\">L’offre accessibilité avancée\u003C/h2>\n\u003Cp>Cette offre s’adresse plus spécifiquement aux entités pour lesquelles \u003Cstrong>l’accessibilité du site est un critère majeur.\u003C/strong> Qu’il s’agisse d’une création ou d’une mise en conformité après un audit d’accessibilité.\u003C/p>\n\u003Cp>Lorsque le projet le nécessite, je fais appel à des partenaires talentueux partageant les mêmes valeurs :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://roseprimaire.com/\">Rose Primaire\u003C/a> pour le conseil et l’accompagnement du projet ;\u003C/li>\n\u003Cli>\u003Ca href=\"https://jedessinebien.com/\">Sylvain Plantier\u003C/a> et/ou \u003Ca href=\"http://ben-etche.com/\">Benoît Etchevery\u003C/a> pour l’illustration et la direction artistique.\u003C/li>\n\u003C/ul>\n\u003C!-- \u003Ca href=\"/offres/accessibilite\" class=\"btn\">L'offre accessibilité en détails\u003C/a> -->",{"headings":937,"imagePaths":941,"frontmatter":942},[938],{"depth":150,"slug":939,"text":940},"loffre-accessibilité-avancée","L’offre accessibilité avancée",[],{"type":908,"lang":16,"order":930,"image":929,"reference":50},"013-offre",{"id":943,"data":945,"body":948,"filePath":949,"digest":950,"rendered":951},{"type":908,"lang":16,"image":946,"order":947},"/assets/images/home/offre-1.3.svg",1.3,"## Et l'éco-conception alors ?\n\nJe ne conçois pas l'éco-conception comme une offre. C'est plutôt une façon de travailler, voire même une vision de mon métier. On fait rarement de l'éco-conception sans accessibilité, j'applique donc ces méthodologies quelque soit le projet !","src/data/HP/013-offre.md","03e37f364ac27cb4",{"html":952,"metadata":953},"\u003Ch2 id=\"et-léco-conception-alors\">Et l’éco-conception alors ?\u003C/h2>\n\u003Cp>Je ne conçois pas l’éco-conception comme une offre. C’est plutôt une façon de travailler, voire même une vision de mon métier. On fait rarement de l’éco-conception sans accessibilité, j’applique donc ces méthodologies quelque soit le projet !\u003C/p>",{"headings":954,"imagePaths":958,"frontmatter":959},[955],{"depth":150,"slug":956,"text":957},"et-léco-conception-alors","Et l’éco-conception alors ?",[],{"type":908,"lang":16,"order":947,"image":946},"020-methodo",{"id":960,"data":962,"body":967,"filePath":968,"digest":969,"rendered":970},{"type":908,"lang":16,"uid":963,"image":964,"order":150,"quickTitle":965,"quickImage":966},"methodology","/assets/images/home/methodo.svg","Ma méthodologie","/assets/images/home/icon-methodo.svg","## Méthodologie\n\n### Accessibilité par défaut\n\nEngagé pour un web plus accessible, je crée des **sites web** en m'appuyant sur le [référentiel général d'amélioration de l'accessibilité (RGAA)](https://www.numerique.gouv.fr/publications/rgaa-accessibilite/) ainsi que sur les bonnes pratiques [Opquast.](https://www.opquast.com/rendre-le-web-meilleur/)\n\n### Sobriété par choix\n\nJe privilégie le développement de **sites statiques** en adoptant une approche [d'éco-conception numérique.](https://eco-conception.designersethiques.org/guide/fr/) \nC'est-à-dire que le site est pensé pour n'embarquer que les fonctionnalités nécessaires à son utilisation.\n\nCette approche présente de **nombreux avantages :**\n\n- chargement rapide des pages ;\n- sécurité renforcée ;\n- coûts serveur réduits ;\n- maintenance facilitée.\n\nLorsque le projet le demande, je mets en place un outil de gestion des contenus (CMS) découplé de l'interface. Cela permet de garantir que **le site reste en ligne** même si le CMS venait à ne plus fonctionner.","src/data/HP/020-methodo.md","75a09b4e0b1e926b",{"html":971,"metadata":972},"\u003Ch2 id=\"méthodologie\">Méthodologie\u003C/h2>\n\u003Ch3 id=\"accessibilité-par-défaut\">Accessibilité par défaut\u003C/h3>\n\u003Cp>Engagé pour un web plus accessible, je crée des \u003Cstrong>sites web\u003C/strong> en m’appuyant sur le \u003Ca href=\"https://www.numerique.gouv.fr/publications/rgaa-accessibilite/\">référentiel général d’amélioration de l’accessibilité (RGAA)\u003C/a> ainsi que sur les bonnes pratiques \u003Ca href=\"https://www.opquast.com/rendre-le-web-meilleur/\">Opquast.\u003C/a>\u003C/p>\n\u003Ch3 id=\"sobriété-par-choix\">Sobriété par choix\u003C/h3>\n\u003Cp>Je privilégie le développement de \u003Cstrong>sites statiques\u003C/strong> en adoptant une approche \u003Ca href=\"https://eco-conception.designersethiques.org/guide/fr/\">d’éco-conception numérique.\u003C/a>\u003Cbr>\nC’est-à-dire que le site est pensé pour n’embarquer que les fonctionnalités nécessaires à son utilisation.\u003C/p>\n\u003Cp>Cette approche présente de \u003Cstrong>nombreux avantages :\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>chargement rapide des pages ;\u003C/li>\n\u003Cli>sécurité renforcée ;\u003C/li>\n\u003Cli>coûts serveur réduits ;\u003C/li>\n\u003Cli>maintenance facilitée.\u003C/li>\n\u003C/ul>\n\u003Cp>Lorsque le projet le demande, je mets en place un outil de gestion des contenus (CMS) découplé de l’interface. Cela permet de garantir que \u003Cstrong>le site reste en ligne\u003C/strong> même si le CMS venait à ne plus fonctionner.\u003C/p>",{"headings":973,"imagePaths":983,"frontmatter":984},[974,977,980],{"depth":150,"slug":975,"text":976},"méthodologie","Méthodologie",{"depth":154,"slug":978,"text":979},"accessibilité-par-défaut","Accessibilité par défaut",{"depth":154,"slug":981,"text":982},"sobriété-par-choix","Sobriété par choix",[],{"type":908,"uid":963,"lang":16,"image":964,"order":150,"quickTitle":965,"quickImage":966},"030-about",{"id":985,"data":987,"body":992,"filePath":993,"digest":994,"rendered":995},{"type":908,"lang":16,"uid":988,"image":989,"order":154,"quickTitle":990,"quickImage":991},"about","/assets/images/home/about.svg","Moi","/assets/images/home/icon-heart.svg","## À propos\n\n### Formations personnelles\n\nAfin de solidifier mes compétences, j'ai suivi les formations et passé les certifications suivantes :\n\n- [Opquast](https://directory.opquast.com/fr/certificat/CTQSKP/) - Maîtrise de la qualité en projet web ;\n- Access42 - Développer et coder des sites accessibles (certificat numéro : 696fa2e0-cc67-11ec-88d2-9dabf3f992d4).\n\n### Formations des autres\n\nDepuis plusieurs années, j'interviens dans différents campus afin de dispenser des cours de développement web.\n\n### Temps libre\n\nJ’essaie de contribuer à des [projets open source](https://git.nardu.in/explore/repos) qui me tiennent à cœur et je m'engage localement avec le collectif [good-it!](https://www.good-it.org/)\n\nAh et j’écris [des articles](/articles) aussi ! Des articles sur le design, le développement web et l’informatique.","src/data/HP/030-about.md","a7abff6d744406ce",{"html":996,"metadata":997},"\u003Ch2 id=\"à-propos\">À propos\u003C/h2>\n\u003Ch3 id=\"formations-personnelles\">Formations personnelles\u003C/h3>\n\u003Cp>Afin de solidifier mes compétences, j’ai suivi les formations et passé les certifications suivantes :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Ca href=\"https://directory.opquast.com/fr/certificat/CTQSKP/\">Opquast\u003C/a> - Maîtrise de la qualité en projet web ;\u003C/li>\n\u003Cli>Access42 - Développer et coder des sites accessibles (certificat numéro : 696fa2e0-cc67-11ec-88d2-9dabf3f992d4).\u003C/li>\n\u003C/ul>\n\u003Ch3 id=\"formations-des-autres\">Formations des autres\u003C/h3>\n\u003Cp>Depuis plusieurs années, j’interviens dans différents campus afin de dispenser des cours de développement web.\u003C/p>\n\u003Ch3 id=\"temps-libre\">Temps libre\u003C/h3>\n\u003Cp>J’essaie de contribuer à des \u003Ca href=\"https://git.nardu.in/explore/repos\">projets open source\u003C/a> qui me tiennent à cœur et je m’engage localement avec le collectif \u003Ca href=\"https://www.good-it.org/\">good-it!\u003C/a>\u003C/p>\n\u003Cp>Ah et j’écris \u003Ca href=\"/articles\">des articles\u003C/a> aussi ! Des articles sur le design, le développement web et l’informatique.\u003C/p>",{"headings":998,"imagePaths":1011,"frontmatter":1012},[999,1002,1005,1008],{"depth":150,"slug":1000,"text":1001},"à-propos","À propos",{"depth":154,"slug":1003,"text":1004},"formations-personnelles","Formations personnelles",{"depth":154,"slug":1006,"text":1007},"formations-des-autres","Formations des autres",{"depth":154,"slug":1009,"text":1010},"temps-libre","Temps libre",[],{"type":908,"uid":988,"lang":16,"image":989,"order":154,"quickTitle":990,"quickImage":991}] \ No newline at end of file diff --git a/astro.config.mjs b/astro.config.mjs index 8bb12a7..d6cd124 100755 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,25 +1,30 @@ -import { defineConfig } from "astro/config"; +import { defineConfig } from 'astro/config' + +import { transformerMetaHighlight } from '@shikijs/transformers' // https://astro.build/config -import mdx from "@astrojs/mdx"; -import sitemap from "@astrojs/sitemap"; +import mdx from '@astrojs/mdx' +import sitemap from '@astrojs/sitemap' // https://astro.build/config export default defineConfig({ - site: "https://www.nardu.in", - build: { - format: "directory", - }, - i18n: { - locales: ["fr", "en"], - defaultLocale: "fr", - }, - image: { - domains: ["assets.nardu.in"], - remotePatterns: [{ protocol: "https" }], + site: 'https://www.nardu.in', + build: { + format: 'directory' }, - integrations: [ - mdx(), - sitemap(), - ], -}); + i18n: { + locales: ['fr', 'en'], + defaultLocale: 'fr' + }, + image: { + domains: ['assets.nardu.in'], + remotePatterns: [{ protocol: 'https' }] + }, + integrations: [mdx(), sitemap()], + markdown: { + shikiConfig: { + theme: 'one-dark-pro', + transformers: [transformerMetaHighlight()] + } + } +}) diff --git a/bun.lockb b/bun.lockb index 44152a49937e42750d551455e4844b246724d021..3ac73a9d088bfa1618cdc76c421d7e996ed12f2b 100755 GIT binary patch delta 31322 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 delta 30704 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 U7VOoU9Q$amR&bbk?owC(7wX)@`Tzg` diff --git a/package.json b/package.json index 0157e68..7293ee8 100755 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "sharp": "^0.33.5" }, "devDependencies": { + "@shikijs/transformers": "^1.24.4", "autoprefixer": "^10.4.20", "postcss": "^8.4.49", "prettier": "^3.4.2", diff --git a/src/components/EditorialContent.astro b/src/components/EditorialContent.astro index 236e35f..a2f7d7d 100755 --- a/src/components/EditorialContent.astro +++ b/src/components/EditorialContent.astro @@ -10,8 +10,6 @@ const { Content, headings } = await render(content) const toc = headings.map((heading) => { return heading }) - -import '../styles/vendor/one-dark-pro.css' ---