From d1e4db163726a179891f7a79ca5645b1bf3f0f42 Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 10:16:46 -0400 Subject: [PATCH 1/8] chore: added Nick Taylor's blog posts --- ...e-your-repository-with-code-owners-4clg.md | 56 ++++ ...-actions-a-maintainers-best-friend-488n.md | 104 ++++++++ ...t-productivity-with-the-github-cli-2mne.md | 232 +++++++++++++++++ ...-vitest-for-your-react-application-1b75.md | 202 +++++++++++++++ ...-the-native-browser-dialog-element-1nhn.md | 85 ++++++ ...ndeniable-goodness-of-tailwind-css-4doc.md | 190 ++++++++++++++ ...le-with-you-an-intro-to-middleware-1gjo.md | 243 ++++++++++++++++++ ...-lost-my-submit-button-got-it-back-5b91.md | 77 ++++++ ...g-react-and-netlify-edge-functions-563a.md | 110 ++++++++ blog/authors.yml | 6 + 10 files changed, 1305 insertions(+) create mode 100644 blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md create mode 100644 blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md create mode 100644 blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md create mode 100644 blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md create mode 100644 blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md create mode 100644 blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md create mode 100644 blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md create mode 100644 blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md create mode 100644 blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md diff --git a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md new file mode 100644 index 00000000..140b65e2 --- /dev/null +++ b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md @@ -0,0 +1,56 @@ +--- +title: "Supercharge your Repository with Code Owners" +tags:[] +authors: nickytonline +slug: 2023-09-21-supercharge-your-repository-with-code-owners-4clg +description: "As a maintainer of a repository, it’s in your best interest to automate processes as much as..." +--- + +As a maintainer of a repository, it’s in your best interest to automate processes as much as possible. The [CODEOWNERS file](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) is one of those tools to help with automating processes. + +I decided to write a post about the CODEOWNERS file after reading this comment from one of our awesome [Octerns](https://education.github.com/students/octernships), Divyansh (@diivi), in a [pull request (PR) where I added the file](https://github.com/open-sauced/ai/pull/268). + +![GitHub user diivi commenting that they weren't aware of the CODEOWNERS feature](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hpkmx91y66efqaa62umv.png) + +A CODEOWNERS file in GitHub is a special file used to specify who reviews and maintains specific files or directories in a repository. It helps with identifying code ownership and who should be notified when pull requests are made to those repositories. + +For example, in this particular CODEOWNERS file there is the `@open-sauced/engineering` team. + + +![A CODEOWNERS file with one team in it, @open-sauced/engineering](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mg69ouah43ks9x3e0zh.png) + +When someone creates a PR for that repository, that team is automatically added as a reviewer. + +![Reviewers for a PR in the GitHub UI including the @open-sauced/engineering team](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hsevadw9yedmewgb0gya.png) + +This is really handy because you don’t need to go and manually add reviewers, and when it’s a PR from an external contributor, they can’t add reviewers so this is super useful for them and can avoid comments like, “Can someone review my PR?” + +Another nice feature of the CODEOWNERS file is that it can be used as part of [branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). + +To enable this, go to the *Protect matching branches* section of a branch protection rule, and ensure the *Require review from Code Owners* option is checked. + +![GitHub PR review file where the UI says that the CODEOWNERS file is valid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b85pfint60i7h5ph9eoi.png) + +One other thing to note is if you have permanent branches aside from `main`, like `beta`, `dev`, or whatever your team calls it, they can have different individuals and teams in those branches CODEOWNERS file. + +## How to add a CODEOWNERS file to your project + +The CODEOWNERS file is a special file that can reside in the root directory, in the `.github` directory or the `docs` directory (if you have one). + +The `.github` folder might not exist in your project if you haven’t added other GitHub automated processes like [GitHub Actions](https://github.com/features/actions), [pull request templates](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository), or [issue templates](https://dev.to/opensauced/how-to-create-a-good-pull-request-template-and-why-you-should-add-gifs-4i0l). + +Also note, GitHub looks for the first CODEOWNERS file it finds, searching first in the root directory, then the `.github` directory, and finally, the `docs` directory (if it exists). + +You can add individual GitHub users, [a team](https://docs.github.com/en/organizations/organizing-members-into-teams/creating-a-team), or a combination of them to a CODEOWNERS file. + +![A CODEOWNERS file with teams an individuals in it](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqjiucgu564d6dx5n89s.png) + +A nice feature of adding or making changes to a CODEOWNERS file in a pull request is that GitHub validates it, letting you know if you are adding a non-existent user or team. + +![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/icix62kg1avsjy54enu2.png) + +If you don’t already have a [CODEOWNERS file](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) file in your repository, I encourage you to add one. Let us know if you have any questions about this or other maintainer-related issues. + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md new file mode 100644 index 00000000..566b50a2 --- /dev/null +++ b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md @@ -0,0 +1,104 @@ +--- +title: "GitHub Actions: A Maintainer's Best Friend" +tags:[] +authors: nickytonline +slug: 2023-10-31-github-actions-a-maintainers-best-friend-488n +description: "As developers, it’s in our best interest to automate things. The less we have to do in a manual way,..." +--- + +As developers, it’s in our best interest to automate things. The less we have to do in a manual way, the better. As soon as manual intervention is required, there is potential for failure or a mishap. Aside from that, it’s your time as a maintainer that could be spent elsewhere. + +If you host your code on GitHub, besides scripts to automate certain actions, you can also leverage the huge ecosystem of [GitHub +Actions](https://github.com/features/actions). + +## Practical Examples + +Let’s look at some practical examples of GitHub actions helping maintainers. + +### peter-evans/create-or-update-comment + +If someone opens an issue on your repository, you could respond with a personal message saying thank you, but those keystrokes are probably better suited for other things. Automate a message reply instead, thanking the community member for creating the issue and mentioning you will look into it. An automated message to the issue opener is friendly, even if it’s automated. + +A great GitHub action for this is Peter Evans’ [Create or Update Comment](https://github.com/peter-evans/create-or-update-comment) action. + +It’s used in the app repository for OpenSauced. Here’s [how we have it configured](https://github.com/open-sauced/app/blob/beta/.github/workflows/issue.yml). + +When a new issue is opened, an issue responds with the following: + +![Automated comment when an issue is created in the OpenSauced App repository that says "Thanks for the issue, our team will look into it as soon as possible! If you would like to work on this issue, please wait for us to decide if it's ready. The issue will be ready to work on once we remove the "needs triage" label. To claim an issue that does not have the "needs triage" label, please leave a comment that says ".take". If you have any questions, please reach out to us on Discord or follow up on the issue itself. For full info on how to contribute, please check out our contributors guide."](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y9zucj40s8ub6jiacrl3.png) + +### bdougie/take-action + +My coworker bdougie (@bdougieyo) created the [take Github action](https://github.com/bdougie/take-action). It allows external contributors to self-assign issues by typing `.take` into a comment of an issue. This removes the burden of a bit of back and forth between contributors and maintainers. + + +[![OpenSauced contributor itskish0re self assigning an issue by using the .take command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh9gjzo8aiwleqqr7qhe.png)](https://github.com/open-sauced/app/issues/2017#issuecomment-1785492904) + +Of course, we don’t want external contributors self-assigning any issue they want. The take action also has the concept of blocking labels. For example, if an issue has a `👀 needs triage` label, we can add this label to a list of blocking labels. + + +[![Someone trying to self-assign an issue when there are blocking labels on the issue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w52j0puh47kpgg27clnd.png)](https://github.com/open-sauced/app/issues/1952#issuecomment-1772176129) + +### balazsorban44/nissuer + +Another action that came onto my radar a couple of days ago was thanks to [styfle](https://twitter.com/styfle). Although I haven’t used it yet, [nissuer](https://github.com/balazsorban44/nissuer) looks like a great utility belt GitHub action for maintainers. The Next.js repository uses it, so I'm sure it brings lots of value to a maintainer. + +I love this note they added in the README. + +> NOTE: Developers are coming to your project with all sorts of backgrounds/skill levels or understanding of the open-source world. Show empathy while using this action. 💚 We recommend adding comments that not only dismiss unhelpful issues/comments, but educate the user on how to be more helpful in the future. + +### Bespoke Actions + +Don’t see a GitHub action for what you need? Create your own. You can even build your own by composing it from existing GitHub actions. Here's an example of a [bespoke workflow I use for pulling in my latest video content from YouTube](https://github.com/nickytonline/www.nickyt.co/blob/main/.github/workflows/get-latest-videos.yml) to my blog. + +I'm using some GitHub Actions, a custom script that leverages the [GitHub CLI](https://cli.github.com/) and magic. + +```yaml +{% raw %} +name: Get latest videos +on: + schedule: + # Everyday at midnight UTC + - cron: '0 0 * * *' + workflow_dispatch: + +jobs: + update_profile_data: + name: Get latest videos + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v3 + with: + node-version: 18 + - name: Get latest videos + run: | + npm install + node bin/udpdateStreamingPage.js + - name: Setup git config + run: | + git config user.name 'token-generator-app[bot]' + git config user.email '82042599+token-generator-app[bot]@users.noreply.github.com' + - name: PR for Videos + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ./bin/pr-videos.sh +{% endraw %} +``` + +You can see the results on the [streaming page of my site](https://www.nickyt.co/pages/streaming/). + +The post is a bit out of date, but I discuss more in depth the automations for my website in + +https://dev.to/nickytonline/my-eleventy-meetup-talk-3b2p + +## Conclusion + +These are just examples of tasks you can automate, and if you’re using GitHub, there is a huge ecosystem of GitHub actions to help with your automation goals. + +What are some GitHub actions that you’ve leveraged in your projects? Share them in the comments. + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md new file mode 100644 index 00000000..f626b5ce --- /dev/null +++ b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md @@ -0,0 +1,232 @@ +--- +title: "Boost productivity with the GitHub CLI" +tags:[] +authors: nickytonline +slug: 2023-11-14-boost-productivity-with-the-github-cli-2mne +description: "The GitHub CLI is an indispensable tool as a project maintainer or contributor on GitHub. It can..." +--- + +The [GitHub CLI](https://cli.github.com/) is an indispensable tool as a project maintainer or contributor on GitHub. It can boost your productivity when getting things done. + +![Someone's head exploding like the exploding head emoji](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xdqnv6j7m6joilp4qdjj.png) + +The day my brain exploded was when I discovered (spoilers) that you could create a pull request using the GitHub CLI. + +Let's get started! + +## Install the GitHub CLI + +Head on over to the [installation docs to get the GitHub CLI set up](https://cli.github.com/). There are installers for Linux, Windows, and macOS. + +## Log In to GitHub via the GitHub CLI + +You're up and running but if you try to run any commands, you're going to be prompted to log in, so let's do that first. + +![Trying to execute a GitHub CLI command when not logged in results in the following message, To get started with GitHub CLI, please run: gh auth login +Alternatively, populate the GH_TOKEN environment variable with a GitHub API authentication token.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4b4y1css355bufj5aivp.png) + +To log in to GitHub via the GitHub CLI, run `gh auth login`. + +![GitHub CLI gh auth login command running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/chype8akpqm392qfzs3d.png) + +You'll be given two options for logging in. GitHub.com or GitHub Enterprise Server. In most cases, unless your company uses GitHub Enterprise Server, you'll select the default, GitHub.com. + +Next, you'll be asked which protocol to log in with. The default is HTTPS, but I recommend SSH. To learn more about configuring GitHub with SSH, see [Connecting to GitHub with SSH](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). + +### Login via SSH + +![The GitHub CLI prompting with the following, What is your preferred protocol for Git operations? Use arrows to move, type to filter HTTPS or SSH](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wo07iigwynxvqyuil64w.png) + +Next, it will ask you to publish your public key to GitHub. This is safe to do and you can proceed. + +![GitHub CLI prompting to upload your public SSH key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ilooaemam9dgcc756k4k.png) + +It will prompt for a title for the key. Using the default value of "GitHub CLI" is fine. + +![The GitHub CLI prompting for a title for the SSH public key](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lnappw8c5adv3pf0ic9o.png) + +### Login via HTTPS + +If you choose HTTPS, you'll be asked to authenticate Git with your GitHub credentials. + +![The GitHub CLI prompting to log in with your GitHub credentials](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c4bfodupmj8oba15ocj1.png) + +Press ENTER to continue. + +### Finishing Login Process + +Next, you'll be prompted to log in via the browser or a token. To be honest, I've never used a token at this step. I always log in via the browser. If you have a token, go for it. + +![The GitHub CLI prompting to log in to GitHub via a browser or a token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fqu5mwmyc0lbl6ckkgr0.png) + +You'll be given a code in the CLI that you need to copy (changed to `some code` in my screenshot) and then press ENTER to log in via the browser. + +![The GitHub CLI outputting a code you need to copy to finish the login process](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgimazlzyobj7kgnwaa6.png) + +Paste or type in the code and press the Continue button. + +![GitHub.com device activation screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/acbc8cs604tjtiq8cfmm.png) + +Next, you'll be asked to Authorize GitHub. Click the Authorize GitHub button. + +![The authorize GitHub CLI screen on github.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wa8xzio1a5f9wsysuw9.png) + +At this point, depending on how you have the security of your account set up, you may be asked to log in via the GitHub mobile app. + +![Multifactor confirm access screen using GitHub mobile](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ieoj4z63o8x071dq6n2u.png) + +Log in via the GitHub mobile app or other multifactor authentication methods you have set up. + +At this point, you should be all set up. + +![GitHub.com confirmation screen that the device was connected successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7i87s3jjk3we0fzwxzv1.png) + +And if you go back to the command line, you should see something similar to this. + +![GitHub CLI confirming that you are logged in](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/furcqwnfulnyksu9s8gx.png) + +## Useful Commands + +Let's walk through a couple of commands I use every day, and then we'll check out some other useful ones that I use less frequently. + +## Reviewing a Pull Request + +As a maintainer of a project, you will definitely be reviewing PRs (for external contributors or team members). Before we had the GitHub CLI, I always had to Google how to get someone's PR on my local machine with Git. I forgot all the time, so, at one point, I made a Git alias for it. The command looks like this, `git fetch origin pull/pr_number/head:name_of_branch`. So if I was going to review pull request 1234, the command would look something like this, `git fetch origin pull/1234/head:pr-1234`. You can call the branch whatever you want. I used to name it `pr-` with the number of the PR. + +None of that is necessary these days. With the GitHub CLI, all you need to do is `cd` into the project directory in your terminal and then run `gh co pr-number`, e.g. `gh co 2062` + +Here it is in action for a recent pull request I reviewed for the [OpenSauced app repository](https://github.com/open-sauced/app/). + +![Running the GitHub CLI checkout command, gh co 2062, to check out pull request 2062 from a repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7zo4ef9ckl76g0dtdd43.gif) + +## Creating a Pull Request + +Before the GitHub CLI, I used to push my branch to GitHub, and then I would go to the repository's page on GitHub.com and create a pull request from there. + +![A repository's main page on github.com with a call to action to create a pull request from a branch pushed to github.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mt6fqypoarfmu7er8c3t.png) + +Although that works, when I discovered that the GitHub CLI could do this, I was blown away. All you need to do is run [gh pr create](https://cli.github.com/manual/gh_pr_create) from the command line, assuming you're currently on the branch of the repo you want to associate with the pull request. You can provide additional arguments, e.g. `gh pr create --draft` or the shorter version `gh pr create -d`, but typically, when I'm creating a PR, I go through the steps in the CLI and continue the final step in the browser. It's a preference, so do what works best for you. + +Here's me creating a new test PR. + +![Running the GitHub CLI create pull request command, gh pr create, to create a new pull request for a repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcmmnrwl2stvg9h5rxuy.gif) + +## Creating or Pushing a New Repository to GitHub + +In the past, I always used to create a new repository from GitHub.com. + +![User menu on GitHub.com open with the menu item New Repository highlighted](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u65e1ghs25onuatof93o.png) + +I'm sure there is a way to create a repository on GitHub from the command line, but I never bothered to learn it, and now I don't really need to thanks to the GitHub CLI. + +### Create a Repository from Scratch + +To create a repository from scratch, run [gh repo create](https://cli.github.com/manual/gh_repo_create) from the command line. + +![The GitHub CLI prompting user what to do with Create a new repository from scratch selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/57cf58p1s48mzsa743zg.png) + +Select `Create a new repository on GitHub from scratch` and press the ENTER key. + +Next, you'll be prompted to name the repository, e.g. `test`. + +![The GitHub CLI prompting for a name for the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wqvv4u62musbve5c8dq.png) + +Next, choose the repository owner. If you're a part of one or more GitHub organizations, they will appear in the list. For our example, I will go with my own account, `nickytonline` as the repository owner. + +![The GitHub CLI prompting for a repository owner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tz8knqytjiqvlu5ll974.png) + +Add a description for the repository, e.g. `test` or leave it blank. It's not required. + +![The GitHub CLI prompting for a description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nbouh9hz8w6gcyzba8sr.png) + +Next, set the visibility of the repository. It can be public (default), private, or internal. + +![The GitHub CLI prompting for the visibility of the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfjbrw0o9okqoh7h9rie.png) + +Since this is a test repository, I'm going to set it to private. + +![The GitHub CLI running with privacy selected for the visibility](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/20lt2a8mwt52qaank5e2.png) + +Next, you'll be asked to create a README file. Type `y` and press the ENTER key. + +![The GitHub CLI prompting to create a README](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtn95z644i4hzvs1ok44.png) + +You'll be prompted to add a gitignore file. Type `y` and press the ENTER key. + +![The GitHub CLI prompting for to create a gitignore file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rf7p7j75fyb8qmw543ez.png) + +Next, choose the language that will best reflect the contents of the gitignore file. I do a lot of JavaScript, Node.js and TypeScript, so I'm going to choose Node. + +![Node selected as the language for the gitignore template](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nxf3ntackdyr2bh0ujfh.png) + +You'll be asked to add a license. Type `y` and press the ENTER key. + +![The GitHub CLI prompting to create a license](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufrcfi5oaanzbnyp5d85.png) + +Choose the license that makes the most sense for the project you're creating. For the purposes of this blog post, I'll choose the MIT license. + +![MIT License selected in the GitHub CLI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys75il7rmt51wvm40fk2.png) + +A quick check will ask if you want to create the repository on GitHub. Type `y` and press the ENTER key to proceed. + +![The GitHub CLI summarizing all the selections made, prompting the user to create the repository on GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fek4c3bxo06ul695g5v2.png) + +Next, you'll be asked if you want to clone the repository locally. + +![The GitHub CLI asking the user if they want to clone the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cu0ea66kzsji32qfh0j.png) + +Type `y` and press the ENTER key to proceed. + +The new repository is on GitHub.com now and has been cloned on your machine. + +### Push an Existing Local Repository to GitHub + +To push an existing local repository to GitHub, run [gh repo create](https://cli.github.com/manual/gh_repo_create) from the command line. + +![The GitHub CLI, with the Push an existing local repository to GitHub option selected](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bdglfgwcshd21yk116qn.png) + +You'll be prompted for the path to the local repository. It defaults to `.`, the current directory. If, for some reason, you ran the command outside your local git repository folder, specify the folder to your repository. + +![The GitHub CLI prompting to enter the path to a local repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqvhfmobqsk8odltby91.png) + +Next, you'll be asked to name the repository. By default, it will use the name of the folder the local repository resides in, e.g. `test`. Change it if it makes sense to. + +![The GitHub CLI, prompting a user to enter a repository name](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rhjs3n4xgcznhdy5d303.png) + +Next up, you're prompted to select a repository owner. By default, it's your user, e.g. `nickytonlin`, but you can select any organizations you're a part of as well. + +![The GitHub CLI prompting for a repository owner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m5mirrkm3g1ifyzted5n.png) + +Next, you'll be asked to add a description. You can add one or leave it blank. It's up to you. + +![The GitHub CLI prompting for a description for the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v6pttkuwhk15u8namc96.png) + +Next, you'll be asked to set the visibility of the repository. It can be public (default), private, or internal. + +![The GitHub CLI prompting to select the visibility of the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/83hk4addzxsefe3osund.png) + +Next, you'll be asked if you want to set a remote. Press enter to say yes (the default) + +![The GitHub CLI prompting to add a remote for the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bh42zxnalpa5vcngoi4d.png) + +You'll be asked what the new remote should be called. Press the ENTER to accept the default name of `origin`. The GitHub CLI notifies you that the remote has been added, e.g. `git@github.com:nickytonline/test.git` + +![The GitHub CLI prompting to name the remote](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whiw5y2pjp1yfylug7nt.png) + +And finally, you'll be asked if you want to push the commits from the current branch to the `origin` remote. Press the ENTER key to push the commits, and you're done! + +![The GitHub CLI pushing the current branch to the origin remote on GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/unodjzvt3r8shsehhfyu.png) + +## Conclusion + +For myself, the GitHub CLI has become a game changer in my day-to-day workflow. I literally use it every day, well, work days. 😎 + +From creating a new repository, to pulling down a pull request (PR) to creating a PR and more, the GitHub CLI has become indispensable to me. + +There is a [whole other set of commands](https://cli.github.com/manual/) available in the GitHub CLI that I encourage you to check out and that, to be honest, even I should explore further. + +I realize not everyone is comfortable with the command line, but I think that if you give the GitHub CLI a chance, you may grow to love it. As always, though, use the tools that make you the most productive. + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md new file mode 100644 index 00000000..60ca11cb --- /dev/null +++ b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md @@ -0,0 +1,202 @@ +--- +title: "Migrating from Jest to Vitest for your React Application" +tags:[] +authors: nickytonline +slug: 2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75 +description: "Are you looking to migrate from Jest to Vitest for your React application? Look no further. I..." +--- + +Are you looking to migrate from [Jest](https://jestjs.io) to [Vitest](https://vitest.dev) for your React application? Look no further. + +I recently migrated the OpenSauced app repository to Vitest. Here's the pull request if you're interested. + +https://github.com/open-sauced/app/pull/2296 + +## Why move from Jest to Vitest? + +Both Jest and Vitest are great testing frameworks, so why bother switching? + +Vitest supports [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) (ESM), [TypeScript](https://typescriptlang.org) out of the box. + +Jest requires additional setup for both, although there is [experimental support for ESM](https://jestjs.io/docs/ecmascript-modules). + +Vitest is also fast. Yes, it depends, but in general, it's faster. (See the [Vitest comparison with other test runners](https://vitest.dev/guide/comparisons.html#comparisons-with-other-test-runners)) + +![Neo fighting an agent in the Matrix movie with one hand](https://media.giphy.com/media/mSXSC0vivvygw/giphy.gif) + +If you're already using Vite in your project or the meta-framework you're using is based on Vite, using Vitest is a no-brainer as you're already in the Vite ecosystem. + +If your project isn't using Vite, e.g. Next.js, it's still a great move. + +Vitest makes it effortless to migrate from Jest. It supports the same [Jasmine](https://jasmine.github.io/) like API. + +**TLDR; You don't need to update existing tests, as it’s mostly a drop-in replacement for Jest.** + +Some other niceties are a default watch mode care of Vite instant Hot Module Reload (HMR). + +## Install Vitest + +The first thing you want to do is install Vitest. + +https://github.com/vitest-dev/vitest + +Run `npm install vitest -D` in the terminal to install Vitest as a dev dependency. + +Next up, create a `vitest.config.ts` file in the root of your project. Even if you're not using TypeScript, name it `vitest.config.ts`. + +In that file, add the following code and save it. + +```javascript +{% raw %} +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + test: { + // some paths to the files that are test files + include: ["./**/*.test.ts", "./**/*.test.tsx"], + }, +}); +{% endraw %} +``` + +You can explicitly import `describe`, `it`/`test`, `expect` or you can have it work like in Jest where they're all globals. All you need to do is set `globals` to `true` in the Vitest configuration. + +```diff +{% raw %} + import { defineConfig } from "vite"; + + // https://vitejs.dev/config/ + export default defineConfig({ + test: { + include: ["./**/*.test.ts", "./**/*.test.tsx"], ++ globals: true, + }, + }); +{% endraw %} +``` + +## Using Vitest with React + +At [OpenSauced](https://dev.to/opensauced), we're using Next.js to build out the [main application](https://app.opensauced.pizza). + +Vitest is based off Vite which supports React via their plugin ecosystem, so you'll need to install the Vite React plugin to get React support. + +Run `npm install @vitejs/plugin-react -D` to install the plugin as a dev dependency. + +Update the Vitest configuration to add the React plugin. + +```diff +{% raw %} + import { defineConfig } from "vite"; + import react from "@vitejs/plugin-react"; + + // https://vitejs.dev/config/ + export default defineConfig({ ++ plugins: [react()], + test: { + include: ["./**/*.test.ts", "./**/*.test.tsx"], + globals: true, + }, + }); +{% endraw %} +``` + +## React Testing Library + +If you happen to be using [React Testing Library](https://testing-library.com/docs/react-testing-library/intro/) in your project, you'll need to keep the [jsdom](https://github.com/jsdom/jsdom) dev dependency installed. + +Next, add `jsdom` to your Vitest configuration. + +```diff +{% raw %} + import { defineConfig } from "vite"; + import react from "@vitejs/plugin-react"; + + // https://vitejs.dev/config/ + export default defineConfig({ + plugins: [react()], + test: { + include: ["./**/*.test.ts", "./**/*.test.tsx"], + globals: true, ++ environment: "jsdom", + }, + }); +{% endraw %} +``` + +## Aliases + +Your project might be using aliases for paths. For example, in the OpenSauced app repository, `components`, `lib`, and `img` are aliases to folders. + +If you need to [support aliases](https://vitest.dev/config/#alias), Vitest has you covered. + +Here's an example of supporting the above-mentioned aliases. + +```diff +{% raw %} + export default defineConfig({ + plugins: [react()], ++ resolve: { ++ alias: { ++ components: fileURLToPath(new URL("./components", import.meta.url)), ++ lib: fileURLToPath(new URL("./lib", import.meta.url)), ++ img: fileURLToPath(new URL("./img", import.meta.url)), ++ }, ++ }, + test: { + include: ["./**/*.test.ts", "./**/*.test.tsx"], + globals: true, + environment: "jsdom", + }, + }); +{% endraw %} +``` + +## TypeScript Types + +If you're using TypeScript, you can add the types for Vitest to the project. + +In your tsconfig.json file, add the types in the compiler options section of the TypeScript configuration file. + +```json +{% raw %} + { + "compilerOptions": { + // . .. other compiler options in your project ++ "types": ["vitest/globals"] + } + + // . .. other TypeScript configuration options in your project + } + +{% endraw %} +``` + +## Running Tests + +To run tests using Vitest, you can run `vitest`. By default, it will go into watch mode. If you only want to run the test suite once, e.g. for the CI/CD pipeline, run `vitest run`. + +## Removing Jest + +If your project is a TypeScript project, you probably have the types for Jest in your project. If you do, run the following to remove the Jest TypeScript types. + +```bash +{% raw %} +npm uninstall -D @types/jest +{% endraw %} +``` + +Uninstall Jest itself. + +```bash +{% raw %} +npm uninstall jest jest-environment-jsdom -D +{% endraw %} +``` + +And that's it! Happy testing! + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md new file mode 100644 index 00000000..e55a8c8d --- /dev/null +++ b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md @@ -0,0 +1,85 @@ +--- +title: "Unlocking the Power of HTML's Native Browser Dialog Element" +tags:[] +authors: nickytonline +slug: 2024-01-23-the-native-browser-dialog-element-1nhn +description: "All the major browsers now support the <dialog > element. Why add this HTML element? User land..." +--- + +All the major browsers now support the `` element. Why add this HTML element? User land code, code that developers write to fill in gaps of the browser, was doing similar things repeatedly, especially around focus trapping, and browser engines responded by adding this functionality directly in the browser. + +## Focus Trapping + +What is focus trapping? It's a feature where you do not want focus outside a specific element, and that element typically contains focusable elements. + +For example, a form in a modal to confirm an action: As a user uses the keyboard to navigate, they go to the next focusable element, e.g. a button. + +If they reach the last focusable element in the modal, without focus trapping, the focus would go to the next focusable element in the [document object model](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) (DOM). With focus trapping, you go from the last focusable back to the first focusable element in the parent element. + +In user land, popular packages like [focus-trap](https://www.npmjs.com/package/focus-trap) have enabled developers to incorporate focus trapping. + +## <dialog> for Modal Dialogs + +With the dialog element, you get this for free, although there is a gotcha. If you add a dialog element to the page with the [open](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#open) attribute set, the dialog element will become visible on the page; however, focus trapping will not work as you'd expect in a modal. + +From the [API documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog#open): + +> Note: While you can toggle between the open and closed states of non-modal dialog boxes by toggling the presence of the open attribute, this approach is not recommended. + +To get focus trapping working, the JavaScript API is required. You can display a modal on the screen by calling the [HTMLDialogElement showModal method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal). + +_Note that you'll need to [view this CodePen in full view](https://codepen.io/nickytonline/full/NWJvbPe) because, [for some reason, modal dialog focus trapping does not work in the CodePen editor view](https://x.com/nickytonline/status/1749655288221782110)._ + +https://codepen.io/nickytonline/pen/NWJvbPe + +Not only do you get focus trapping, you also get modal close functionality that people have come to expect via the Escape key. + +All of that is already amazing, but another common thing people were doing in user land was adding a background to block out users from interacting with the page. With the `` element, we can add a `::backdrop` pseudo-element that does this for you. All you need to do is style it. In the CodePen above, uncomment out this code in the CSS panel to see this in action. + +```css +{% raw %} +dialog::backdrop { + background-color: purple; + opacity: 0.55; + filter: blur(100px); +} +{% endraw %} +``` + +## <dialog> for Non-Modal Dialogs + +The structure of a non-modal dialog element is the same as a modal dialog. The main difference is to show a non-modal dialog, you need to call the [HTMLDialogElement show method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/show). + +With a non-modal dialog, the user is not blocked from navigating the rest of the page, i.e. no focus trapping, and the Escape key will not automatically close the dialog. + +https://codepen.io/nickytonline/pen/ExMvNJw + +## Closing a dialog + +To close a dialog or modal, we can use the [HTMLDialogElement close method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close). + +```typescript +{% raw %} +const modal = document.querySelector("dialog"); + +// some button in the dialog that has a click event listener registered +modal.querySelector("button").addEventListener("click", () => { + modal.close(); +}); +{% endraw %} +``` + +## Wrapping up + +The web platform keeps getting better. It's great to see pain points in user land that had user solutions come natively to browser land. + +## References + +- [Using JavaScript to trap focus in an element](https://hidde.blog/using-javascript-to-trap-focus-in-an-element/) +- [MDN - <dialog>: The Dialog element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog) +- GitHub issue [ element should trap focus](https://github.com/w3c/html/issues/1514) from the _w3c/html_ repository. +- [Dialog - web.dev](https://web.dev/learn/html/dialog) + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md new file mode 100644 index 00000000..335bc806 --- /dev/null +++ b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md @@ -0,0 +1,190 @@ +--- +title: "Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS" +tags:[] +authors: nickytonline +slug: 2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc +description: "People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but..." +--- + +People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but I really don't want to get into all that. Head on over to Twitter if you want to waste some time. + +If you're pretty well versed with Tailwind, this article might not be for you, but who knows? Read on and maybe you'll learn something. + +I'm coming in with what, I think, is a fresh perspective. I'm using Tailwind for the first time professionally. Furthermore, I don't consider myself a CSS expert, but I think I have pretty solid CSS skills. + +I mention all this, to convey a sentiment, I've seen many people exhibit. You're using Tailwind because you don't understand CSS. I do understand CSS. + +So the first thing that I've seen when people say when they do not like Tailwind, is that it's not CSS, or it's inline CSS. This is completely false, even coming in as a newbie to Tailwind, all Tailwind is, at the end of the day, once it's compiled, is CSS utility classes. + +## Comparisons + +So let's look at some comparisons between Tailwind and "real" CSS. I'm going to put the vanilla CSS in a `style` tag, but you could also put it in a `.css` file and link it in the `head` of your HTML or however your application bundles CSS. This is just for the sake of comparison. + +### First Glances of Tailwind + +**Vanilla CSS** + +```html +{% raw %} + +
    +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
+{% endraw %} +``` + +**Tailwind** + +```html +{% raw %} +
    +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
+{% endraw %} +``` + +So the first thing someone might say is that Tailwind is repeating the `border` CSS class on a list item, `
  • `, instead of using a selector that can target the `li` DOM elements. This is true, but Tailwind allows you to create the equivalent of `.my-list li`. You can do the following: + +```html +{% raw %} +
      +
    • Item 1
    • +
    • Item 2
    • +
    • Item 3
    • +
    +{% endraw %} +``` + +This is probably where someone might say, "Well, now you're just writing inline CSS." This is also false. It will generate a [CSS rule](https://developer.mozilla.org/en-US/docs/Web/API/CSSRule) based on the `[&_li]:border` CSS class name. It will compile it to literal CSS that will generate an equivalent CSS rule comparable to the CSS rule for the `.mylist li` selector. + +In fact, this is what it compiles to. I've formatted it since it gets minified. + +```css +{% raw %} +.\[\&_li\]\:border li { + border-width: 1px; +} +{% endraw %} +``` + +You could make an argument that the "real" version looks nicer, but this isn't a strong argument, and you have CSS source maps if you open the browser dev tools. + +I'll say it here and repeat it again later. **Tailwind is a utility-first CSS framework. It's not inline CSS.** + +If you want to see an example of this in production grade code, check out a recent pull request (PR) of mine to the OpenSauced app repository. + +https://github.com/open-sauced/app/pull/2524 + +### Styling pseudo-elements + +What about something more complex like [pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)? Let's take the [::before pseudo-element for a spin](https://developer.mozilla.org/en-US/docs/Web/CSS/::before). + +**Vanilla CSS** + +```html +{% raw %} + +

    + OpenSauced is awesome! +

    +{% endraw %} +``` + +**Tailwind** + +```html +{% raw %} +

    + OpenSauced is awesome! +

    +{% endraw %} +``` + +Here's what it generates as CSS when Tailwind compiles that CSS class. + +```css +{% raw %} +.before\:content-\[attr\(data-inset-label\)\]:before{ + --tw-content:attr(data-inset-label); + content:var(--tw-content) +} +{% endraw %} +``` + +You could complain that that is one hell of a bloated CSS class name, but again, I don't think this is a colossal deal. + +If you want to see an example of this in production grade code, check out a recent PR of mine to the OpenSauced app repository. + +https://github.com/open-sauced/app/pull/2552 + +## Animations + +If you're looking to add animations, [Tailwind ships with plenty of useful animations](https://tailwindcss.com/docs/animation) and CSS classes to leverage them. + +Need a custom animation? You can do that as well. I won't go into it here, but here's a great post about [writing custom animations in Tailwind](https://blog.logrocket.com/creating-custom-animations-tailwind-css/). + +## Accessibility + +You've got all these cool animations, but what if someone has specified [prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion)? Tailwind can handle that for you as long as you prefix your animation with `motion-safe:`, e.g. + +```html +{% raw %} +

    Spinning text

    +{% endraw %} +``` + +There's other useful Tailwind classes for accessibility, like [sr-only](https://tailwindcss.com/docs/screen-readers#screen-reader-only-elements), which will remain in the page, but only be visible to screen readers. + +I think something that would be interesting to add to the Tailwind a11y story is using Tatiana Mac's (@tatianamac) approach of [taking a no-motion-first approach to animations](https://www.tatianamac.com/posts/prefers-reduced-motion). + +## Define some base styles + +I'm all for components, and I'm a big fan of [JSX](https://jasonformat.com/wtf-is-jsx/). Tailwind pairs nicely with components, but I do think that it's still good to have some base styles defined, even if you are using components. + +For example, a base font size and colour, focus state styles, headings etc. This is what I [ended up doing in the OpenSauced app repository](https://github.com/open-sauced/app/pulls?q=is%3Apr+sort%3Aupdated-desc+is%3Amerged+focus+author%3Anickytonline). + +## Another Complaint: It's like bootstrap + +Tailwind CSS on its own is not like bootstrap. It's just CSS utility classes, whereas bootstrap is UI components and CSS. + +I've never used it, but maybe you could fall into this trap with [Tailwind UI](https://tailwindui.com/). + +## Tradeoffs + +Like many things, there are tradeoffs. I think the biggest one is learning the Tailwind CSS classes and naming conventions for building them, but I think the benefits outweigh this. And to be honest, once you start writing the classes frequently, the naming convention just sticks in your head. + +And if you have some super complex CSS, for whatever reason, Tailwind can't handle, there's nothing wrong with adding some custom CSS. + +## Wrapping Things Up + +I literally only started using Tailwind September 18th of 2023 [when I started at OpenSauced](https://twitter.com/nickytonline/status/1703742155351539781). + +Tailwind has made me super productive while building out OpenSauced, and I've used it in some other projects since then. + +Remember, **Tailwind is a utility-first CSS framework. It's not inline CSS.** + +I encourage you to give Tailwind a go. They have outstanding [documentation](https://tailwindcss.com/docs) and [great IDE support](https://tailwindcss.com/docs/editor-setup) to help you along the way. + +If you give it a go and say it's not for me, that's OK. Use what makes you the most productive. + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md new file mode 100644 index 00000000..90d3854a --- /dev/null +++ b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md @@ -0,0 +1,243 @@ +--- +title: "Stuck in the Middle with You: An intro to Middleware" +tags:[] +authors: nickytonline +slug: 2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo +description: "Middleware exists in several frameworks like Next.js, Express, Hono and Fresh, and not just in..." +--- + +Middleware exists in several frameworks like Next.js, Express, Hono and Fresh, and not just in JavaScript land. You can find it in frameworks like ASP.NET core in the .NET ecosystem, or Laravel in PHP. Since I mainly work in JavaScript and TypeScript these days, examples will be from frameworks in those ecosystems. + +Middleware is something that happens in the middle of a user or some service interacting with a site or [API](https://en.wikipedia.org/wiki/API) call and happens at the framework level. + +It runs before a page loads or an API endpoint is called, or more generally a route. There are many reasons why you might want to do that: + +* gate certain content, e.g. a private route +* set and read cookies +* add headers to the response being sent out +* [URL](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL) redirect, e.g. redirecting to another page based on some criteria +* URL rewrites + +Let's dig in! + +## Gate Content + +Authentication and authorization are two great candidates for guarding certain routes, although it’s still good to guard access to privied resources in API endpoints and pages. In this context, think of the middleware as the first line of defense. + +![Gandfalf saying, "You shall not pass!"](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExMzF0MWU4cmEwb3Y3ZnozY25raGJkM2VseTVhMHRpNjY3OHI0cjFobCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/njYrp176NQsHS/giphy-downsized-large.gif) + +In the OpenSauced application, when a user logs in and the path is `/workspaces` we redirect them to their workspace. + +```typescript +{% raw %} + if (session?.user && req.nextUrl.pathname === "/workspaces") { + const data = await loadSession(req, session?.access_token); + const workspaceUrl = getWorkspaceUrl(req.cookies, req.url, data.personal_workspace_id); + + return NextResponse.redirect(`${workspaceUrl}`); + } +{% endraw %} +``` + +[Code on GitHub](https://github.com/open-sauced/app/blob/beta/middleware.ts#L63C1-L68C4) + +## Setting and Reading cookies + +So what is a cookie? + +A cookie is a way to set a piece of user-specific data. This could be a session ID for someone who is logged in to a site, or it could be some other user data. Note that the data in a cookie is typically not that large, but according to MDN, there is [no size limit to the name or value of a cookie](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#notes). + +![Cookie monster eating cookies](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExb2dwc2IzcmxrZ2hzMWFmbmYwMWE4Z2NoODh5amdjN3NnbDhhbWtmciZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/BsUORZkF3gBqg/giphy.gif) + +Cookies that are [HTTP only](https://owasp.org/www-community/HttpOnly) can be accessed on the server-side, but for cookies that are not HTTP only, they can be accessed server-side and client-side. For example, you wouldn't want someone to tamper with your session ID on the client-side, so this type of cookie is set as HTTP only. + +We recently shipped a new feature at OpenSauced, called [Workspaces](https://docs.opensauced.pizza/features/workspaces/). You can read all about it in this great post from my co-worker Bekah (@BekahHW). + +https://dev.to/opensauced/navigating-the-challenges-of-scaling-open-source-projects-11h2 + +TLDR; a Workspace acts like a workspace in other software you may have used, like Notion. One thing required for this feature is when a user navigates to the `/workspaces` URL, it has to load the last accessed workspace. If a user has never accessed a workspace before, it should default to their personal workspace. This is a perfect use case to leverage using a cookie. + +When someone logs in, we check if they have a workspace ID cookie set. If they don’t, we grab their personal workspace ID, a type of workspace every user has. + +The code for this was in the code snippet in the last section. + +```typescript +{% raw %} + const workspaceUrl = getWorkspaceUrl(req.cookies, req.url, data.personal_workspace_id); +{% endraw %} +``` + +Let's take a peek into the `getWorkspaceUrl` function. + +```typescript +{% raw %} +export function getWorkspaceUrl(cookies: RequestCookies, baseUrl: string, personalWorkspaceId: string) { + if (!cookies.has(WORKSPACE_ID_COOKIE_NAME)) { + cookies.set(WORKSPACE_ID_COOKIE_NAME, personalWorkspaceId); + } + + // @ts-expect-error the cookie value will be defined + const workspaceId = cookies.get(WORKSPACE_ID_COOKIE_NAME).value; + + return new URL(`/workspaces/${workspaceId}`, baseUrl); +} +{% endraw %} +``` + +If there is no workspace cookie set, we create a cookie and set its value to the user's personal workspace ID. + +After that, we read the cookie, we build a URL with it and the user is redirected to the workspace. + +The other piece of this that doesn't occur in middleware is when a user visits a valid workspace page they have access to, we set the workspace ID cookie. Next time they go to the `/workspaces` link, the cookie will exist, and a URL using `new URL()` will be used to redirect them to the last accessed workspace homepage. + +The page will call the OpenSauced app's `setCookie` function. + +```typescript +{% raw %} +export function setCookie({ + response, + name, + value, + maxAge = 31536000, + sameSite = "Lax", +}: { + response: Response; + name: string; + value: string; + maxAge?: number; + sameSite?: SameSite; +}) { + response.setHeader( + "Set-Cookie", + `${name}=${value}; Max-Age=${maxAge}; Path=/; HttpOnly; SameSite=${sameSite}; Secure` + ); +} +{% endraw %} +``` + +[Code on GitHub](https://github.com/open-sauced/app/blob/beta/lib/utils/server/cookies.ts#L18C1-L35C2) + +Although cookies are their own thing, you have set them in a header. + +## Add Headers + +As mentioned in the previous section, you set cookies via a header. So what is a header, more specifically, an HTTP header? + +Headers are a set of key value pairs to let a browser know how to behave, for example, should a page be cached? It can also be custom key value pairs that your application or services might need. For example, when I worked at Netlify, for the CDN to work, there would be Netlify-specific headers that once inside the internal network would allow Netlify to do some magic. + +If you go to my website, [nickyt.co](https://nickyt.co), and open the network panel in the dev tools of your browser of choice, you'll see some Netlify-specific headers. + +![Response headers from nickyt.co's homepage showing some custom Netlify headers being set](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0yzhri4reu5xv8lvdzr.png) + +I recently gave a talk on Fresh, a full-stack framework for Deno at [Node Summit '24](https://www.linkedin.com/feed/update/urn:li:activity:7160791824209498113/). The recording isn't up yet, but here's the [slide deck](https://www.nickyt.co/slides/fresh) and [code from the demo](https://github.com/nickytonline/fresh-demo) for anyone interested. + +In Fresh middleware, this is how you could set a header. + +```typescript +{% raw %} +export async function handler( + request: Request, + ctx: FreshContext +) { + const response = await ctx.next(); + response.headers.set("x-fresh", "true"); + + if (request.url.includes("joke-of-the-day")) { + response.headers.set("x-joke-page", "true"); + } + + if (request.url.includes("movie/")) { + response.headers.set("x-movie-page", "true"); + } + + return response; +} +{% endraw %} +``` + +[Code on GitHub](https://github.com/nickytonline/fresh-demo/blob/main/routes/_middleware.ts#L8C1-L24C2) + +In the above code snippet, we're checking to see if a specific route contains a certain string and if it does, we set a custom header, e.g. + +```typescript +{% raw %} +response.headers.set("x-joke-page", "true"); +{% endraw %} +``` + +## URL Redirection + +Page redirection allows you to have a URL go to another URL. You might do this for a couple of reasons. Maybe a bunch of links on your site changed, and you need to have them go to a new set of links, or you have a URL that needs to redirect to a user-specific page. + +![Kermit the frog looking at a map trying to figure out where to go](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExMjdlMThsN3gwbDRxcnZvYnphcTRoMmx4cjd6YjU2Yjk3cXJnMG5jbiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/cjbfyJrICOaKIXBWyG/giphy.gif) + +For non-trivial redirects like the workspaces redirect URL mentioned in one of the previous sections, middleware is a great place for handing redirects. + +```typescript +{% raw %} + if (session?.user && req.nextUrl.pathname === "/workspaces") { + const data = await loadSession(req, session?.access_token); + const workspaceUrl = getWorkspaceUrl(req.cookies, req.url, data.personal_workspace_id); + + return NextResponse.redirect(`${workspaceUrl}`); + } +{% endraw %} +``` + +[Code on GitHub](https://github.com/open-sauced/app/blob/beta/middleware.ts#L63C1-L68C4) + +In this case, when someone in the OpenSauced application goes to `/workspaces` we redirect them to a user-specific URL. + +```typescript +{% raw %} +return NextResponse.redirect(`${workspaceUrl}`); +{% endraw %} +``` + +Not a hard and fast rule, but if you have trivial redirects like redirect `/old-blog-path/*` to `/blog/*`, consider using your hosting platform's redirects instead of middleware. + +## URL Rewriting + +You can also do URL rewrites. It's like a redirect, but the URL never changes. Frameworks like Next.js provide this out of the box in their configuration file, but for more complex handling, you may want to do it in middleware. So what is a [URL rewrite](https://www.smashingmagazine.com/2011/11/introduction-to-url-rewriting/)? A rewrite will preserve the existing URL but will render content from another URL. + +![Mr. Burns from the Simpsons saying, "Well, cover it with a rewrite"](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExeGIzcWZ5dXdjcGxnYnBhd2diNDFraTM0emo4Z2xwMWY3b293aTJqaSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/xT5LMuqfAqBIsGs5xK/giphy.gif) + +Here's a slightly modified example straight out of the Next.js middleware documentation: + +```typescript +{% raw %} +import { NextResponse } from 'next/server' +import type { NextRequest } from 'next/server' + +export function middleware(request: NextRequest) { + if (request.nextUrl.pathname.startsWith('/dashboard')) { + return NextResponse.rewrite(new URL('/dashboard/user', request.url)) + } +} +{% endraw %} +``` + +[Code in Next.js documenation](https://nextjs.org/docs/app/building-your-application/routing/middleware#conditional-statements) + +In the above snippet, all users have a `/dashboard` page they go to, but every user's dashboard is different. In this case, the user will always see the page as `/dashboard` but it loads the specific user's dashboard. + +## Resources + +Here's the documentation for middleware of the mentioned frameworks: + +* [Express middleware](https://expressjs.com/en/guide/using-middleware.html) +* [Hono middleware](https://hono.dev/guides/middleware) +* [Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) +* [Fresh middlewares](https://fresh.deno.dev/docs/concepts/middleware) +* [Laravel middleware](https://laravel.com/docs/10.x/middleware) +* [ASP.NET Core middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0) + +## Wrapping Up + +Middleware is a great tool and if your framework of choice supports middleware (most do), I encourage you to read up on how to leverage it in that framework. + +What use cases have you used middleware for? Please let me know in the comments. + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md new file mode 100644 index 00000000..ad18e7dd --- /dev/null +++ b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md @@ -0,0 +1,77 @@ +--- +title: "Form and Function: How I Lost My Submit Button & Got It Back" +tags:[] +authors: nickytonline +slug: 2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91 +description: "As web developers, we know that most of the create, read update, and delete (CRUD) actions we perform..." +--- + +As web developers, we know that most of the create, read update, and delete (CRUD) actions we perform on the web are typically (hopefully?) done using an [HTML form](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form). + +## HTML Forms + +HTML Forms are cool because they have plenty of built-in features. + +For example, they have native form validation and access to all the inputs in a form, and at some point, because you need to submit the form, there is a mechanism to do that as well. You can use a [button](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button), `` or an [input of type submit](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/submit), ``, although the latter isn't used as much these days in new sites, from what I've seen. + +Here is a simple form to exhibit this. + +https://codepen.io/nickytonline/pen/JjVOarX + +If you fill out the form and click submit, the form will submit and add a paragraph with dark green text client-side that says, "Form submitted". + +![Submitting the simple form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbpoz901yk9s8kewx806.gif) + +There are other things in the simple form, like form validation via the [required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required) attribute on inputs, but that's not what we're here to discuss. + +What we want to touch on is that the form was able to handle the submit event because it had a submit button associated with it, which was defined in HTML within the form element. + +_Note: you can press enter in fields to submit a form, but again, not what we're here to discuss._ + +## How I Broke My Form + +This brings us to a new feature that I was working on for OpenSauced for a few months, [workspaces](https://docs.opensauced.pizza/features/workspaces/). I encourage you to create your own, but for now, let's get back to the business of forms. + +Here's our beautiful workspaces settings page that I implemented. + +![an OpenSauced workspace settings page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bq93z0w7duinhgew6azp.png) + +Recently, there were styling changes, which is what you see above. + +https://github.com/open-sauced/app/pull/2982 + +Everything looked great, and I had tested it. + +_Narrator: he thought he had tested it, and we shipped things to production._ + +Once things went live, I decided to do some smoke tests, which I usually do. I went over to the beautiful workspace settings I had worked on, made some changes in the settings, and then clicked Update Workspace button. Hmm, no toast message saying the settings were updated. I checked the browser dev tools to see if there were any JavaScript errors. Nothing related to the updates. And then it dawned on me. The submit button was outside the form, and I just broke some key functionality in the app. + +![Michael Scott telling everybody not to panic.](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExY2xxdGVubmtuam5rMzM1N2RxNjY4dTJkOTh1cW03NnN4d3FkNDgzayZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/1luXLMeNxsaNFMUuOe/giphy.gif) + +Side note, but luckily thanks to Netlify's deployment rollback feature, I was able to revert to the previous production deployment within about a minute of the workspace settings page being broken 😅 + +## How I Fixed My Form + +So how did I fix it? We needed this new styling to fix several other issues related to [z-indexes](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index) and layout. + +For some context, the OpenSauced application is a Next.js site, so React, but I decided to put on my old school HTML hat and remembered that form elements can be associated to a form via a `form` attribute. What you need to do is give the form an `id` attribute, and the form element that you want to associate the form to needs to have a `form` attribute whose value is the value of the `id` attribute for the form. + +Here's another simple form demonstrating a simplified version of my fix. + +https://codepen.io/nickytonline/pen/XWQzPOX + +I encourage you to remove the `form` attribute from the button in the above CodePen to see the issue I caused. + +Here's the fix I rolled out to production. + +https://github.com/open-sauced/app/pull/3003 + +## Wrapping Up + +Learning a framework is great, and I'm a big proponent of just building something, but as you continue on in your career, it's great to start getting some fundamentals into the mix. + +Also, this is a perfect example of why using [semantic HTML](https://developer.mozilla.org/en-US/curriculum/core/semantic-html/) is important! It definitely helped me get out of jam! 😅 + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md new file mode 100644 index 00000000..4ec00fc7 --- /dev/null +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md @@ -0,0 +1,110 @@ +--- +title: "Creating an OG image using React and Netlify Edge Functions" +tags:[] +authors: nickytonline +slug: 2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a +description: "Open Graph (OG) images are a must if you're sharing content on the Internet. From sites like..." +--- + +[Open Graph](url) (OG) images are a must if you're sharing content on the Internet. From sites like X/Twitter, to Slack or Discord, a great OG image makes your link share pop. + +## Examples + +I recently built out a couple of OG images for Open Sauced for a couple of features we've rolled out over the past couple of months, [Workspaces](https://docs.opensauced.pizza/features/workspaces/) and [Repository pages](https://docs.opensauced.pizza/features/repo-pages/). They're great features that I encourage you to check out, and I encourage you to share them on socials so our beautiful OG images pop. + +For example, here's an OG image for a [workspace for jsr](https://app.opensauced.pizza/workspaces/760ea8ea-ebd3-4f9a-91ab-780384e3c102). [JSR](https://jsr.io) is the new JavaScript registry from the folks from Deno. + +[![OG image for the OpenSauced workspace for jsr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9v3aq0eu0lsoxni8b3z.png)](https://app.opensauced.pizza/workspaces/760ea8ea-ebd3-4f9a-91ab-780384e3c102) + +And here's the OG image for a repository page for [huggingface/transformers](https://app.opensauced.pizza/s/huggingface/transformers). + +[![OG image for the huggingface/transformers repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7wrvyq2qqjwefpeklraf.png)](https://app.opensauced.pizza/s/huggingface/transformers) + +Looking at the image for the jsr workspace, there is a template for the image, but there are several dynamic portions to the image. + +All the sections denoted by green outlined squares are dynamic. + +![OG image for the OpenSauced workspace for jsr with sections outline in green squares denoting dynamic portions of the image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/32npdvf35s50hjl9r9iv.png) + +This dynamic info gets pulled in for the most part from the OpenSauced API. + +Other parts are pulled in from the URL, like `30` for the day range, and the description comes from the query string in the OG image URL. + +![browser dev tools view of the metadata section of the with OG image URLs outlined by green squares](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f059m9we4gkmb8ixx39v.png) + +## React to generate an image + +So, how do we use React to generate an image? + +We're using og_edge from my old co-worker Matt Kane (@ascorbic), but og_edge is a direct port of [@vercel/og](https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images) that works on Deno and Netlify Edge Functions which run on Deno. + +https://github.com/ascorbic/og-edge + +Under the hood, og_edge and @vercel/og use the Satori library. + +> Satori: Enlightened library to convert HTML and CSS to SVG. + +https://github.com/vercel/satori + +The API for the `og_edge` module is pretty straightforward. It exposes an `ImageResponse` constructor with the following options and that's it. + +```typescript +{% raw %} +new ImageResponse( + element: ReactElement, + options: { + width?: number = 1200 + height?: number = 630 + emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' | 'fluent' | 'fluentFlat' = 'twemoji', + fonts?: { + name: string, + data: ArrayBuffer, + weight: number, + style: 'normal' | 'italic' + }[] + debug?: boolean = false + + // Options that will be passed to the HTTP response + status?: number = 200 + statusText?: string + headers?: Record + }, +) +{% endraw %} +``` + +_Code snippet above care of the official [og_edge API reference](https://github.com/ascorbic/og-edge#api-reference)._ + +To build out these OG images, we have a background image, some icons, like a star and fork icon, and we also pull in the repository organization or user's avatar. With a bit of vanilla CSS, we can position things just right. We also pull in the [Inter font](https://fonts.google.com/specimen/Inter) as that's what we use at OpenSauced. + +As far as I know, `og_edge` does not support Tailwind like `@vercel/og` does. Not a dealbreaker at all, but just something to be mindful of. + +One other thing we do is set cache headers as these are dynamic images where the data changes over time. Having said that, some social networks cache OG images very aggressively. + +```typescript +{% raw %} + headers: { + // cache for 2 hours + "cache-control": "public, s-maxage=7200", + "content-type": "image/png", + }, +{% endraw %} +``` + +## Show me the code + +Here's the pull requests for the initial work on these two OG images. + +https://github.com/open-sauced/app/pull/2939 + +https://github.com/open-sauced/app/pull/3117 + +## Wrapping up + +Beautiful and dynamic OG images are a must if you're looking to stand out when sharing links on socials, and `og_edge` and `@vercel/og` are great options if you also want to leverage your existing React skill set. + +Now go out and build your own OG images! 🖼️ + +Stay saucy peeps! + +If you would like to know more about my work in open source, [follow me on OpenSauced](https://oss.fyi/nickytonline). diff --git a/blog/authors.yml b/blog/authors.yml index 01621536..87fbb2c5 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -5,3 +5,9 @@ BekahHW: image_url: https://github.com/BekahHW.png email: Bekah@opensauced.pizza twitter: BekahHW + +nickytonline: + name: Nick Taylor + title: AI Engineer + url: https://www.nickyt.co/ + image_url: https://github.com/nickytonline.png From 6d71cd1a01481a6f30048b02afddd45812210075 Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 10:19:51 -0400 Subject: [PATCH 2/8] chore: added missing author info --- blog/authors.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/blog/authors.yml b/blog/authors.yml index 87fbb2c5..06d72ad0 100644 --- a/blog/authors.yml +++ b/blog/authors.yml @@ -11,3 +11,5 @@ nickytonline: title: AI Engineer url: https://www.nickyt.co/ image_url: https://github.com/nickytonline.png + email: nick@opensauced.pizza + twitter: nickytonline From b90314f5f3074df3d6c215be5642f0a01879c5bb Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 10:25:29 -0400 Subject: [PATCH 3/8] chore: fixed an issue with a missing space in tags in front matter --- ...e-your-repository-with-code-owners-4clg.md | 7 ++--- ...-actions-a-maintainers-best-friend-488n.md | 8 ++---- ...t-productivity-with-the-github-cli-2mne.md | 6 ++-- ...-vitest-for-your-react-application-1b75.md | 4 +-- ...-the-native-browser-dialog-element-1nhn.md | 4 +-- ...ndeniable-goodness-of-tailwind-css-4doc.md | 20 ++++++------- ...le-with-you-an-intro-to-middleware-1gjo.md | 28 +++++++++---------- ...-lost-my-submit-button-got-it-back-5b91.md | 6 ++-- ...g-react-and-netlify-edge-functions-563a.md | 2 +- 9 files changed, 40 insertions(+), 45 deletions(-) diff --git a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md index 140b65e2..003b6372 100644 --- a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md +++ b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md @@ -1,6 +1,6 @@ --- title: "Supercharge your Repository with Code Owners" -tags:[] +tags: [] authors: nickytonline slug: 2023-09-21-supercharge-your-repository-with-code-owners-4clg description: "As a maintainer of a repository, it’s in your best interest to automate processes as much as..." @@ -16,7 +16,6 @@ A CODEOWNERS file in GitHub is a special file used to specify who reviews and ma For example, in this particular CODEOWNERS file there is the `@open-sauced/engineering` team. - ![A CODEOWNERS file with one team in it, @open-sauced/engineering](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mg69ouah43ks9x3e0zh.png) When someone creates a PR for that repository, that team is automatically added as a reviewer. @@ -27,7 +26,7 @@ This is really handy because you don’t need to go and manually add reviewers, Another nice feature of the CODEOWNERS file is that it can be used as part of [branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule). -To enable this, go to the *Protect matching branches* section of a branch protection rule, and ensure the *Require review from Code Owners* option is checked. +To enable this, go to the _Protect matching branches_ section of a branch protection rule, and ensure the _Require review from Code Owners_ option is checked. ![GitHub PR review file where the UI says that the CODEOWNERS file is valid](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b85pfint60i7h5ph9eoi.png) @@ -37,7 +36,7 @@ One other thing to note is if you have permanent branches aside from `main`, lik The CODEOWNERS file is a special file that can reside in the root directory, in the `.github` directory or the `docs` directory (if you have one). -The `.github` folder might not exist in your project if you haven’t added other GitHub automated processes like [GitHub Actions](https://github.com/features/actions), [pull request templates](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository), or [issue templates](https://dev.to/opensauced/how-to-create-a-good-pull-request-template-and-why-you-should-add-gifs-4i0l). +The `.github` folder might not exist in your project if you haven’t added other GitHub automated processes like [GitHub Actions](https://github.com/features/actions), [pull request templates](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository), or [issue templates](https://dev.to/opensauced/how-to-create-a-good-pull-request-template-and-why-you-should-add-gifs-4i0l). Also note, GitHub looks for the first CODEOWNERS file it finds, searching first in the root directory, then the `.github` directory, and finally, the `docs` directory (if it exists). diff --git a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md index 566b50a2..814ed918 100644 --- a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md +++ b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md @@ -1,6 +1,6 @@ --- title: "GitHub Actions: A Maintainer's Best Friend" -tags:[] +tags: [] authors: nickytonline slug: 2023-10-31-github-actions-a-maintainers-best-friend-488n description: "As developers, it’s in our best interest to automate things. The less we have to do in a manual way,..." @@ -8,7 +8,7 @@ description: "As developers, it’s in our best interest to automate things. The As developers, it’s in our best interest to automate things. The less we have to do in a manual way, the better. As soon as manual intervention is required, there is potential for failure or a mishap. Aside from that, it’s your time as a maintainer that could be spent elsewhere. -If you host your code on GitHub, besides scripts to automate certain actions, you can also leverage the huge ecosystem of [GitHub +If you host your code on GitHub, besides scripts to automate certain actions, you can also leverage the huge ecosystem of [GitHub Actions](https://github.com/features/actions). ## Practical Examples @@ -31,11 +31,9 @@ When a new issue is opened, an issue responds with the following: My coworker bdougie (@bdougieyo) created the [take Github action](https://github.com/bdougie/take-action). It allows external contributors to self-assign issues by typing `.take` into a comment of an issue. This removes the burden of a bit of back and forth between contributors and maintainers. - [![OpenSauced contributor itskish0re self assigning an issue by using the .take command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eh9gjzo8aiwleqqr7qhe.png)](https://github.com/open-sauced/app/issues/2017#issuecomment-1785492904) -Of course, we don’t want external contributors self-assigning any issue they want. The take action also has the concept of blocking labels. For example, if an issue has a `👀 needs triage` label, we can add this label to a list of blocking labels. - +Of course, we don’t want external contributors self-assigning any issue they want. The take action also has the concept of blocking labels. For example, if an issue has a `👀 needs triage` label, we can add this label to a list of blocking labels. [![Someone trying to self-assign an issue when there are blocking labels on the issue](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w52j0puh47kpgg27clnd.png)](https://github.com/open-sauced/app/issues/1952#issuecomment-1772176129) diff --git a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md index f626b5ce..203fdb4b 100644 --- a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md +++ b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md @@ -1,6 +1,6 @@ --- title: "Boost productivity with the GitHub CLI" -tags:[] +tags: [] authors: nickytonline slug: 2023-11-14-boost-productivity-with-the-github-cli-2mne description: "The GitHub CLI is an indispensable tool as a project maintainer or contributor on GitHub. It can..." @@ -101,7 +101,7 @@ Here it is in action for a recent pull request I reviewed for the [OpenSauced ap ## Creating a Pull Request -Before the GitHub CLI, I used to push my branch to GitHub, and then I would go to the repository's page on GitHub.com and create a pull request from there. +Before the GitHub CLI, I used to push my branch to GitHub, and then I would go to the repository's page on GitHub.com and create a pull request from there. ![A repository's main page on github.com with a call to action to create a pull request from a branch pushed to github.com](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mt6fqypoarfmu7er8c3t.png) @@ -171,7 +171,7 @@ A quick check will ask if you want to create the repository on GitHub. Type `y` ![The GitHub CLI summarizing all the selections made, prompting the user to create the repository on GitHub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fek4c3bxo06ul695g5v2.png) -Next, you'll be asked if you want to clone the repository locally. +Next, you'll be asked if you want to clone the repository locally. ![The GitHub CLI asking the user if they want to clone the repository](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cu0ea66kzsji32qfh0j.png) diff --git a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md index 60ca11cb..a2fc5e58 100644 --- a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md +++ b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md @@ -1,6 +1,6 @@ --- title: "Migrating from Jest to Vitest for your React Application" -tags:[] +tags: [] authors: nickytonline slug: 2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75 description: "Are you looking to migrate from Jest to Vitest for your React application? Look no further. I..." @@ -127,7 +127,7 @@ Next, add `jsdom` to your Vitest configuration. ## Aliases -Your project might be using aliases for paths. For example, in the OpenSauced app repository, `components`, `lib`, and `img` are aliases to folders. +Your project might be using aliases for paths. For example, in the OpenSauced app repository, `components`, `lib`, and `img` are aliases to folders. If you need to [support aliases](https://vitest.dev/config/#alias), Vitest has you covered. diff --git a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md index e55a8c8d..c912adab 100644 --- a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md +++ b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md @@ -1,6 +1,6 @@ --- title: "Unlocking the Power of HTML's Native Browser Dialog Element" -tags:[] +tags: [] authors: nickytonline slug: 2024-01-23-the-native-browser-dialog-element-1nhn description: "All the major browsers now support the <dialog > element. Why add this HTML element? User land..." @@ -56,7 +56,7 @@ With a non-modal dialog, the user is not blocked from navigating the rest of the ## Closing a dialog -To close a dialog or modal, we can use the [HTMLDialogElement close method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close). +To close a dialog or modal, we can use the [HTMLDialogElement close method](https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close). ```typescript {% raw %} diff --git a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md index 335bc806..47b54cf3 100644 --- a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md +++ b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md @@ -1,6 +1,6 @@ --- title: "Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS" -tags:[] +tags: [] authors: nickytonline slug: 2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc description: "People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but..." @@ -10,7 +10,7 @@ People definitely have opinions about Tailwind. There are staunch supporters and If you're pretty well versed with Tailwind, this article might not be for you, but who knows? Read on and maybe you'll learn something. -I'm coming in with what, I think, is a fresh perspective. I'm using Tailwind for the first time professionally. Furthermore, I don't consider myself a CSS expert, but I think I have pretty solid CSS skills. +I'm coming in with what, I think, is a fresh perspective. I'm using Tailwind for the first time professionally. Furthermore, I don't consider myself a CSS expert, but I think I have pretty solid CSS skills. I mention all this, to convey a sentiment, I've seen many people exhibit. You're using Tailwind because you don't understand CSS. I do understand CSS. @@ -98,13 +98,11 @@ What about something more complex like [pseudo-elements](https://developer.mozil ```html {% raw %} -

    - OpenSauced is awesome! -

    +

    OpenSauced is awesome!

    {% endraw %} ``` @@ -157,13 +155,13 @@ I think something that would be interesting to add to the Tailwind a11y story is ## Define some base styles -I'm all for components, and I'm a big fan of [JSX](https://jasonformat.com/wtf-is-jsx/). Tailwind pairs nicely with components, but I do think that it's still good to have some base styles defined, even if you are using components. +I'm all for components, and I'm a big fan of [JSX](https://jasonformat.com/wtf-is-jsx/). Tailwind pairs nicely with components, but I do think that it's still good to have some base styles defined, even if you are using components. For example, a base font size and colour, focus state styles, headings etc. This is what I [ended up doing in the OpenSauced app repository](https://github.com/open-sauced/app/pulls?q=is%3Apr+sort%3Aupdated-desc+is%3Amerged+focus+author%3Anickytonline). ## Another Complaint: It's like bootstrap -Tailwind CSS on its own is not like bootstrap. It's just CSS utility classes, whereas bootstrap is UI components and CSS. +Tailwind CSS on its own is not like bootstrap. It's just CSS utility classes, whereas bootstrap is UI components and CSS. I've never used it, but maybe you could fall into this trap with [Tailwind UI](https://tailwindui.com/). @@ -183,7 +181,7 @@ Remember, **Tailwind is a utility-first CSS framework. It's not inline CSS.** I encourage you to give Tailwind a go. They have outstanding [documentation](https://tailwindcss.com/docs) and [great IDE support](https://tailwindcss.com/docs/editor-setup) to help you along the way. -If you give it a go and say it's not for me, that's OK. Use what makes you the most productive. +If you give it a go and say it's not for me, that's OK. Use what makes you the most productive. Stay saucy peeps! diff --git a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md index 90d3854a..896551e7 100644 --- a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md +++ b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md @@ -1,6 +1,6 @@ --- title: "Stuck in the Middle with You: An intro to Middleware" -tags:[] +tags: [] authors: nickytonline slug: 2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo description: "Middleware exists in several frameworks like Next.js, Express, Hono and Fresh, and not just in..." @@ -12,11 +12,11 @@ Middleware is something that happens in the middle of a user or some service int It runs before a page loads or an API endpoint is called, or more generally a route. There are many reasons why you might want to do that: -* gate certain content, e.g. a private route -* set and read cookies -* add headers to the response being sent out -* [URL](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL) redirect, e.g. redirecting to another page based on some criteria -* URL rewrites +- gate certain content, e.g. a private route +- set and read cookies +- add headers to the response being sent out +- [URL](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL) redirect, e.g. redirecting to another page based on some criteria +- URL rewrites Let's dig in! @@ -208,8 +208,8 @@ Here's a slightly modified example straight out of the Next.js middleware docume {% raw %} import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' - -export function middleware(request: NextRequest) { + +export function middleware(request: NextRequest) { if (request.nextUrl.pathname.startsWith('/dashboard')) { return NextResponse.rewrite(new URL('/dashboard/user', request.url)) } @@ -225,12 +225,12 @@ In the above snippet, all users have a `/dashboard` page they go to, but every u Here's the documentation for middleware of the mentioned frameworks: -* [Express middleware](https://expressjs.com/en/guide/using-middleware.html) -* [Hono middleware](https://hono.dev/guides/middleware) -* [Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) -* [Fresh middlewares](https://fresh.deno.dev/docs/concepts/middleware) -* [Laravel middleware](https://laravel.com/docs/10.x/middleware) -* [ASP.NET Core middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0) +- [Express middleware](https://expressjs.com/en/guide/using-middleware.html) +- [Hono middleware](https://hono.dev/guides/middleware) +- [Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) +- [Fresh middlewares](https://fresh.deno.dev/docs/concepts/middleware) +- [Laravel middleware](https://laravel.com/docs/10.x/middleware) +- [ASP.NET Core middleware](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-8.0) ## Wrapping Up diff --git a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md index ad18e7dd..8389bbc6 100644 --- a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md +++ b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md @@ -1,6 +1,6 @@ --- title: "Form and Function: How I Lost My Submit Button & Got It Back" -tags:[] +tags: [] authors: nickytonline slug: 2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91 description: "As web developers, we know that most of the create, read update, and delete (CRUD) actions we perform..." @@ -22,7 +22,7 @@ If you fill out the form and click submit, the form will submit and add a paragr ![Submitting the simple form](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rbpoz901yk9s8kewx806.gif) -There are other things in the simple form, like form validation via the [required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required) attribute on inputs, but that's not what we're here to discuss. +There are other things in the simple form, like form validation via the [required](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required) attribute on inputs, but that's not what we're here to discuss. What we want to touch on is that the form was able to handle the submit event because it had a submit button associated with it, which was defined in HTML within the form element. @@ -41,7 +41,7 @@ Recently, there were styling changes, which is what you see above. https://github.com/open-sauced/app/pull/2982 Everything looked great, and I had tested it. - + _Narrator: he thought he had tested it, and we shipped things to production._ Once things went live, I decided to do some smoke tests, which I usually do. I went over to the beautiful workspace settings I had worked on, made some changes in the settings, and then clicked Update Workspace button. Hmm, no toast message saying the settings were updated. I checked the browser dev tools to see if there were any JavaScript errors. Nothing related to the updates. And then it dawned on me. The submit button was outside the form, and I just broke some key functionality in the app. diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md index 4ec00fc7..21c337bb 100644 --- a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md @@ -1,6 +1,6 @@ --- title: "Creating an OG image using React and Netlify Edge Functions" -tags:[] +tags: [] authors: nickytonline slug: 2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a description: "Open Graph (OG) images are a must if you're sharing content on the Internet. From sites like..." From a01c3db004a238631e2f224b13a74a3d0e0b9385 Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 10:36:33 -0400 Subject: [PATCH 4/8] chore: fixed mdx rendering issues --- .../2024-01-23-the-native-browser-dialog-element-1nhn.md | 6 +++--- ...-og-image-using-react-and-netlify-edge-functions-563a.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md index c912adab..fc7bcfce 100644 --- a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md +++ b/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md @@ -6,7 +6,7 @@ slug: 2024-01-23-the-native-browser-dialog-element-1nhn description: "All the major browsers now support the <dialog > element. Why add this HTML element? User land..." --- -All the major browsers now support the `` element. Why add this HTML element? User land code, code that developers write to fill in gaps of the browser, was doing similar things repeatedly, especially around focus trapping, and browser engines responded by adding this functionality directly in the browser. +All the major browsers now support the `<dialog%gt;` element. Why add this HTML element? User land code, code that developers write to fill in gaps of the browser, was doing similar things repeatedly, especially around focus trapping, and browser engines responded by adding this functionality directly in the browser. ## Focus Trapping @@ -34,7 +34,7 @@ _Note that you'll need to [view this CodePen in full view](https://codepen.io/ni Not only do you get focus trapping, you also get modal close functionality that people have come to expect via the Escape key. -All of that is already amazing, but another common thing people were doing in user land was adding a background to block out users from interacting with the page. With the `` element, we can add a `::backdrop` pseudo-element that does this for you. All you need to do is style it. In the CodePen above, uncomment out this code in the CSS panel to see this in action. +All of that is already amazing, but another common thing people were doing in user land was adding a background to block out users from interacting with the page. With the `<dialog%gt;` element, we can add a `::backdrop` pseudo-element that does this for you. All you need to do is style it. In the CodePen above, uncomment out this code in the CSS panel to see this in action. ```css {% raw %} @@ -77,7 +77,7 @@ The web platform keeps getting better. It's great to see pain points in user lan - [Using JavaScript to trap focus in an element](https://hidde.blog/using-javascript-to-trap-focus-in-an-element/) - [MDN - <dialog>: The Dialog element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog) -- GitHub issue [ element should trap focus](https://github.com/w3c/html/issues/1514) from the _w3c/html_ repository. +- GitHub issue [<dialog%gt; element should trap focus](https://github.com/w3c/html/issues/1514) from the _w3c/html_ repository. - [Dialog - web.dev](https://web.dev/learn/html/dialog) Stay saucy peeps! diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md index 21c337bb..54073f14 100644 --- a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md @@ -30,7 +30,7 @@ This dynamic info gets pulled in for the most part from the OpenSauced API. Other parts are pulled in from the URL, like `30` for the day range, and the description comes from the query string in the OG image URL. -![browser dev tools view of the metadata section of the with OG image URLs outlined by green squares](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f059m9we4gkmb8ixx39v.png) +![browser dev tools view of the metadata section of the head with OG image URLs outlined by green squares](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f059m9we4gkmb8ixx39v.png) ## React to generate an image From 52b1db7343ac543d758cf940d4302527ad4e279b Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 10:55:32 -0400 Subject: [PATCH 5/8] chore: fixed broken link --- ...g-an-og-image-using-react-and-netlify-edge-functions-563a.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md index 54073f14..8d344bb3 100644 --- a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md @@ -6,7 +6,7 @@ slug: 2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563 description: "Open Graph (OG) images are a must if you're sharing content on the Internet. From sites like..." --- -[Open Graph](url) (OG) images are a must if you're sharing content on the Internet. From sites like X/Twitter, to Slack or Discord, a great OG image makes your link share pop. +[Open Graph](https://ogp.me/) (OG) images are a must if you're sharing content on the Internet. From sites like X/Twitter, to Slack or Discord, a great OG image makes your link share pop. ## Examples From 1cda66310cbc5fc63d105a1c0877dd48bfbf8c3d Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 11:11:22 -0400 Subject: [PATCH 6/8] chore: fixed slugs --- ... 2023-09-21-supercharge-your-repository-with-code-owners.md} | 2 +- ...d => 2023-10-31-github-actions-a-maintainers-best-friend.md} | 2 +- ....md => 2023-11-14-boost-productivity-with-the-github-cli.md} | 2 +- ...migrating-from-jest-to-vitest-for-your-react-application.md} | 2 +- ...-1nhn.md => 2024-01-23-the-native-browser-dialog-element.md} | 2 +- ...eptics-unveiling-the-undeniable-goodness-of-tailwind-css.md} | 2 +- ...-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md | 2 +- ...and-function-how-i-lost-my-submit-button-got-it-back-5b91.md | 2 +- ...g-an-og-image-using-react-and-netlify-edge-functions-563a.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) rename blog/2023/{2023-09-21-supercharge-your-repository-with-code-owners-4clg.md => 2023-09-21-supercharge-your-repository-with-code-owners.md} (98%) rename blog/2023/{2023-10-31-github-actions-a-maintainers-best-friend-488n.md => 2023-10-31-github-actions-a-maintainers-best-friend.md} (98%) rename blog/2023/{2023-11-14-boost-productivity-with-the-github-cli-2mne.md => 2023-11-14-boost-productivity-with-the-github-cli.md} (99%) rename blog/2023/{2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md => 2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md} (98%) rename blog/2024/{2024-01-23-the-native-browser-dialog-element-1nhn.md => 2024-01-23-the-native-browser-dialog-element.md} (98%) rename blog/2024/{2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md => 2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md} (98%) diff --git a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md similarity index 98% rename from blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md rename to blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md index 003b6372..171661f9 100644 --- a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners-4clg.md +++ b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md @@ -2,7 +2,7 @@ title: "Supercharge your Repository with Code Owners" tags: [] authors: nickytonline -slug: 2023-09-21-supercharge-your-repository-with-code-owners-4clg +slug: supercharge-your-repository-with-code-owners description: "As a maintainer of a repository, it’s in your best interest to automate processes as much as..." --- diff --git a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md similarity index 98% rename from blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md rename to blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md index 814ed918..2992bad9 100644 --- a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend-488n.md +++ b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md @@ -2,7 +2,7 @@ title: "GitHub Actions: A Maintainer's Best Friend" tags: [] authors: nickytonline -slug: 2023-10-31-github-actions-a-maintainers-best-friend-488n +slug: github-actions-a-maintainers-best-friend description: "As developers, it’s in our best interest to automate things. The less we have to do in a manual way,..." --- diff --git a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md similarity index 99% rename from blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md rename to blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md index 203fdb4b..43aa9f88 100644 --- a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli-2mne.md +++ b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md @@ -2,7 +2,7 @@ title: "Boost productivity with the GitHub CLI" tags: [] authors: nickytonline -slug: 2023-11-14-boost-productivity-with-the-github-cli-2mne +slug: boost-productivity-with-the-github-cli description: "The GitHub CLI is an indispensable tool as a project maintainer or contributor on GitHub. It can..." --- diff --git a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md similarity index 98% rename from blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md rename to blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md index a2fc5e58..fe665f4f 100644 --- a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75.md +++ b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md @@ -2,7 +2,7 @@ title: "Migrating from Jest to Vitest for your React Application" tags: [] authors: nickytonline -slug: 2023-12-14-migrating-from-jest-to-vitest-for-your-react-application-1b75 +slug: migrating-from-jest-to-vitest-for-your-react-application description: "Are you looking to migrate from Jest to Vitest for your React application? Look no further. I..." --- diff --git a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md b/blog/2024/2024-01-23-the-native-browser-dialog-element.md similarity index 98% rename from blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md rename to blog/2024/2024-01-23-the-native-browser-dialog-element.md index fc7bcfce..125a5c6f 100644 --- a/blog/2024/2024-01-23-the-native-browser-dialog-element-1nhn.md +++ b/blog/2024/2024-01-23-the-native-browser-dialog-element.md @@ -2,7 +2,7 @@ title: "Unlocking the Power of HTML's Native Browser Dialog Element" tags: [] authors: nickytonline -slug: 2024-01-23-the-native-browser-dialog-element-1nhn +slug: the-native-browser-dialog-element description: "All the major browsers now support the <dialog > element. Why add this HTML element? User land..." --- diff --git a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md similarity index 98% rename from blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md rename to blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md index 47b54cf3..29af9a27 100644 --- a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc.md +++ b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md @@ -2,7 +2,7 @@ title: "Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS" tags: [] authors: nickytonline -slug: 2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css-4doc +slug: challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css description: "People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but..." --- diff --git a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md index 896551e7..8b617b70 100644 --- a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md +++ b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md @@ -2,7 +2,7 @@ title: "Stuck in the Middle with You: An intro to Middleware" tags: [] authors: nickytonline -slug: 2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo +slug: stuck-in-the-middle-with-you-an-intro-to-middleware description: "Middleware exists in several frameworks like Next.js, Express, Hono and Fresh, and not just in..." --- diff --git a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md index 8389bbc6..a8c2c27d 100644 --- a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md +++ b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md @@ -2,7 +2,7 @@ title: "Form and Function: How I Lost My Submit Button & Got It Back" tags: [] authors: nickytonline -slug: 2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91 +slug: form-and-function-how-i-lost-my-submit-button-got-it-back description: "As web developers, we know that most of the create, read update, and delete (CRUD) actions we perform..." --- diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md index 8d344bb3..cd9f7786 100644 --- a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md @@ -2,7 +2,7 @@ title: "Creating an OG image using React and Netlify Edge Functions" tags: [] authors: nickytonline -slug: 2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a +slug: creating-an-og-image-using-react-and-netlify-edge-functions description: "Open Graph (OG) images are a must if you're sharing content on the Internet. From sites like..." --- From 1b6602126bf1a8a869cd9dae790c84e7cf9bba1a Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 17:04:48 -0400 Subject: [PATCH 7/8] chore: renamed files to remove dev.to slug post-fix --- ...-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md} | 0 ...-form-and-function-how-i-lost-my-submit-button-got-it-back.md} | 0 ...reating-an-og-image-using-react-and-netlify-edge-functions.md} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename blog/2024/{2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md => 2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md} (100%) rename blog/2024/{2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md => 2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md} (100%) rename blog/2024/{2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md => 2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md} (100%) diff --git a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md similarity index 100% rename from blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware-1gjo.md rename to blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md diff --git a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md similarity index 100% rename from blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back-5b91.md rename to blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md similarity index 100% rename from blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions-563a.md rename to blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md From 6a908eceec2af2a066451cb7ad2f7805e87b5f6a Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Mon, 10 Jun 2024 17:11:25 -0400 Subject: [PATCH 8/8] chore: added tags to @nickytonline's blog posts --- .../2023-09-21-supercharge-your-repository-with-code-owners.md | 2 +- .../2023/2023-10-31-github-actions-a-maintainers-best-friend.md | 2 +- blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md | 2 +- ...-migrating-from-jest-to-vitest-for-your-react-application.md | 2 +- blog/2024/2024-01-23-the-native-browser-dialog-element.md | 2 +- ...keptics-unveiling-the-undeniable-goodness-of-tailwind-css.md | 2 +- ...03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md | 2 +- ...form-and-function-how-i-lost-my-submit-button-got-it-back.md | 2 +- ...eating-an-og-image-using-react-and-netlify-edge-functions.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md index 171661f9..d9a6c5c2 100644 --- a/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md +++ b/blog/2023/2023-09-21-supercharge-your-repository-with-code-owners.md @@ -1,6 +1,6 @@ --- title: "Supercharge your Repository with Code Owners" -tags: [] +tags: ["github", "opensource", "productivity", "security"] authors: nickytonline slug: supercharge-your-repository-with-code-owners description: "As a maintainer of a repository, it’s in your best interest to automate processes as much as..." diff --git a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md index 2992bad9..5cea5710 100644 --- a/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md +++ b/blog/2023/2023-10-31-github-actions-a-maintainers-best-friend.md @@ -1,6 +1,6 @@ --- title: "GitHub Actions: A Maintainer's Best Friend" -tags: [] +tags: ["githubactions", "automation", "opensource", "productivity"] authors: nickytonline slug: github-actions-a-maintainers-best-friend description: "As developers, it’s in our best interest to automate things. The less we have to do in a manual way,..." diff --git a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md index 43aa9f88..8e13ef23 100644 --- a/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md +++ b/blog/2023/2023-11-14-boost-productivity-with-the-github-cli.md @@ -1,6 +1,6 @@ --- title: "Boost productivity with the GitHub CLI" -tags: [] +tags: ["github", "cli", "git", "productivity"] authors: nickytonline slug: boost-productivity-with-the-github-cli description: "The GitHub CLI is an indispensable tool as a project maintainer or contributor on GitHub. It can..." diff --git a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md index fe665f4f..ed211a53 100644 --- a/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md +++ b/blog/2023/2023-12-14-migrating-from-jest-to-vitest-for-your-react-application.md @@ -1,6 +1,6 @@ --- title: "Migrating from Jest to Vitest for your React Application" -tags: [] +tags: ["testing", "react", "vitest", "typescript"] authors: nickytonline slug: migrating-from-jest-to-vitest-for-your-react-application description: "Are you looking to migrate from Jest to Vitest for your React application? Look no further. I..." diff --git a/blog/2024/2024-01-23-the-native-browser-dialog-element.md b/blog/2024/2024-01-23-the-native-browser-dialog-element.md index 125a5c6f..95342ba6 100644 --- a/blog/2024/2024-01-23-the-native-browser-dialog-element.md +++ b/blog/2024/2024-01-23-the-native-browser-dialog-element.md @@ -1,6 +1,6 @@ --- title: "Unlocking the Power of HTML's Native Browser Dialog Element" -tags: [] +tags: ["html", "javascript", "a11y", "css"] authors: nickytonline slug: the-native-browser-dialog-element description: "All the major browsers now support the <dialog > element. Why add this HTML element? User land..." diff --git a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md index 29af9a27..9605c97c 100644 --- a/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md +++ b/blog/2024/2024-02-06-challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css.md @@ -1,6 +1,6 @@ --- title: "Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS" -tags: [] +tags: ["css", "tailwindcss", "webdev"] authors: nickytonline slug: challenging-the-skeptics-unveiling-the-undeniable-goodness-of-tailwind-css description: "People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but..." diff --git a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md index 8b617b70..a7fd3662 100644 --- a/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md +++ b/blog/2024/2024-03-14-stuck-in-the-middle-with-you-an-intro-to-middleware.md @@ -1,6 +1,6 @@ --- title: "Stuck in the Middle with You: An intro to Middleware" -tags: [] +tags: ["webdev", "beginners", "frameworks", "javascript"] authors: nickytonline slug: stuck-in-the-middle-with-you-an-intro-to-middleware description: "Middleware exists in several frameworks like Next.js, Express, Hono and Fresh, and not just in..." diff --git a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md index a8c2c27d..eee2d422 100644 --- a/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md +++ b/blog/2024/2024-04-02-form-and-function-how-i-lost-my-submit-button-got-it-back.md @@ -1,6 +1,6 @@ --- title: "Form and Function: How I Lost My Submit Button & Got It Back" -tags: [] +tags: ["html", "webdev", "beginners"] authors: nickytonline slug: form-and-function-how-i-lost-my-submit-button-got-it-back description: "As web developers, we know that most of the create, read update, and delete (CRUD) actions we perform..." diff --git a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md index cd9f7786..5c48f4fe 100644 --- a/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md +++ b/blog/2024/2024-04-16-creating-an-og-image-using-react-and-netlify-edge-functions.md @@ -1,6 +1,6 @@ --- title: "Creating an OG image using React and Netlify Edge Functions" -tags: [] +tags: ["netlify", "typescript", "react"] authors: nickytonline slug: creating-an-og-image-using-react-and-netlify-edge-functions description: "Open Graph (OG) images are a must if you're sharing content on the Internet. From sites like..."