56,966 blogs · [ { "id": "01a0cdc6-9fe7-72a7-bf5b-db931feb737e", "title": "Build a contact form with Astro and Resend", "url": "https://philna.sh/blog/2026/07/23/build-contact-form-astro-resend/", "published_at": "2026-09-21T00:00:00+00:00" }, { "id": "01a0b68b-4ce4-7114-95a9-6bda53a6e68b", "title": "Phil Nash", "url": "https://philna.sh", "published_at": "2026-09-07T05:20:44+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4a622670e", "title": "Generate AI-powered related links for your Astro content", "url": "https://philna.sh/blog/2026/06/22/ai-powered-related-content-astro-site/", "published_at": "2026-05-27T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4a7217d93", "title": "I built a new app and I don't know how I feel about it", "url": "https://philna.sh/blog/2026/05/25/i-built-a-new-app-and-i-dont-know-how-i-feel-about-it/", "published_at": "2026-05-25T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4a7d330d7", "title": "5 quick tips for giving better presentations", "url": "https://philna.sh/blog/2026/03/05/talking-tips/", "published_at": "2026-03-05T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4a8615c1b", "title": "Things you need to do for npm trusted publishing to work", "url": "https://philna.sh/blog/2026/01/28/trusted-publishing-npm/", "published_at": "2026-01-31T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4a9395360", "title": "How wrong can a JavaScript Date calculation go?", "url": "https://philna.sh/blog/2026/01/11/javascript-date-calculation/", "published_at": "2026-01-11T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4aa2a5177", "title": "How to Create Vector Embeddings in Python", "url": "https://philna.sh/blog/2025/04/08/how-to-create-vector-embeddings-in-python/", "published_at": "2025-04-08T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4aab0a5ea", "title": "Troubles with multipart form data and fetch in Node.js", "url": "https://philna.sh/blog/2025/01/14/troubles-with-multipart-form-data-fetch-node-js/", "published_at": "2025-01-14T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4ab91bb98", "title": "Clean up HTML Content for Retrieval-Augmented Generation with Readability.js", "url": "https://philna.sh/blog/2025/01/09/html-content-retrieval-augmented-generation-readability-js/", "published_at": "2025-01-09T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4abf4ba74", "title": "Shallow clones versus structured clones", "url": "https://philna.sh/blog/2024/12/30/shallow-clones-versus-structured-clones/", "published_at": "2024-12-30T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4ac6af945", "title": "How to Create Vector Embeddings in Node.js", "url": "https://philna.sh/blog/2024/09/25/how-to-create-vector-embeddings-in-node-js/", "published_at": "2024-09-25T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4ac9ce211", "title": "How to Chunk Text in JavaScript for Your RAG Application", "url": "https://philna.sh/blog/2024/09/18/how-to-chunk-text-in-javascript-for-rag-applications/", "published_at": "2024-09-18T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4acfc0229", "title": "How Using Fetch with the Streams API Gets You Faster UX with GenAI Apps", "url": "https://philna.sh/blog/2024/08/22/fetch-streams-api-for-faster-ux-generative-ai-apps/", "published_at": "2024-08-22T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4ad8e82b3", "title": "JavaScript is getting array grouping methods", "url": "https://philna.sh/blog/2023/09/14/javascript-array-grouping-methods/", "published_at": "2023-09-14T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4adb11c49", "title": "Node.js includes built-in support for .env files", "url": "https://philna.sh/blog/2023/09/05/nodejs-supports-dotenv/", "published_at": "2023-09-05T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4aea368ef", "title": "Easy and accessible pagination links for your Astro collections", "url": "https://philna.sh/blog/2023/07/13/easy-and-accessible-pagination-links-for-your-astro-collections/", "published_at": "2023-07-13T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4af89cb49", "title": "Build bots on Bluesky with Node.js and GitHub Actions", "url": "https://philna.sh/blog/2023/05/01/build-bots-on-bluesky-with-typescript/", "published_at": "2023-05-16T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b06ed5f9", "title": "Create a CLI Chatbot with the ChatGPT API and Node.js", "url": "https://philna.sh/blog/2023/03/13/create-a-cli-chatbot-with-chatgpt-api-and-node-js/", "published_at": "2023-03-13T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b0776745", "title": "The yaml document from hell — JavaScript edition", "url": "https://philna.sh/blog/2023/02/02/yaml-document-from-hell-javascript-edition/", "published_at": "2023-02-02T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b1571a9d", "title": "Better two factor authentication experiences with WebOTP", "url": "https://philna.sh/blog/2022/12/07/better-two-factor-authentication-experiences-with-web-otp/", "published_at": "2022-12-07T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b1d29412", "title": "Alias your Mastodon username to your own domain with Jekyll", "url": "https://philna.sh/blog/2022/11/23/alias-your-mastodon-username-to-your-own-domain-with-jekyll/", "published_at": "2022-11-23T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b20e0302", "title": "How to use the Bitly API in Ruby", "url": "https://philna.sh/blog/2022/11/09/how-to-use-the-bitly-api-in-ruby/", "published_at": "2022-11-09T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b24bfdef", "title": "Don't ever write your own function to parse URL parameters", "url": "https://philna.sh/blog/2021/04/11/dont-ever-write-your-own-function-to-parse-url-parameters/", "published_at": "2021-04-11T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b3132ecb", "title": "Restart your app and not your tunnel with ngrok and nodemon", "url": "https://philna.sh/blog/2021/03/15/restart-app-not-tunnel-ngrok-nodemon/", "published_at": "2021-03-15T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b3e720c1", "title": "How to display dates in your user's time zone with the Intl API", "url": "https://philna.sh/blog/2021/02/22/display-dates-in-your-users-time-zone/", "published_at": "2021-02-22T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b49b5af2", "title": "How to stream file downloads in Node.js with Got", "url": "https://philna.sh/blog/2020/08/06/how-to-stream-file-downloads-in-node-js-with-got/", "published_at": "2020-08-06T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b4c49b12", "title": "I built a VSCode extension: ngrok for VSCode", "url": "https://philna.sh/blog/2020/04/14/ngrok-for-vscode/", "published_at": "2020-04-14T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b53aaf11", "title": "Making a responsive Twitch Embed", "url": "https://philna.sh/blog/2020/03/23/responsive-twitch-embed/", "published_at": "2020-03-23T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b580695c", "title": "The story of a mildly popular Ruby gem", "url": "https://philna.sh/blog/2020/03/17/the-story-of-a-midly-popular-ruby-gem/", "published_at": "2020-03-17T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b6751d33", "title": "Mistakes I've made treating file paths as strings", "url": "https://philna.sh/blog/2020/03/04/mistakes-treating-paths-as-strings/", "published_at": "2020-03-04T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b75a22dd", "title": "How to find CFPs for developer conferences", "url": "https://philna.sh/blog/2020/01/29/how-to-find-cfps-for-developer-conferences/", "published_at": "2020-01-29T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b836782c", "title": "Testing signed and encrypted cookies in Rails", "url": "https://philna.sh/blog/2020/01/15/test-signed-cookies-in-rails/", "published_at": "2020-01-15T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b86c2f38", "title": "How not to sort an array in JavaScript", "url": "https://philna.sh/blog/2019/08/26/how-not-to-sort-an-array-in-javascript/", "published_at": "2019-08-26T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b8ecefc4", "title": "How to start a Node.js project", "url": "https://philna.sh/blog/2019/01/10/how-to-start-a-node-js-project/", "published_at": "2019-01-10T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b95ba0de", "title": "2018 in review", "url": "https://philna.sh/blog/2019/01/03/2018-in-review/", "published_at": "2019-01-03T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4b9cec673", "title": "Service workers: beware Safari's range request", "url": "https://philna.sh/blog/2018/10/23/service-workers-beware-safaris-range-request/", "published_at": "2018-10-23T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4ba3ec15b", "title": "Techniques for animating on the canvas in React", "url": "https://philna.sh/blog/2018/09/27/techniques-for-animating-on-the-canvas-in-react/", "published_at": "2018-09-27T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bb1c9b1d", "title": "Implementing one time passwords in Crystal", "url": "https://philna.sh/blog/2018/09/04/implementing-one-time-passwords-in-crystal/", "published_at": "2018-09-04T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bbf5bcb8", "title": "Git commands to keep a fork up to date", "url": "https://philna.sh/blog/2018/08/21/git-commands-to-keep-a-fork-up-to-date/", "published_at": "2018-08-21T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bc01a2bc", "title": "Spring clean your dev machine", "url": "https://philna.sh/blog/2018/05/27/spring-clean-your-dev-machine/", "published_at": "2018-05-27T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bc24d370", "title": "Use the web share API easily with web components", "url": "https://philna.sh/blog/2018/04/25/web-share-api-with-web-components/", "published_at": "2018-04-25T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bd0a8f59", "title": "CSS: select first-of-class with the subsequent sibling combinator", "url": "https://philna.sh/blog/2018/03/18/css-first-of-class/", "published_at": "2018-03-18T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bd651e86", "title": "gzip a file in Ruby", "url": "https://philna.sh/blog/2018/02/25/gzip-file-ruby/", "published_at": "2018-02-25T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bda5c293", "title": "Permissions on the web suck", "url": "https://philna.sh/blog/2018/01/08/permissions-on-the-web-suck/", "published_at": "2018-01-08T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4bdc8193f", "title": "Two tests you should run against your Ruby project now", "url": "https://philna.sh/blog/2017/07/12/two-tests-you-should-run-against-your-ruby-project-now/", "published_at": "2017-07-12T00:00:00+00:00" }, { "id": "01a087c2-2289-700f-afdd-59c4beb321b0", "title": "Experimenting with the background fetch API", "url": "https://philna.sh/blog/2017/07/04/experimenting-with-the-background-fetch-api/", "published_at": "2017-07-04T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d70323f38142", "title": "Speed up bundle install with this one trick", "url": "https://philna.sh/blog/2017/06/12/speed-up-bundle-install-with-this-one-trick/", "published_at": "2017-06-12T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d70324e160cb", "title": "Always install Bundler alongside Ruby with rbenv", "url": "https://philna.sh/blog/2017/03/22/always-install-bundler-alongside-ruby-with-rbenv/", "published_at": "2017-03-22T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d703257cca3a", "title": "The web share API", "url": "https://philna.sh/blog/2017/03/14/the-web-share-api/", "published_at": "2017-03-14T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032602e3d0", "title": "Doing things wrong", "url": "https://philna.sh/blog/2017/02/13/doing-things-wrong/", "published_at": "2017-02-13T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d703265adeb9", "title": "A toast to ES2015 destructuring", "url": "https://philna.sh/blog/2017/02/09/toast-to-es2015-destructuring/", "published_at": "2017-02-09T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d703271f6aa6", "title": "On fixing a favicon", "url": "https://philna.sh/blog/2017/01/27/on-fixing-a-favicon/", "published_at": "2017-01-27T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d70327fa820a", "title": "Dev Tools Tricks: Store objects and elements as variables in the console", "url": "https://philna.sh/blog/2017/01/12/dev-tools-tricks-store-objects-and-elements-as-variables-in-the-console/", "published_at": "2017-01-12T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d703284c29b5", "title": "Git back to the future", "url": "https://philna.sh/blog/2017/01/04/git-back-to-the-future/", "published_at": "2017-01-04T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d703291f8849", "title": "A community offers to help", "url": "https://philna.sh/blog/2016/09/05/a-community-offers-to-help/", "published_at": "2016-09-05T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d70329cbb9a6", "title": "Install a service worker declaratively", "url": "https://philna.sh/blog/2016/08/17/install-a-service-worker-declaratively/", "published_at": "2016-08-17T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032a5f275c", "title": "August is iOS month", "url": "https://philna.sh/blog/2016/08/01/august-is-ios-month/", "published_at": "2016-08-01T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032ae6dde1", "title": "Creating an asset pipeline with Jekyll-Assets", "url": "https://philna.sh/blog/2016/06/28/asset-pipelines-with-jekyll-assets/", "published_at": "2016-06-28T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032bc1a053", "title": "Critique my Swift on Exercism", "url": "https://philna.sh/blog/2016/06/20/critique-my-swift-on-exercism/", "published_at": "2016-06-20T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032c2149d6", "title": "The surprise multipart/form-data", "url": "https://philna.sh/blog/2016/06/13/the-surprise-multipart-form-data/", "published_at": "2016-06-13T00:00:00+00:00" }, { "id": "01a087c2-228a-70b6-a88f-d7032cdc95f2", "title": "This site isn't finished", "url": "https://philna.sh/blog/2016/05/18/this-site-isnt-finished/", "published_at": "2016-05-18T00:00:00+00:00" } ] posts Claim your blog
Back to Blog | Phil Nash
Blog · corpus.blog/blogs/philna.sh/posts

Blog | Phil Nash

philna.sh

2026

2025

2024

2023

2022

2021

2020

2019

2018

2017

2016