Deprecated: Function get_magic_quotes_gpc() is deprecated in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 99

Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 619

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 832

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839

Warning: Cannot modify header information - headers already sent by (output started at /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php:99) in /hermes/walnacweb04/walnacweb04ab/b2791/pow.jasaeld/htdocs/De1337/nothing/index.php on line 839
{ "version": "https://jsonfeed.org/version/1", "title": "Articles by François Best", "home_page_url": "https://francoisbest.com/posts", "feed_url": "https://francoisbest.com/posts/feed/articles.json", "description": "I write about TypeScript, Node.js, React, security and privacy.", "icon": "https://francoisbest.com/favicons/apple-icon-120x120.png", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "items": [ { "id": "/posts/2023/testing-against-every-nextjs-canary-release", "content_html": "How to run a GitHub Actions workflow when a new pre-release version of Next.js is published.\n\nFull article (6 min read).", "url": "https://francoisbest.com/posts/2023/testing-against-every-nextjs-canary-release?utm_source=json", "title": "Testing against every Next.js canary release", "summary": "How to run a GitHub Actions workflow when a new pre-release version of Next.js is published.", "image": "https://francoisbest.com/posts/2023/testing-against-every-nextjs-canary-release/opengraph-image-7h4dih.png", "date_modified": "2023-11-06T00:00:00.000Z", "date_published": "2023-11-06T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "next.js", "github-actions", "testing" ] }, { "id": "/posts/2023/publish-a-json-schema", "content_html": "Improving DX in editors is only half the story.\n\nFull article (3 min read).", "url": "https://francoisbest.com/posts/2023/publish-a-json-schema?utm_source=json", "title": "Publish a JSON Schema", "summary": "Improving DX in editors is only half the story.", "image": "https://francoisbest.com/posts/2023/publish-a-json-schema/opengraph-image-2njqy7.png", "date_modified": "2023-10-12T00:00:00.000Z", "date_published": "2023-10-12T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "json-schema", "nodejs" ] }, { "id": "/posts/2023/dotenv-is-dead", "content_html": "Long live type-safe environment variable management in Node.js\n\nFull article (3 min read).", "url": "https://francoisbest.com/posts/2023/dotenv-is-dead?utm_source=json", "title": "Dotenv is dead", "summary": "Long live type-safe environment variable management in Node.js", "image": "https://francoisbest.com/posts/2023/dotenv-is-dead/opengraph-image-1ad5cn.png", "date_modified": "2023-10-02T00:00:00.000Z", "date_published": "2023-10-02T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "til", "nodejs", "env" ] }, { "id": "/posts/2023/displaying-local-times-in-nextjs", "content_html": "Making time accessible by dealing with React SSR hydration mismatches across timezones.\n\nFull article (4 min read).", "url": "https://francoisbest.com/posts/2023/displaying-local-times-in-nextjs?utm_source=json", "title": "Displaying Local Times in Next.js", "summary": "Making time accessible by dealing with React SSR hydration mismatches across timezones.", "image": "https://francoisbest.com/posts/2023/displaying-local-times-in-nextjs/opengraph-image-520618.png", "date_modified": "2023-09-27T08:00:00.000Z", "date_published": "2023-09-27T08:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "til", "next.js", "react", "ssr", "rsc" ] }, { "id": "/posts/2023/npm-download-stats-are-down", "content_html": "And people are drawing the funniest conclusions.\n\nFull article (2 min read).", "url": "https://francoisbest.com/posts/2023/npm-download-stats-are-down?utm_source=json", "title": "NPM download stats are down", "summary": "And people are drawing the funniest conclusions.", "image": "https://francoisbest.com/posts/2023/npm-download-stats-are-down/opengraph-image-2ebvo2.png", "date_modified": "2023-09-21T00:00:00.000Z", "date_published": "2023-09-21T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "npm" ] }, { "id": "/posts/2023/storing-react-state-in-the-url-with-nextjs", "content_html": "A peek under the hood of the next-usequerystate 1.8.x update with support for the app router.\n\nFull article (7 min read).", "url": "https://francoisbest.com/posts/2023/storing-react-state-in-the-url-with-nextjs?utm_source=json", "title": "Storing React state in the URL with Next.js", "summary": "A peek under the hood of the next-usequerystate 1.8.x update with support for the app router.", "image": "https://francoisbest.com/posts/2023/storing-react-state-in-the-url-with-nextjs/opengraph-image-1t8hxb.png", "date_modified": "2023-09-20T00:00:00.000Z", "date_published": "2023-09-20T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "next.js", "react", "typescript" ] }, { "id": "/posts/2023/reading-files-on-vercel-during-nextjs-isr", "content_html": "A little hack to let the Next.js file tracer pick up relative file paths.\n\nFull article (2 min read).", "url": "https://francoisbest.com/posts/2023/reading-files-on-vercel-during-nextjs-isr?utm_source=json", "title": "Reading files on Vercel during Next.js ISR", "summary": "A little hack to let the Next.js file tracer pick up relative file paths.", "image": "https://francoisbest.com/posts/2023/reading-files-on-vercel-during-nextjs-isr/opengraph-image-5rau3n.jpg", "date_modified": "2023-09-16T00:00:00.000Z", "date_published": "2023-09-16T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "til", "next.js", "vercel", "rsc" ] }, { "id": "/posts/2023/displaying-the-right-vercel-deployment-urls-in-nextjs", "content_html": "A TIL about caching, Git branch management and React Server Components.\n\nFull article (4 min read).", "url": "https://francoisbest.com/posts/2023/displaying-the-right-vercel-deployment-urls-in-nextjs?utm_source=json", "title": "Displaying the right Vercel deployment URLs in Next.js", "summary": "A TIL about caching, Git branch management and React Server Components.", "image": "https://francoisbest.com/posts/2023/displaying-the-right-vercel-deployment-urls-in-nextjs/opengraph-image-2y7azx.jpg", "date_modified": "2023-09-09T00:00:00.000Z", "date_published": "2023-09-09T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "til", "rsc", "git", "next.js", "turborepo", "vercel" ] }, { "id": "/posts/2021/hashvatars", "content_html": "How to turn 256 bits of entropy into a beautiful, avatar-friendly circular SVG: the Hashvatar.\n\nFull article (12 min read).", "url": "https://francoisbest.com/posts/2021/hashvatars?utm_source=json", "title": "Representing SHA-256 Hashes As Avatars", "summary": "How to turn 256 bits of entropy into a beautiful, avatar-friendly circular SVG: the Hashvatar.", "image": "https://francoisbest.com/posts/2021/hashvatars/opengraph-image-aql0c0.jpg", "date_modified": "2021-04-18T00:00:00.000Z", "date_published": "2021-04-18T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "cryptography", "svg" ] }, { "id": "/posts/2021/cargo-docker-mtime", "content_html": "The perils of premature optimisation in detecting modified source files when building Docker images for Rust.\n\nFull article (4 min read).", "url": "https://francoisbest.com/posts/2021/cargo-docker-mtime?utm_source=json", "title": "Cargo, Docker and mtime", "summary": "The perils of premature optimisation in detecting modified source files when building Docker images for Rust.", "image": "https://francoisbest.com/posts/2021/cargo-docker-mtime/opengraph-image-3fykr9.jpg", "date_modified": "2021-01-25T00:00:00.000Z", "date_published": "2021-01-25T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "rust", "docker" ] }, { "id": "/posts/2020/mobile-device-frames-for-excalidraw", "content_html": "Building mobile UI mockups in Excalidraw is a lot of fun, but eye-balling screen ratios is not great. Here are some free resources to help you get started, and a guide on how to make your own frames.\n\nFull article (3 min read).", "url": "https://francoisbest.com/posts/2020/mobile-device-frames-for-excalidraw?utm_source=json", "title": "Mobile Device Frames For Excalidraw", "summary": "Building mobile UI mockups in Excalidraw is a lot of fun, but eye-balling screen ratios is not great. Here are some free resources to help you get started, and a guide on how to make your own frames.", "image": "https://francoisbest.com/posts/2020/mobile-device-frames-for-excalidraw/opengraph-image-2ujlx6.jpg", "date_modified": "2020-06-11T00:00:00.000Z", "date_published": "2020-06-11T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "excalidraw", "ui-design" ] }, { "id": "/posts/2020/dark-mode-for-excalidraw", "content_html": "How to give a dark twist to Excalidraw diagrams with CSS filters.\n\nFull article (3 min read).", "url": "https://francoisbest.com/posts/2020/dark-mode-for-excalidraw?utm_source=json", "title": "Dark Mode For Excalidraw", "summary": "How to give a dark twist to Excalidraw diagrams with CSS filters.", "image": "https://francoisbest.com/posts/2020/dark-mode-for-excalidraw/opengraph-image-fdfkxf.jpg", "date_modified": "2020-06-05T00:00:00.000Z", "date_published": "2020-06-05T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "frontend", "css", "excalidraw" ] }, { "id": "/posts/2020/the-security-of-github-actions", "content_html": "GitHub Actions are a great way to build powerful customised CI/CD workflows using the power of community-driven resources, but they can be tricky to get right in terms of security.\n\nFull article (9 min read).", "url": "https://francoisbest.com/posts/2020/the-security-of-github-actions?utm_source=json", "title": "The Security of GitHub Actions", "summary": "GitHub Actions are a great way to build powerful customised CI/CD workflows using the power of community-driven resources, but they can be tricky to get right in terms of security.", "image": "https://francoisbest.com/posts/2020/the-security-of-github-actions/opengraph-image-uguro0.jpg", "date_modified": "2020-02-24T00:00:00.000Z", "date_published": "2020-02-24T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "security", "tooling", "github-actions", "docker" ] }, { "id": "/posts/2020/password-reset-for-e2ee-apps", "content_html": "We forget passwords. Usually it's OK, because most websites implement a password reset feature. But how to do this in end-to-end encrypted applications that don't have access to the password in the first place ?\n\nFull article (5 min read).", "url": "https://francoisbest.com/posts/2020/password-reset-for-e2ee-apps?utm_source=json", "title": "Password Reset for End-to-End Encrypted Applications", "summary": "We forget passwords. Usually it's OK, because most websites implement a password reset feature. But how to do this in end-to-end encrypted applications that don't have access to the password in the first place ?", "image": "https://francoisbest.com/posts/2020/password-reset-for-e2ee-apps/opengraph-image-1al033.jpg", "date_modified": "2020-02-15T00:00:00.000Z", "date_published": "2020-02-15T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "e2ee", "security", "cryptography" ] }, { "id": "/posts/2019/how-to-store-e2ee-keys-in-the-browser", "content_html": "End-to-end encrypted applications use cryptographic keys that don't leave the client, so how do we store them securely in the browser ?\n\nFull article (4 min read).", "url": "https://francoisbest.com/posts/2019/how-to-store-e2ee-keys-in-the-browser?utm_source=json", "title": "How To Store End-to-End Encryption Keys In The Browser", "summary": "End-to-end encrypted applications use cryptographic keys that don't leave the client, so how do we store them securely in the browser ?", "image": "https://francoisbest.com/posts/2019/how-to-store-e2ee-keys-in-the-browser/opengraph-image-39g9ol.jpg", "date_modified": "2019-12-13T00:00:00.000Z", "date_published": "2019-12-13T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "e2ee", "security" ] }, { "id": "/posts/2019/strava-auth-cli-in-rust", "content_html": "A first look at how to implement an OAuth authentication / authorization exchange in Rust.\n\nFull article (14 min read).", "url": "https://francoisbest.com/posts/2019/strava-auth-cli-in-rust?utm_source=json", "title": "Building A Strava Authentication CLI In Rust", "summary": "A first look at how to implement an OAuth authentication / authorization exchange in Rust.", "image": "https://francoisbest.com/posts/2019/strava-auth-cli-in-rust/opengraph-image-2gs6w5.jpg", "date_modified": "2019-01-15T00:00:00.000Z", "date_published": "2019-01-15T00:00:00.000Z", "author": { "name": "François Best", "url": "https://francoisbest.com/" }, "tags": [ "rust", "strava" ] } ] }