<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 1Password</title>
    <description>The latest articles on DEV Community by 1Password (@1password).</description>
    <link>https://dev.to/1password</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F447%2Fc92dac9e-3758-42ab-8b72-5153a659a244.png</url>
      <title>DEV Community: 1Password</title>
      <link>https://dev.to/1password</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/1password"/>
    <language>en</language>
    <item>
      <title>Join the 1Password Hackathon hosted by Hashnode and compete for $10,000 in prizes</title>
      <dc:creator>Jason Harris</dc:creator>
      <pubDate>Thu, 01 Jun 2023 22:13:07 +0000</pubDate>
      <link>https://dev.to/1password/join-the-1password-hackathon-hosted-by-hashnode-and-compete-for-10000-in-prizes-4lpo</link>
      <guid>https://dev.to/1password/join-the-1password-hackathon-hosted-by-hashnode-and-compete-for-10000-in-prizes-4lpo</guid>
      <description>&lt;p&gt;&lt;em&gt;We love hackathons. In fact, that’s where the idea for 1Password came from – with all-night coding sessions that demanded credentials throughout the process.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hackathons are high-energy, creative marathons that serve as a playground for innovation and collaboration, and often result in exciting projects that are a joy to deliver. That’s why we’re excited to announce the first virtual &lt;a href="https://hashnode.com/hackathons/1password" rel="noopener noreferrer"&gt;1Password Hackathon&lt;/a&gt; hosted by Hashnode.&lt;/p&gt;

&lt;p&gt;Taking place June 1st through June 30th, participants will compete for a chance to win $10,000 in cash prizes by building with &lt;a href="https://1password.com/developers" rel="noopener noreferrer"&gt;1Password Developer Tools&lt;/a&gt; and &lt;a href="https://passage.1password.com/" rel="noopener noreferrer"&gt;Passage by 1Password&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As much fun as in-person hackathons are, we’re also big fans of virtual ones that are global in scope and inclusive of all skill levels. If you’re a developer looking to sharpen your skills, network with like-minded individuals, and craft something extraordinary, the Hashnode Hackathon should be on your list. There are 10,000 reasons why – and utilizing 1Password Developer Tools and Passage can make your experience even better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your mission – and the tools in your toolbelt
&lt;/h2&gt;

&lt;p&gt;1Password Developer Tools brings the speed and security of biometrics to your dev workflows. Passage unlocks passwordless sign-in – powered by passkeys – for your users. &lt;strong&gt;Hackathon participants will receive two free months of 1Password and 1Password Developer Tools, including Shell Plugins and 1Password CLI for new customers&lt;/strong&gt;. For Passage, the free tier will suffice for hackathon purposes.&lt;/p&gt;

&lt;p&gt;Let’s talk details. For the hackathon event, we’re challenging you to build with or on top of these tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.passage.id/getting-started/quickstart" rel="noopener noreferrer"&gt;Passage by 1Password&lt;/a&gt;: The easiest way to implement passkey authentication in your app or website.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/cli/shell-plugins" rel="noopener noreferrer"&gt;1Password Shell Plugins&lt;/a&gt;: Eliminate API access keys stored on disc and securely authenticate any CLI with your fingerprint, Apple Watch, or other biometrics.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/cli" rel="noopener noreferrer"&gt;1Password CLI&lt;/a&gt;: Automate administrative tasks, securely provision secrets across development environments, and use biometrics to authenticate in the terminal.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What are 1Password Developer Tools?
&lt;/h2&gt;

&lt;p&gt;1Password is a password management platform used extensively in the developer community, in part because of features designed specifically for developers.&lt;/p&gt;

&lt;p&gt;With 1Password Developer Tools, you can securely store passwords, API keys, and other secrets, then access them in your code or easily share with your team members. This not only makes your project more secure but also simplifies collaboration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Passage by 1Password?
&lt;/h2&gt;

&lt;p&gt;Passage allows you to implement seamless passwordless authentication in your app or website with just a few lines of code. Eliminate passwords for good with Passkey Complete, a standalone solution that defaults to passkeys with fallbacks to other passwordless methods. Or use Passkey Flex to add support for passkeys alongside your existing password-based auth flow. Passage takes care of authentication so you can focus on the core logic of your hackathon project.&lt;/p&gt;

&lt;p&gt;During the June Hackathon, we invite you to show off your skills and submit a project that expands Passage by integrating it with other platforms, like &lt;a href="https://supabase.com/docs/guides/integrations/passage" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt;. Or, you could build one that shows a creative way &lt;a href="https://docs.passage.id/getting-started/quickstart" rel="noopener noreferrer"&gt;Passage&lt;/a&gt; can be used to streamline sign-in for your application or service.&lt;/p&gt;

&lt;p&gt;Want to really impress the judges? Make your project multi-platform and show how Passage works across systems and devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples from the community
&lt;/h2&gt;

&lt;p&gt;1Password wouldn’t be 1Password without the developer community. In fact, more than half of our published Shell Plugins have been written by the community!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm6fvylafi923uqqn9if.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpm6fvylafi923uqqn9if.gif" alt="Stripe API key being saved in 1Password directly from VS Code with the 1Password VS Code extension"&gt;&lt;/a&gt;&lt;br&gt;
We’ve seen some amazing projects and integrations built on the 1Password CLI, including the &lt;a href="https://developer.1password.com/docs/vscode/" rel="noopener noreferrer"&gt;VS Code integration&lt;/a&gt; and a community-written &lt;a href="https://blog.1password.com/1password-jetbrains/" rel="noopener noreferrer"&gt;JetBrains integration&lt;/a&gt;. And we can’t wait to see what Hackathon participants build to extend Passage to new frameworks and platforms. If you’re looking for inspiration, we’d love to see more integrations like the newly published &lt;a href="https://supabase.com/docs/guides/integrations/passage" rel="noopener noreferrer"&gt;Supabase package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And for even more projects contributed by the community, see the &lt;a href="https://developer.1password.com/community" rel="noopener noreferrer"&gt;1Password Community Showcase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get started, &lt;a href="https://hashnode.com/hackathons/1password" rel="noopener noreferrer"&gt;register to participate with Hashnode&lt;/a&gt;. You’ll receive an email containing a coupon code and instructions to redeem your two free months of 1Password for new customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get support from the 1Password community
&lt;/h2&gt;

&lt;p&gt;Need some guidance to help you get started – or to stay on track? We’re here to help.&lt;/p&gt;

&lt;p&gt;Chat with other devs in our &lt;a href="https://join.slack.com/t/1password-devs/shared_invite/zt-1halo11ps-6o9pEv96xZ3LtX_VE0fJQA" rel="noopener noreferrer"&gt;Developer Slack community&lt;/a&gt; and on the &lt;a href="https://discord.com/invite/hashnode" rel="noopener noreferrer"&gt;Hashnode Discord&lt;/a&gt;.&lt;br&gt;
Set up a pair programming session with our engineers. To request a session, see the instructions in the Discord channel.&lt;br&gt;
We’ll have two live events in June including the &lt;a href="https://www.youtube.com/watch?v=CJlI0BEt384" rel="noopener noreferrer"&gt;Hashnode Workshop&lt;/a&gt; with demos and Q&amp;amp;A on June 7th and a &lt;a href="https://1password.zoom.us/meeting/register/tJwkfuyhrD4pGdCs_NCEPWvWmAIzmUlFJEat" rel="noopener noreferrer"&gt;Community Office Hour on June 23rd&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Good luck to all participants!
&lt;/h2&gt;

&lt;p&gt;This hackathon is an exciting community project and we look forward to meeting and learning from you! We’ll be watching all the action on Discord, our Developer Slack, and GitHub. Please be sure to use #Buildwith1Password so we can help spread the word and profile your work!&lt;/p&gt;

&lt;p&gt;Let’s get hacking!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Please note, this hackathon is a Hashnode contest and terms and conditions apply. You can find all applicable details on &lt;a href="https://hashnode.com/hackathons/1password" rel="noopener noreferrer"&gt;the contest website&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>programming</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Unlock any CLI using biometrics with 1Password Shell Plugins</title>
      <dc:creator>Jason Harris</dc:creator>
      <pubDate>Wed, 07 Dec 2022 17:49:08 +0000</pubDate>
      <link>https://dev.to/1password/unlock-any-cli-using-biometrics-with-1password-shell-plugins-n1</link>
      <guid>https://dev.to/1password/unlock-any-cli-using-biometrics-with-1password-shell-plugins-n1</guid>
      <description>&lt;p&gt;I love Touch ID. When I use it to log in to a site or authorize a purchase, authentication just kind of &lt;em&gt;happens&lt;/em&gt;. It doesn’t feel futuristic anymore, but it does feel like the present. It’s the modern computing experience.&lt;br&gt;
​&lt;br&gt;
Then I open my terminal, and I'm transported right back to the past. Why can't devs have that modern experience?&lt;br&gt;
​&lt;br&gt;
I know I'm not alone. When we introduced Touch ID support for &lt;a href="https://blog.1password.com/1password-cli-2_0/" rel="noopener noreferrer"&gt;1Password CLI 2.0&lt;/a&gt;, one of the most frequent pieces of feedback we heard was: Can we have touch ID for &lt;em&gt;all&lt;/em&gt; CLIs? &lt;br&gt;
​&lt;br&gt;
So, about that. &lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing 1Password Shell Plugins
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figuomkv9cpgr59h73mt7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figuomkv9cpgr59h73mt7.gif" alt="Image description" width="1300" height="813"&gt;&lt;/a&gt;&lt;br&gt;
​&lt;br&gt;
We use CLIs to perform quick actions from the comfort of our terminals and automate recurring tasks. You might use the &lt;a href="https://about.gitlab.com/blog/2022/12/07/introducing-the-gitlab-cli/" rel="noopener noreferrer"&gt;GitLab CLI&lt;/a&gt; to submit your code in a merge request, so the team can review it and include it in the next release, for example. Many other developer platforms like &lt;a href="https://aws.amazon.com/cli/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;, &lt;a href="https://stripe.com/docs/stripe-cli" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt;, &lt;a href="https://docs.sentry.io/product/cli/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;, and &lt;a href="https://circleci.com/docs/local-cli/" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt; offer CLIs as well.&lt;br&gt;
​&lt;br&gt;
Connecting a CLI to your online account often involves generating API access keys in a browser, then pasting those values into the terminal. Those credentials are usually saved in a plaintext config file that gives the CLI persistent access to your account, even after reboots. But if an attacker or process gains access to your system, they have the same level of access to your account that you do. &lt;br&gt;
​&lt;br&gt;
We built &lt;a href="https://developer.1password.com/docs/cli/shell-plugins" rel="noopener noreferrer"&gt;1Password Shell Plugins&lt;/a&gt; so you can securely store all of your access keys in encrypted 1Password vaults, rather than on disk. When you use a Shell Plugin for a particular service, access to the associated API keys is restricted to your specific terminal session. &lt;br&gt;
​&lt;br&gt;
Because they're saved in 1Password, you can securely sign in to any CLI with your fingerprint or another form of biometrics. If the service supports it, MFA codes can be filled automatically  – so there’s no need to pull out your phone multiple times every day.&lt;br&gt;
​&lt;br&gt;
In fact, there’s no need to type &lt;em&gt;anything&lt;/em&gt;. No plaintext, no typing passwords, no hassle – you can stay in the zone and focus on the task at hand. &lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Extensibility built in
&lt;/h2&gt;

&lt;p&gt;​&lt;br&gt;
We’ve already built Shell Plugins for many popular CLIs, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/gitlab" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/circleci" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/aws" rel="noopener noreferrer"&gt;Amazon Web Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/sentry" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt; (Get $240 in Sentry credits with code “1Password”) &lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/stripe" rel="noopener noreferrer"&gt;Stripe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/twilio" rel="noopener noreferrer"&gt;Twilio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/github" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
​&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are &lt;a href="https://developer.1password.com/docs/cli/shell-plugins" rel="noopener noreferrer"&gt;many more pre-built integrations&lt;/a&gt;, but you’re not limited to the ones we built. You can build your own, for any CLI. &lt;br&gt;
​&lt;br&gt;
Shell Plugins are fully extensible and aren’t restricted to specific services. If you don't see an integration you need, you can join the open source project (currently in beta) and &lt;a href="https://developer.1password.com/docs/cli/shell-plugins/contribute/" rel="noopener noreferrer"&gt;contribute your own&lt;/a&gt;. &lt;br&gt;
​&lt;br&gt;
Want to add MFA support to an existing Shell Plugin? You can do that too.&lt;br&gt;
​&lt;br&gt;
​&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Many of our users rely on GitLab to shorten code review cycles, increase their developer productivity and strengthen overall security at every step. 1Password’s latest rollout is an important development in that last bucket. Launching Shell Plugins will help ensure developers can access our tools in their terminals as quickly and securely as possible.&lt;/em&gt; – Kai Armstrong, senior product manager, GitLab&lt;br&gt;
​&lt;/p&gt;
&lt;h2&gt;
  
  
  Your keys, but portable
&lt;/h2&gt;

&lt;p&gt;​&lt;br&gt;
Storing your keys in 1Password means you can use them &lt;em&gt;everywhere&lt;/em&gt;. If you switch to a different machine, system, or environment, the process is exactly the same. &lt;br&gt;
​&lt;br&gt;
Just install and configure Shell Plugins on your machine, then use biometrics to grant access to your key in 1Password. If the plugin supports MFA, you can use 1Password to autofill the codes.&lt;br&gt;
​&lt;br&gt;
This all makes setup, developer onboarding, and collaboration simpler. If new teammates are in the relevant group in 1Password, they already have the permissions they need to access the shared credentials and contribute immediately. All they have to do is install the &lt;a href="https://1password.com/downloads/command-line/" rel="noopener noreferrer"&gt;1Password CLI&lt;/a&gt; and the appropriate Shell Plugins.&lt;br&gt;
​&lt;/p&gt;
&lt;h2&gt;
  
  
  How Shell Plugins work
&lt;/h2&gt;

&lt;p&gt;​&lt;br&gt;
Once you've set up 1Password CLI, you can install a supported Shell Plugin with a single command. For example, to install the plugin for GitLab, you would run:&lt;br&gt;
​&lt;br&gt;
&lt;code&gt;op plugin init glab&lt;/code&gt;&lt;br&gt;
​&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27flmwv6vc6oclzp9r8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27flmwv6vc6oclzp9r8o.png" alt="Image description" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
​&lt;br&gt;
During the configuration process, you can import existing credentials from your config file or create new credentials in 1Password. &lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jjcspqd1epzjnhd2ouc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jjcspqd1epzjnhd2ouc.png" alt="Image description" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
​&lt;br&gt;
At this point, your credentials are safely stored in 1Password, so you can remove them from your disk. &lt;br&gt;
​&lt;br&gt;
&lt;a href="https://developer.1password.com/docs/cli/shell-plugins/" rel="noopener noreferrer"&gt;Check out the developer docs&lt;/a&gt; to learn more about Shell Plugins.&lt;br&gt;
​&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0ywimmrzua7h9uyz86a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0ywimmrzua7h9uyz86a.png" alt="Image description" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing CI/CD integrations
&lt;/h2&gt;

&lt;p&gt;​&lt;br&gt;
One more thing. When you’re setting up a CI/CD workflow, you often need to manually enter secrets by visiting the settings page of the tool you’re using. But now you can store those secrets in 1Password, too. &lt;br&gt;
​&lt;br&gt;
You can access them directly within your CI/CD tools – and reference their location in 1Password directly within the job that requires them – via new integrations for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://developer.1password.com/docs/ci-cd/circle-ci" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://developer.1password.com/docs/ci-cd/jenkins" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.1password.com/docs/ci-cd/github-actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;
​&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, feel free to &lt;a href="https://developer.1password.com/docs/ci-cd/" rel="noopener noreferrer"&gt;jump into the documentation&lt;/a&gt; to get started.&lt;br&gt;
​&lt;/p&gt;

&lt;h2&gt;
  
  
  Securing the software development life cycle
&lt;/h2&gt;

&lt;p&gt;​&lt;br&gt;
Our goal is to bring this same level of security and ease of use to the entire &lt;a href="https://1password.com/developers/" rel="noopener noreferrer"&gt;software development life cycle&lt;/a&gt;. My colleague, Marc Mackenbach, has written about &lt;a href="https://blog.1password.com/developers-deserve-great-ux/" rel="noopener noreferrer"&gt;how far the developer user experience has to go&lt;/a&gt; before it catches up with the consumer experience in terms of both security and UX.&lt;br&gt;
​&lt;br&gt;
We're working on that. Check out &lt;a href="https://1password.com/developers/" rel="noopener noreferrer"&gt;1Password.com/developers&lt;/a&gt; for a quick overview of everything we’re building to secure developer workflows. In the meantime, feel free to &lt;a href="https://developer.1password.com/docs/cli/shell-plugins/" rel="noopener noreferrer"&gt;start exploring the Shell Plugins documentation&lt;/a&gt;. &lt;br&gt;
​&lt;br&gt;
And maybe keep your phone in your pocket. You won’t need it nearly as often anymore. 😉&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ruby</category>
      <category>python</category>
    </item>
    <item>
      <title>Brick by brick: why Docusaurus is a powerful documentation framework</title>
      <dc:creator>Jody Heavener</dc:creator>
      <pubDate>Wed, 06 Jul 2022 15:33:34 +0000</pubDate>
      <link>https://dev.to/1password/brick-by-brick-why-docusaurus-is-a-powerful-documentation-framework-15a9</link>
      <guid>https://dev.to/1password/brick-by-brick-why-docusaurus-is-a-powerful-documentation-framework-15a9</guid>
      <description>&lt;p&gt;&lt;em&gt;At 2022’s AGConf (1Password’s annual employee conference), every employee received a goodie box to celebrate the event and the company’s successes over the past year. Our theme this year was “space”, so the goodie box included a kit for a Lego rocket ship (very appropriate considering our own CEO is a &lt;a href="https://twitter.com/jeffreyshiner/status/978497319283834880" rel="noopener noreferrer"&gt;Lego aficionado&lt;/a&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building the spaceship brought me back to when I was younger and played endlessly with those little bricks.&lt;/p&gt;

&lt;p&gt;For me, though, it wasn’t so much about building the specific items in a kit. Sure, I absolutely loved putting together the houses and planes and cars, but what I was most fascinated by was how I could use tiny bricks to expand my creation and build anything I could dream up. The possibilities were endless, my imagination ran wild, and sometimes – usually through through dumb luck – I built something way cooler than what the kit offered in the first place.&lt;/p&gt;

&lt;p&gt;Late last year, I started exploring the React-based documentation framework &lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt;, and  spent a good chunk of time going through the documentation. (Surprise! They use their own product!) I got pretty familiar with how it works under the hood, and the ways in which it can be expanded on. It's also got a &lt;a href="https://docusaurus.io/community/support" rel="noopener noreferrer"&gt;bustling community&lt;/a&gt;, which is unsurprising since it’s entirely open source. &lt;/p&gt;

&lt;p&gt;When I joined 1Password earlier this year, where I would be driving the effort to stand up a &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;developer portal&lt;/a&gt; for our new developer offerings, I was excited to learn that we’d chosen Docusaurus v2 as the framework to power it all. I’ve had a chance to really dig in since then, learning as much as I could about this powerful little static site generator. &lt;/p&gt;

&lt;p&gt;And it occurred to me recently that, with the way they’ve set it up, I’m reminded of those Lego creations: at its core it’s really just a bunch of individual pieces cleverly interlocked to create something far greater. It’s also built on a foundation designed to be entirely extensible.&lt;/p&gt;

&lt;p&gt;So I’d like to look at how Docusaurus is put together, and why it’s so great for &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;the 1Password developer portal&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Plugins all the way down
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Plugins are the building blocks of features in a Docusaurus 2 site. Each plugin handles its own individual feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Docusaurus has handy plugin &lt;a href="https://docusaurus.io/docs/api/plugin-methods/lifecycle-apis" rel="noopener noreferrer"&gt;lifecycle APIs&lt;/a&gt;. When you start up the development server or generate a static bundle, each plugin kicks in and traverses through every stage of the lifecycle. With it, you can pull in data across all plugins simultaneously, register routes, validate configuration, and inject HTML tags, among many other things. Docusaurus leverages these same APIs to build up the overall user-facing functionality of the framework through their own collection of &lt;a href="https://docusaurus.io/docs/api/plugins" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Consider the primary use case for Docusaurus: documentation. The &lt;a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-docs" rel="noopener noreferrer"&gt;@docusaurus/plugin-content-docs plugin&lt;/a&gt; powers this central feature for the framework. Its more immediate functionality comes from using the &lt;code&gt;loadContent&lt;/code&gt; method to look for potentially localized and versioned sets of documentation on the filesystem, and &lt;code&gt;contentLoaded&lt;/code&gt; to provide the structured route data for the core to register and produce HTML files. It also extends Docusaurus’ CLI to allow for tagging a new docs version, and even tells the dev server which files to watch, and in turn run the lifecycles again.&lt;/p&gt;

&lt;p&gt;The documentation plugin is obviously a huge part of Docusaurus, but they don’t stop there.  Everything from the docs, to &lt;a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-blog" rel="noopener noreferrer"&gt;blogging&lt;/a&gt; and &lt;a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-pages" rel="noopener noreferrer"&gt;individual pages&lt;/a&gt;, all the way down to setting up &lt;a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-google-analytics" rel="noopener noreferrer"&gt;Google Analytics&lt;/a&gt; and &lt;a href="https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-sitemap" rel="noopener noreferrer"&gt;generating sitemaps&lt;/a&gt; are all powered by plugins.&lt;/p&gt;

&lt;p&gt;So, why is this important?&lt;/p&gt;

&lt;p&gt;If you’ll allow me to borrow my Lego analogy again: Docusaurus’ plugin APIs mean that, while they provide you with a kit you can set up and build something really cool with, they’ve also provided you with the ability to extend the framework in any direction to build something to suit your exact needs (at least as far as static sites go). &lt;/p&gt;

&lt;p&gt;Great examples of this can be found on their &lt;a href="https://docusaurus.io/community/resources#community-plugins" rel="noopener noreferrer"&gt;community plugins&lt;/a&gt; page, where others have built plugins for &lt;a href="https://github.com/easyops-cn/docusaurus-search-local" rel="noopener noreferrer"&gt;offline/local search&lt;/a&gt; (we even use this today), adding &lt;a href="https://github.com/rlamana/docusaurus-plugin-sass" rel="noopener noreferrer"&gt;SASS styles loading&lt;/a&gt;, and &lt;a href="https://github.com/rohit-gohri/redocusaurus" rel="noopener noreferrer"&gt;consuming OpenAPI specs&lt;/a&gt; to generate full API documentation pages. And it couldn’t be easier to roll your own. &lt;/p&gt;

&lt;p&gt;Let’s say you wanted to load in some Google Fonts. Here’s what a plugin that does this by using the &lt;code&gt;injectHtmlTags&lt;/code&gt; method might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluginGoogleFonts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;plugin-google-fonts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="na"&gt;injectHtmlTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Tell the browser we're going to be loading resources from these origins&lt;/span&gt;
      &lt;span class="na"&gt;headTags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preconnect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.googleapis.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;preconnect&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.gstatic.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;crossorigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;anonymous&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// Load the Lobster font&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;attributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;rel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stylesheet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://fonts.googleapis.com/css2?family=Lobster&amp;amp;display=swap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this plugin in place, you can now freely use the Lobster font in your CSS. If you wanted to take it a step further and package this plugin up for distribution, you could even allow it to take an array of font names and weights as options to make it truly dynamic.&lt;/p&gt;

&lt;p&gt;In the future, as we expand our developer portal, you’re likely to see us build plugins for things like importing and rendering &lt;a href="https://blog.1password.com/categories/developers/" rel="noopener noreferrer"&gt;developer blog posts&lt;/a&gt;, highlighting integrations built by our developer community, and a whole lot more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Need to customize it? Swizzle away.
&lt;/h2&gt;

&lt;p&gt;Plugins aren’t limited to just extending functionality, either. They’re what also delivers the look of the framework. Using the &lt;code&gt;getThemePath&lt;/code&gt; method your plugin can tell Docusaurus where to find the React components that make up a theme, selectively overriding components from an existing theme or building your own theme from the ground up.&lt;/p&gt;

&lt;p&gt;One of the neatest features of Docusaurus is the ability to &lt;a href="https://docusaurus.io/docs/swizzling" rel="noopener noreferrer"&gt;Swizzle a component&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[Swizzling] comes from Objective-C and Swift-UI: method swizzling is the process of changing the implementation of an existing selector (method). For Docusaurus, component swizzling means providing an alternative component that takes precedence over the component provided by the theme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What does this mean in practice? Well, our developer portal currently uses the default &lt;a href="https://docusaurus.io/docs/next/api/themes/@docusaurus/theme-classic" rel="noopener noreferrer"&gt;Classic theme&lt;/a&gt;, but if you check out our footer you’ll notice that it looks nothing like the footer in that theme. We wanted ours to share a consistent look with the one on &lt;a href="https://1password.com/" rel="noopener noreferrer"&gt;1Password.com&lt;/a&gt;, so we swizzled the existing Footer component by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run swizzle @docusaurus/theme-classic Footer &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--eject&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This cloned the component out of the Docusaurus package and into our workspace. Now we've got full agency over the look and feel of the site’s footer, while still being able to rely on the rest of the theme’s components, which also includes future updates. We’re going to be swizzling a fair bit this year as the developer portal evolves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4kh5vqeyeddog0zros6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc4kh5vqeyeddog0zros6.png" alt="The default Footer component versus our swizzled Footer component to match the 1Password.com style."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The framework ships with the Classic theme, and out of the box it does a fantastic job. As of April 2022 the theme selection is fairly limited for v2 of Docusaurus, with only the Classic theme and some extensions to it available. More are coming, though. One that I’m particularly looking forward to, a &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;-powered theme, is also a great example of why I appreciate that they’re an open source project: it started as a &lt;a href="https://github.com/facebook/docusaurus/issues/2961" rel="noopener noreferrer"&gt;community request&lt;/a&gt;, grew in popularity, and over time evolved into &lt;a href="https://github.com/facebook/docusaurus/issues/2961#issuecomment-1035892969" rel="noopener noreferrer"&gt;part of the roadmap&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Markup or Markdown - how about both?
&lt;/h2&gt;

&lt;p&gt;As with every static site generator, it’s expected that Docusaurus would support Markdown - and they took it a step further, using &lt;a href="https://docusaurus.io/docs/markdown-features/react" rel="noopener noreferrer"&gt;MDX&lt;/a&gt; to parse content. MDX allows you to write JSX (React components) alongside your Markdown, allowing seamless native integration with the rest of the React app, which eventually gets all compiled down to HTML. This concept of static site generators interlacing Markdown with another syntax to extend the capabilities of its documentation is not new, but what gets me excited is the power that JSX affords us. You’re not limited to static HTML or shortcodes. Instead you get the full power of JSX components, meaning it’s possible to build fully styled, rich components that you can embed right in your content.&lt;/p&gt;

&lt;p&gt;MDX also supports &lt;a href="https://github.com/remarkjs/remark" rel="noopener noreferrer"&gt;Remark&lt;/a&gt; and &lt;a href="https://github.com/rehypejs/rehype" rel="noopener noreferrer"&gt;Rehype&lt;/a&gt; plugins, allowing you to augment the syntax and replace content on the fly. What can we do with this? Docusaurus demonstrates this well by creating its own plugins for &lt;a href="https://github.com/elviswolcott/remark-admonitions" rel="noopener noreferrer"&gt;admonitions&lt;/a&gt;, &lt;a href="https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-mdx-loader/src/remark/toc/index.ts" rel="noopener noreferrer"&gt;table of contents&lt;/a&gt; generation, and creating &lt;a href="https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-mdx-loader/src/remark/headings/index.ts" rel="noopener noreferrer"&gt;heading links&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There’s already a huge collection of plugins available for both Remark and Rehype, but if you need something a little more tailored to your specific use case creating &lt;a href="https://docusaurus.io/docs/next/markdown-features/plugins#creating-new-rehyperemark-plugins" rel="noopener noreferrer"&gt;these types of plugins&lt;/a&gt; is really straightforward, too. Consider this 13-liner that defaults Markdown code blocks to using Shell highlighting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;visit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;unist-util-visit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pluginRemarkShellCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// If the node is a code block, but the language is not set&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;code&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Set it to Shell&lt;/span&gt;
        &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lang&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shell&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;a href="https://www.npmjs.com/package/unist-util-visit" rel="noopener noreferrer"&gt;unist-util-visit&lt;/a&gt; we can iterate across all nodes and their children to selectively modify the properties or contents of any node that matches our criteria. Now our Markdown files only need to specify language for those code blocks that aren't using Shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fully Open Source
&lt;/h2&gt;

&lt;p&gt;I’ve been heads down in Docusaurus for quite some time now, and it’s proven to be incredibly robust. But beyond the framework itself, I’ve also really appreciated the community behind it. From contributing my &lt;a href="https://github.com/facebook/docusaurus/pulls?q=is%3Apr+author%3Ajodyheavener+sort%3Aupdated-desc+" rel="noopener noreferrer"&gt;own PRs&lt;/a&gt; to the core, to getting help from team members themselves and other eager developers in their &lt;a href="https://discord.gg/docusaurus" rel="noopener noreferrer"&gt;Discord server&lt;/a&gt;, it’s been a pleasure creating with this extraordinary tool.&lt;/p&gt;

&lt;p&gt;Go check out the &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;1Password developer portal&lt;/a&gt;, built with Docusaurus. I’m looking forward to showing off the cool things we’ve got planned for it down the road as we use these building blocks to create something really, really cool.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>docusaurus</category>
      <category>react</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Introducing 1Password for Visual Studio Code</title>
      <dc:creator>Jody Heavener</dc:creator>
      <pubDate>Thu, 23 Jun 2022 15:22:22 +0000</pubDate>
      <link>https://dev.to/1password/introducing-1password-for-visual-studio-code-3b2k</link>
      <guid>https://dev.to/1password/introducing-1password-for-visual-studio-code-3b2k</guid>
      <description>&lt;p&gt;&lt;em&gt;In writing software, we’re used to embedding secrets and other configurable values right in the codebase. They might be Stripe keys to power your online shop, webhooks for a custom Slack bot, a Docker username and password for a CI config, AWS credentials, or an API token and host to set up 1Password &lt;a href="https://developer.1password.com/docs/connect/" rel="noopener noreferrer"&gt;Connect&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Secrets are used everywhere in our code. Sometimes, though, we forget when we’ve been using real secrets in our work. Maybe there’s a leftover token you dropped in to build that one feature, or maybe you didn’t delete the .env file you set up to test drive the app. Now you’ve got to rotate your secrets because you accidentally committed and pushed sensitive values for the whole world to see. Yikes.&lt;/p&gt;

&lt;p&gt;We’ve all been there. That’s why I’m delighted that I get to announce the launch of the all-new &lt;a href="https://developer.1password.com/docs/vscode" rel="noopener noreferrer"&gt;1Password for VS Code extension&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go ahead, commit your &lt;del&gt;secrets&lt;/del&gt; references
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://1password.com/products/secrets/" rel="noopener noreferrer"&gt;1Password Secrets Automation&lt;/a&gt;, the 1Password Developer Products team introduced the concept of &lt;a href="https://developer.1password.com/docs/cli/secrets-reference-syntax" rel="noopener noreferrer"&gt;secret references&lt;/a&gt;. It starts by storing a sensitive value, such as an API credential or client ID, in 1Password. That item and the field you’d like to get the value from can then be retrieved through a special op:// URL scheme that 1Password’s tooling knows how to parse. It’s made up of three parts: vault, item, and field. This is known as a “secret reference”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkam5y0fdkxp9ydm7kog3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkam5y0fdkxp9ydm7kog3.png" alt="1Password Secret Reference example consisting of vault, item, and field"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Now, instead of using a real value in your configs, environment variable files, or anywhere else in the codebase, just drop in the secret reference in VS Code. When you do, you can rest easy knowing that the real value will never accidentally make its way into your codebase.&lt;/p&gt;

&lt;p&gt;The best part? Through our &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;suite of tools and integrations&lt;/a&gt;, you can work with references in both local and deployed environments.&lt;/p&gt;

&lt;p&gt;To help make sure you’re not accidentally leaving secrets in your code, you can move them over to 1Password with just a couple clicks. The extension uses a series of secret detection techniques to look for values that might be sensitive. With these matches, it makes inline suggestions to store them in 1Password, automatically replacing them with secret references.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3cn4w8jkpj9yxrib8lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3cn4w8jkpj9yxrib8lu.png" alt="Example of a secret that would be replaced by the 1Password extension for VS Code"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Secret reference integration doesn’t stop there. You can hover a reference to inspect the item and field details, click it to open the item in the desktop app, and even &lt;a href="https://developer.1password.com/docs/vscode/#inspect-and-preview-secret-references" rel="noopener noreferrer"&gt;preview the real values&lt;/a&gt; of an entire file full of references.&lt;/p&gt;

&lt;p&gt;Beyond &lt;a href="https://developer.1password.com/docs/vscode/#secret-detection" rel="noopener noreferrer"&gt;secret detection&lt;/a&gt; suggestions, 1Password for VS Code makes it easy to &lt;a href="https://developer.1password.com/docs/vscode/#get-values-from-1password" rel="noopener noreferrer"&gt;retrieve items&lt;/a&gt; for use in your code, as well as &lt;a href="https://developer.1password.com/docs/vscode/#save-in-1password" rel="noopener noreferrer"&gt;store any bits of code&lt;/a&gt; you’d like in 1Password. If you’ve got multiple values you want stored in the same item – perhaps a username, password, and email – it supports that as well. Just select each value and run the “Save in 1Password” command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9en56z7r453hx8aq1ii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe9en56z7r453hx8aq1ii.png" alt="VSCode Screenshot"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Built using tools available to everyone
&lt;/h2&gt;

&lt;p&gt;I’ll let you in on a little secret: we didn’t plan to build this extension. It wasn’t requested by our developer community, and wasn’t part of any roadmap. Instead this extension began as a side project for myself. I wanted to scratch my own itch and integrate 1Password more closely into my development workflow, and to generally &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;learn more about developing with 1Password&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So you can imagine my excitement when, after a quick demo at an internal call, I was invited to polish it up and get it slated for release.&lt;/p&gt;

&lt;p&gt;To my delight, after demoing the extension and then going on vacation, &lt;a href="https://www.youtube.com/watch?v=hghKTE_pUaQ" rel="noopener noreferrer"&gt;Dave posted a video&lt;/a&gt; of the presentation from his &lt;a href="https://blog.1password.com/1password-cli-2_0/" rel="noopener noreferrer"&gt;CLI launch blog post&lt;/a&gt; and it was met with some pretty wild enthusiasm from the developer community. There was even some love for it at our &lt;a href="https://www.reddit.com/r/1Password/comments/ui9exd/were_the_team_behind_1password_8_for_mac_ask_us/i7fyfp9/" rel="noopener noreferrer"&gt;1Password 8 for Mac Reddit AMA&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqd10vvapq9iv00rgsftm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqd10vvapq9iv00rgsftm.png" alt="Reddit comment from user arnebr asking if the VS Code plugin will be live soon"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although not a goal from the outset, an interesting aspect of this project is that it’s built using only tools available to the public – there’s nothing internal or proprietary powering the features of the extension. We’ve even &lt;a href="https://github.com/1Password/op-vscode" rel="noopener noreferrer"&gt;open-sourced the whole project on our GitHub&lt;/a&gt;, so if you want to help iterate on it or report an issue, that’s a great place to start.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;VS Code extensions run in a Node environment, and we wanted to interact with the new CLI. So we built and open-sourced an entirely new package for doing exactly this: &lt;a href="https://github.com/1Password/op-js" rel="noopener noreferrer"&gt;op-js&lt;/a&gt;. It wraps the CLI with a simple-to-use JavaScript interface and ships with TypeScript declarations, making 60+ commands, including those that support biometrics unlock, available to your Node-based application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ultimately my hope is that this extension demonstrates some of the neat ways you can extend the power of 1Password by building your own integrations, whether it be for yourself or others. And you should &lt;a href="https://blog.1password.com/developers-deserve-great-ux/" rel="noopener noreferrer"&gt;have fun doing it&lt;/a&gt;. We’re in early days here, with plenty more developer offerings coming down the line.&lt;/p&gt;

&lt;p&gt;I’d love to hear what you think, and we’ll be iterating on the extension as feedback rolls in. Learn more about &lt;a href="https://developer.1password.com/docs/vscode" rel="noopener noreferrer"&gt;1Password for VS Code&lt;/a&gt; and our other developer tools by checking out our &lt;a href="https://developer.1password.com/" rel="noopener noreferrer"&gt;developer portal&lt;/a&gt;. While you’re there, consider joining our &lt;a href="https://join.slack.com/t/1password-devs/shared_invite/zt-15k6lhima-GRb5Ga~fo7mjS9xPzDaF2A" rel="noopener noreferrer"&gt;Developer Slack workspace&lt;/a&gt;, where you’ll find myself and others on the Developer Products team who are eager to hear how you’re incorporating 1Password into your development workflow. And if you’re building something cool, be sure to tag it &lt;a href="https://twitter.com/hashtag/buildwith1password?f=live" rel="noopener noreferrer"&gt;#BuildWith1Password&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Finally, we owe a tremendous debt of gratitude to &lt;a href="https://www.linkedin.com/in/mikeselander/" rel="noopener noreferrer"&gt;Mike Selander&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/chrisdunnbirch/" rel="noopener noreferrer"&gt;Chris Dunn-Birch&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/florisvdg/" rel="noopener noreferrer"&gt;Floris van der Grinten&lt;/a&gt;, the incredibly helpful folks over in the &lt;a href="https://github.com/1Password/op-vscode/blob/main/CONTRIBUTING.md#acknowledgments" rel="noopener noreferrer"&gt;VS Code Extension community&lt;/a&gt;, and so many more for providing endless help and guidance while working on this project. Thank you!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>vscode</category>
      <category>programming</category>
      <category>security</category>
    </item>
    <item>
      <title>1Password for SSH changed the way I work</title>
      <dc:creator>Jason Harris</dc:creator>
      <pubDate>Mon, 09 May 2022 17:12:06 +0000</pubDate>
      <link>https://dev.to/1password/1password-for-ssh-changed-the-way-i-work-2501</link>
      <guid>https://dev.to/1password/1password-for-ssh-changed-the-way-i-work-2501</guid>
      <description>&lt;p&gt;&lt;a href="https://blog.1password.com/1password-ssh-agent/"&gt;1Password for SSH&lt;/a&gt; was shared with the world last month. I have been using it since it was available for internal beta. I knew it would improve my endpoint security. I didn’t expect it to change &lt;del&gt;the way I generated, stored and used SSH keys&lt;/del&gt; the way I work.&lt;/p&gt;

&lt;p&gt;Let me take a step back.&lt;/p&gt;

&lt;p&gt;The first time I used SSH, I connected my college’s &lt;a href="https://www.csee.umbc.edu/courses/undergraduate/341/fall04/hood/notes/ssh/"&gt;global lab linux server&lt;/a&gt; with &lt;a href="https://www.putty.org/"&gt;PuTTY&lt;/a&gt;. I used a username and password to authenticate and never really appreciated &lt;a href="https://datatracker.ietf.org/doc/html/rfc4253"&gt;the magic that made it all work&lt;/a&gt;. It was a step away from the familiar world of FTP and RDP.&lt;/p&gt;

&lt;p&gt;SSH later became an integral part of my developer experience when my job switched from &lt;a href="https://subversion.apache.org/"&gt;Subversion&lt;/a&gt; to &lt;a href="https://lwn.net/Articles/165127/"&gt;Git&lt;/a&gt;. I was a Jr. Developer at the time and struggled to generate an SSH key. Another developer on the team generated an RSA key pair for me and shared it on a thumb drive. It was some years later before I realized &lt;a href="https://www.freebsd.org/news/2012-compromise/"&gt;this was less than ideal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Eventually, I fell into a routine. I would get a new laptop, generate a private key – sometimes I would even use a passphrase – and upload the new key to all the services I used (GitHub, VPS, etc.). I used the one-key-per-device pattern and repeated the process for my phone and other devices. Occasionally, I’d pull a device from cold storage for something I forgot about.&lt;/p&gt;

&lt;p&gt;The problem was that each SSH key represented one of my devices; it had no purpose attached to it. I used the same keys for work, open source contributions, file servers and a lot more. When I unlocked a key for one use, I unlocked it for all uses.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1Password for SSH has entered the chat&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.1password.com/docs/ssh/"&gt;1Password SSH Agent&lt;/a&gt; has a stricter authorization model than the OpenSSH Agent[1] defaults[2]. Instead of a key either being available or unavailable, a key has an authorized session. An authorized session consists of the key pair and either a terminal session or application. I wanted to be able to deliberately authorize a set of actions for my current context (e.g., work or open source).&lt;/p&gt;

&lt;p&gt;Thus, a new way of working.&lt;/p&gt;

&lt;p&gt;I generated a new key pair for each of my use cases. &lt;a href="https://support.1password.com/getting-started-browser/"&gt;1Password in the browser&lt;/a&gt; made this really easy by autofilling the new key in the GitHub and Gitlab public key forms. Now, when it’s time to get to work, I open my terminal and run a git fetch. 1Password prompts for my fingerprint and I approve the usage of my Work SSH key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zIUtI7qA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vwhpcdsxzbf3cgnbt7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zIUtI7qA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8vwhpcdsxzbf3cgnbt7y.png" alt="Image description" width="370" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m not prompted again while actively using my laptop. When it’s time to switch to an &lt;a href="https://github.com/neon-bindings/neon"&gt;open source project&lt;/a&gt;, I’m seamlessly prompted for my GitHub key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vsXiky6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmo7e9ygcnwdw34vwhf0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vsXiky6W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tmo7e9ygcnwdw34vwhf0.png" alt="Image description" width="370" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A little later, when I need to update my blog, I pop open a new terminal tab and start an SSH session. I forward my SSH Agent with &lt;code&gt;ssh -A&lt;/code&gt; so that I can perform a &lt;code&gt;git pull&lt;/code&gt; while I’m there[3]. When I’m done, I &lt;code&gt;exit&lt;/code&gt; the terminal session, deauthorizing it from the 1Password SSH Agent.&lt;/p&gt;

&lt;p&gt;Now, generating SSH keys is no longer part of my new device flow! All of my SSH keys are saved in 1Password and synchronized across my devices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kWWh4T05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0elf7hbrtnzccybiuhwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kWWh4T05--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0elf7hbrtnzccybiuhwd.png" alt="Image description" width="293" height="161"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m really excited for Git’s recent addition of &lt;a href="https://github.com/git/git/blob/master/Documentation/RelNotes/2.34.0.txt"&gt;commit signing with SSH keys&lt;/a&gt;. It already &lt;a href="https://git-scm.com/docs/git-config#Documentation/git-config.txt-gpgformat"&gt;works with 1Password SSH&lt;/a&gt; and I can’t wait for &lt;a href="https://github.com/github/feedback/discussions/7744"&gt;GitHub&lt;/a&gt; and &lt;a href="https://gitlab.com/gitlab-org/gitlab/-/issues/343879"&gt;Gitlab&lt;/a&gt; to support verification!&lt;/p&gt;




&lt;p&gt;[1] &lt;a href="https://www.openssh.com/agent-restrict.html"&gt;SSH agent restriction&lt;/a&gt; looks really cool! ↩︎&lt;/p&gt;

&lt;p&gt;[2] Similar functionality is available with &lt;code&gt;ssh-add -c&lt;/code&gt;. ↩︎&lt;/p&gt;

&lt;p&gt;[3] Eventually I’ll get around setting up a &lt;a href="https://docs.github.com/en/actions"&gt;GitHub Action&lt;/a&gt;. At least, that’s what I tell myself. ↩︎&lt;/p&gt;

&lt;p&gt;This &lt;a href="https://blog.1password.com/1password-ssh-changed-how-i-work/"&gt;post originally&lt;/a&gt; written by K.J. Valincik, Senior Staff Developer at 1Password.&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
