Open {re}Source | Articleshttps://openresource.dev/enRunning a Local AI Inside Obsidian with Ollamahttps://openresource.dev/articles/running-a-local-ai-inside-obsidian-with-ollama/https://openresource.dev/articles/running-a-local-ai-inside-obsidian-with-ollama/What if your Obsidian notes could think with you, without sending a single word to the cloud? This article shows you how to build a fully local AI setup inside Obsidian using Ollama and the open Gemma 3 model. You'll learn why local AI makes sense for knowledge work, how to install and test Ollama from the command line, and how to connect it to Obsidian using community plugins for a seamless writing experience.&lt;br&gt;&lt;br&gt;By the end of this tutorial, you'll have a private AI assistant that can rewrite text, summarize notes, brainstorm ideas, and help draft content all while keeping full control over your data. This setup combines Obsidian's local-first philosophy with Ollama's open source AI capabilities to create a knowledge workspace that's private, hackable, and built to last, proving that powerful tools don't have to come at the cost of control. Sun, 01 Feb 2026 00:00:00 GMT<p><strong>What if your notes could think with you, without sending a single word to the cloud?</strong> In this article, we’ll build a fully local AI setup inside Obsidian using Ollama and the open Gemma 3 model. You’ll learn why local AI makes sense for knowledge work, how to install and test Ollama from the command line, how to connect it to Obsidian using community plugins, and how to use it for practical, everyday note-taking workflows, all while keeping full control over your data.</p> <hr> <div><h2 id="why-local-ai-in-a-notes-app">Why Local AI in a Notes App?</h2></div> <p>Before jumping into installation, it’s worth clarifying what is and isn’t open source in this setup, and why it still aligns strongly with open source values.</p> <p><strong><a href="https://obsidian.md/">Obsidian</a> is an application that allows users to create and manage notes using plain text Markdown files stored locally on their devices.</strong></p> <p><strong>Obsidian is not open source itself, but supports open source community plugins, and is local-first</strong>:</p> <ul> <li>Notes are plain Markdown files</li> <li>Stored on your own filesystem</li> <li>No mandatory account or cloud dependency</li> <li>Easy to migrate, back up, or process with other tools</li> </ul> <p>This dramatically reduces vendor lock-in. Even without Obsidian, your knowledge remains usable.</p> <p><strong><a href="https://ollama.com/">Ollama</a> is an open source tool that lets you run AI models locally on your machine:</strong></p> <ul> <li>Runs open models locally</li> <li>Exposes a local HTTP API</li> <li>Requires no internet once models are installed</li> <li>Never sends your data elsewhere</li> </ul> <p>Together, Obsidian and Ollama create a powerful combination that aligns with open source values: local notes, local AI for privacy, and knowledge work that you actually control.</p> <hr> <div><h2 id="what-well-build">What We’ll Build</h2></div> <p>By the end of this article, you’ll have:</p> <ul> <li>Ollama installed and verified from the command line</li> <li>The Gemma 3 model running locally</li> <li>Obsidian configured with community plugins</li> <li>A fully local AI assistant embedded in your notes</li> </ul> <p>Everything described below has been tested using Gemma 3 with Ollama.</p> <p>Let’s consider that Obsidian is already installed on your machine. If you haven’t done so yet, you can download it from <a href="https://obsidian.md/">obsidian.md</a>.</p> <hr> <div><h2 id="step-1-install-and-test-ollama-command-line-first">Step 1: Install and Test Ollama (Command Line First)</h2></div> <ol role="list"> <li> <p>Install Ollama from the official site at <a href="https://ollama.com">https://ollama.com</a>, or via Homebrew on macOS via</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>brew</span><span> </span><span>install</span><span> </span><span>ollama</span></div></div></code></pre></figure></div> </li> <li> <p>Verify the installation by running in your terminal:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>ollama</span><span> </span><span>--version</span></div></div></code></pre></figure></div> <p>The output should show the installed version of Ollama.</p> </li> <li> <p>Pull and run the Gemma 3 model with:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>ollama</span><span> </span><span>run</span><span> </span><span>gemma3</span></div></div></code></pre></figure></div> <p>Once the model is downloaded, you’ll get an interactive prompt. Test it with:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>Explain what a local-first application is in one paragraph.</span></div></div></code></pre></figure></div> <p>If you receive a response, everything is working correctly.</p> </li> <li> <p>Exit the chat with the command:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>/bye</span></div></div></code></pre></figure></div> </li> <li> <p>Ollama also starts a local API server at <a href="http://localhost:11434">http://localhost:11434</a>.</p> <p>Opening this URL in your browser will show the “Ollama API is running” message. This endpoint is what Obsidian will use next.</p> </li> </ol> <hr> <div><h2 id="step-2-install-the-required-obsidian-community-plugins">Step 2: Install the Required Obsidian Community Plugins</h2></div> <p>To connect Obsidian to Ollama, you’ll need two open source Obsidian community plugins created by <a href="https://github.com/pfrankov">Pavel Frankov</a>:</p> <ul> <li>AI Providers</li> <li>Local GPT</li> </ul> <div> <div> <span> <a href="https://github.com/pfrankov/obsidian-local-gpt"> <span><span>pfrankov/</span><br>obsidian-local-gpt</span> </a> <span>Local Ollama and OpenAI-like GPT's assistance for maximum privacy and offline access </span> </span> <img src="https://avatars.githubusercontent.com/u/584632?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <div> <div> <span> <a href="https://github.com/pfrankov/obsidian-ai-providers"> <span><span>pfrankov/</span><br>obsidian-ai-providers</span> </a> <span>This plugin is a hub for setting AI providers (OpenAI-like, Ollama and more) in one place. </span> </span> <img src="https://avatars.githubusercontent.com/u/584632?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <div><h3 id="ai-providers">AI Providers</h3></div> <p>Let’s start by installing the <strong>AI Providers</strong> plugin.</p> <ol role="list"> <li> <p>In Obsidian, go to “Settings → Community Plugins → Browse” and search for “AI Providers”.</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-1.png" alt="" loading="lazy" decoding="async" width="720" height="320"> </div> </li> <li> <p>Click “Install”, then “Enable” to enable the plugin.</p> </li> <li> <p>Click “Options” to configure the plugin:</p> <ul> <li>In the “AI providers” section, click ”+” to add a new provider.</li> <li>In the “Add new provider” dialog: <ul> <li>Select “Ollama” as the provider type.</li> <li>Click on the refresh icon of the “Model” field to fetch Gemma 3 from your local Ollama installation.</li> <li>Click “Save” to add the provider.</li> </ul> </li> </ul> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-2.png" alt="" loading="lazy" decoding="async" width="420" height="320"> </div> </li> </ol> <div><h3 id="local-gpt">Local GPT</h3></div> <p>Then, install the <strong>Local GPT</strong> plugin.</p> <ol role="list"> <li> <p>In Obsidian, go to “Settings → Community Plugins → Browse” and search for “Local GPT”.</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-3.png" alt="" loading="lazy" decoding="async" width="720" height="320"> </div> </li> <li> <p>Click “Install”, then “Enable” to enable the plugin.</p> </li> <li> <p>Click “Options” to configure the plugin:</p> <ul> <li>In the “Main AI Provider”, “Embedding AI Provider”, and “Vision AI Provider” sections, select “Ollama ~ gemma3:latest” from the dropdown.</li> </ul> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-4.png" alt="" loading="lazy" decoding="async" width="720" height="320"> </div> </li> </ol> <hr> <div><h2 id="step-3-attach-hot-keys-for-quick-access">Step 3: Attach Hot Keys for Quick Access</h2></div> <p>To quickly access Local GPT features, set up hot keys in Obsidian.</p> <ol role="list"> <li> <p>In Obsidian, go to “Settings → Hotkeys”.</p> </li> <li> <p>Filter by “Local”.</p> </li> <li> <p>Assign hot keys to the following commands:</p> <ul> <li>For “Local GPT: Action Palette”, click on ”+” and press your desired key combination (e.g., <kbd>⌘ + J</kbd>).</li> <li>For “Local GPT: Show context menu”, click on ”+” and press your desired key combination (e.g., <kbd>⌘ + M</kbd>).</li> </ul> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-5.png" alt="" loading="lazy" decoding="async" width="720" height="320"> </div> </li> </ol> <hr> <div><h2 id="step-4-test-local-gpt-inside-obsidian">Step 4: Test Local GPT Inside Obsidian</h2></div> <p>Now that everything is set up, it’s time to test Local GPT inside Obsidian.</p> <p>Two hot keys are set up: one for the action palette and one for the context menu.</p> <div><h3 id="using-the-context-menu">Using the Context Menu</h3></div> <p>The context menu is a quick way to apply AI actions to selected text.</p> <ol role="list"> <li> <p>Open any note in Obsidian.</p> </li> <li> <p>Select some text you want to process with AI.</p> </li> <li> <p>Press the hot key you assigned for “Local GPT: Show context menu” (e.g., <kbd>⌘ + M</kbd>). It will open a context menu with various AI actions you can perform on the selected text:</p> <ul> <li>General help</li> <li>Continue writing</li> <li>Summarize</li> <li>Fix spelling and grammar</li> <li>Find action items</li> <li>New System Prompt</li> </ul> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-6.png" alt="" loading="lazy" decoding="async" width="720" height="320"> </div> <p>Please note that you can create your own custom prompts as well.</p> </li> </ol> <p>Let’s say I’ve written this article in Obsidian first and wanted to summarize it. I would select the text and use the context menu to choose “Summarize”.</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-7.png" alt="" loading="lazy" decoding="async" width="420" height="320"> </div> <p>Gemma 3 would then generate a concise summary of the selected content directly at the end of my note (this can be configured).</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-8.png" alt="" loading="lazy" decoding="async" width="420" height="320"> </div> <div><h3 id="using-the-action-palette">Using the Action Palette</h3></div> <p>The action palette allows you to type custom prompts and interact with Local GPT more freely.</p> <ol role="list"> <li>Open any note in Obsidian.</li> <li>Press the hot key you assigned for “Local GPT: Action Palette” (e.g., <kbd>⌘ + J</kbd>). It will open the action palette where you can type your prompt.</li> </ol> <p>Let’s say I want to analyze an image to describe its content. I would select the image in my note, open the action palette, and type: “Describe this image!”</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-9.png" alt="" loading="lazy" decoding="async" width="420" height="320"> </div> <p>The model would then generate a description of the image directly in my note.</p> <div> <img src="https://openresource.dev/images/running-a-local-ai-inside-obsidian-with-ollama-10.png" alt="" loading="lazy" decoding="async" width="420" height="320"> </div> <hr> <div><h2 id="everyday-use-cases-that-actually-feel-useful">Everyday Use Cases That Actually Feel Useful</h2></div> <p><strong>I just scratched the surface of what you can do with this setup, and honestly, it’s pretty useful for specific tasks.</strong> Gemma 3 works well for close-to-the-text stuff: cleaning up messy first drafts, turning rambling meeting notes into actual bullet points, or getting a quick summary when I don’t want to reread a long note.</p> <p>Response times are decent for most tasks. Not instant, but fast enough to keep you in the flow.</p> <p>Where I use it most is rewriting awkward sentences, expanding bullet points when I need more detail, or brainstorming different ways to phrase something. It’s also surprisingly good at catching unclear writing that I might miss.</p> <p><strong>But it definitely has limits.</strong> It can’t access other notes in my vault (just the current one), struggles with complex reasoning, and sometimes gives generic responses if your prompt is too vague. I’m also not sure how well it handles really technical content as I’ve had mixed results there.</p> <p>The key thing I’ve learned is that <strong>it works best as an editing partner for stuff you’ve already written, rather than generating ideas from scratch.</strong></p> <p>Maybe a more powerful setup could mix local and cloud models, using local for sensitive stuff and cloud for heavy lifting when needed. But for now, this local-first approach feels like a solid step toward more private, controllable AI in my writing workflow.</p> <hr> <div><h2 id="trade-offs-and-why-theyre-worth-it">Trade-Offs (And Why They’re Worth It)</h2></div> <p>Local AI isn’t perfect:</p> <ul> <li>Slower than cloud-hosted models</li> <li>Smaller context windows</li> <li>Less immediate “wow” factor than other cloud paid systems</li> </ul> <p>But in exchange, you get:</p> <ul> <li>Privacy by default</li> <li>Zero marginal cost</li> <li>Full control over models and prompts</li> <li>No vendor dependency or platform lock-in</li> </ul> <p>For personal knowledge management and everyday writing, that trade-off is often not just acceptable, but desirable.</p> <hr> <p><strong>Local AI inside Obsidian isn’t about chasing the biggest model: it’s about reclaiming agency over how you think and write.</strong> By combining a local-first notes app with open models running through Ollama, you get an AI workflow that is private, hackable, and built to last. In a world increasingly defined by opaque clouds and locked platforms, this setup quietly proves that powerful tools don’t have to come at the cost of control.</p> <p>If you try out this setup, let me know how it goes! Share your experiences, tips, or custom workflows in our social platforms.</p> <p>Happy note-taking!</p>AIToolsTutorialCoding LinkedIn Carouselshttps://openresource.dev/articles/coding-linkedin-carousels/https://openresource.dev/articles/coding-linkedin-carousels/Coding LinkedIn carousels... yes, not using design tools but using developer tools! It's now possible!&lt;br&gt;&lt;br&gt;Learn how to code LinkedIn carousels with Slidev and discover our open-source Slidev theme for LinkedIn carousels named slidev-theme-linkedin-carousel. Sun, 29 Sep 2024 00:00:00 GMT<p>Coding LinkedIn carousels… yes, not using design tools but using developer tools! It’s now possible!</p> <p>A few days ago, we shared <a href="https://www.linkedin.com/posts/open-re-source_generate-github-repositories-top-contributors-activity-7245171076966559745-sBAM/">a new article on LinkedIn</a> and tried to make it more engaging by using a carousel. And creating a carousel on LinkedIn can take a bit of time, especially if you’re not that familiar with design tools such as <a href="https://www.canva.com">Canva</a>, <a href="https://www.figma.com">Figma</a>, or even <a href="https://penpot.app/">Penpot</a>, our open-source design tool friend. Even with the tons of templates available out there, customizing them is a lot of work.</p> <p>In the open-source software world, we are mostly developers, we’re not going to lie. So, we thought: <strong>“Why not code the LinkedIn carousel?” And that’s what we did!</strong></p> <div><h2 id="how-linkedin-carousels-work">How LinkedIn carousels work</h2></div> <p>Just for those who are not familiar with LinkedIn carousels, they are a series of images or slides that you can swipe through. They are a great way to share information in a visually appealing format. You can use them to showcase your open-source project, share tips, or even tell a story.</p> <p>There’s no really a creator tool for LinkedIn carousels, so you have to create them yourself.</p> <p><strong>Basically, a LinkedIn carousel is in fact a PDF file.</strong> You can create a PDF file with multiple pages, and each page will be a slide in your carousel. You can then upload this PDF file to LinkedIn, and it will automatically convert it into a carousel.</p> <ol> <li>On LinkedIn, click on the ”+ Create” button.</li> <li>Select “Start a post”.</li> <li>Click on the ”+” icon, and “Add a document”.</li> <li>Select your PDF file, choose a document title, and LinkedIn will convert it into a carousel.</li> </ol> <div> <img src="https://openresource.dev/images/coding-linkedin-carousels-1.png" alt="" loading="lazy" decoding="async" width="400" height="320"> </div> <div> <img src="https://openresource.dev/images/coding-linkedin-carousels-2.png" alt="" loading="lazy" decoding="async" width="400" height="257"> </div> <div><h2 id="the-idea">The Idea</h2></div> <p><strong>So, if it just a PDF file, why not code it?</strong> We can create a simple HTML file with multiple slides, and then convert it into a PDF file. And that’s what we did!</p> <p>We already use this great tool for presentations, it’s called <a href="https://sli.dev/">Slidev</a>.</p> <p>Slidev is a presentation tool based on Vue.js. It allows you to create beautiful slides with Markdown and code. And it has a feature to export your slides as a PDF file. It is an open-source project, under the MIT license.</p> <div> <div> <span> <a href="https://github.com/slidevjs/slidev"> <span><span>slidevjs/</span><br>slidev</span> </a> <span>Presentation Slides for Developers</span> </span> <img src="https://avatars.githubusercontent.com/u/83095831?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <div><h2 id="how-to-code-linkedin-carousels">How to Code LinkedIn Carousels</h2></div> <p>It’s really simple in fact.</p> <p>The first step is to create a new Slidev project. You can do this by running the following command:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>npm</span><span> </span><span>init</span><span> </span><span>slidev@latest</span></div></div></code></pre></figure></div> <p>This will create a new Slidev project in the current directory. You can then open the project in your code editor and start customizing the slides.</p> <p>Obviously, you’ll notice that the default Slidev theme is not really suitable for LinkedIn carousels as the slides are generally in landscape format, in 16:9 ratio. So, you’ll need to customize the theme to make it more suitable for LinkedIn carousels.</p> <p>In the <code dir="auto">slides.md</code> you just have to add the following properties in the frontmatter:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>---</span></div></div><div><div><span>aspectRatio: </span><span>"</span><span>3/4</span><span>"</span></div></div><div><div><span>canvasWidth: </span><span>800</span></div></div></code></pre></figure></div> <p>Just install <code dir="auto">playwright-chromium</code> as a dev dependency, and export your slides as a PDF file:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>npm</span><span> </span><span>install</span><span> </span><span>-D</span><span> </span><span>playwright-chromium</span></div></div><div><div><span>npm</span><span> </span><span>run</span><span> </span><span>export</span></div></div></code></pre></figure></div> <p>And voilà, you got a nice <code dir="auto">slides-export.pdf</code> that could be used as a LinkedIn carousel!</p> <div><h2 id="we-created-a-theme-for-linkedin-carousels">We Created a Theme for LinkedIn Carousels</h2></div> <p>However, you’ll notice that you still have some design work to do in order to render your carousel more visually appealing.</p> <p><strong>So, we created a theme for LinkedIn carousels called <code dir="auto">slidev-theme-linkedin-carousel</code></strong>, that is an open-source project under the MIT license.</p> <div> <div> <span> <a href="https://github.com/Open-reSource/slidev-theme-linkedin-carousel"> <span><span>Open-reSource/</span><br>slidev-theme-linkedin-carousel</span> </a> <span>Slidev theme to create LinkedIn carousels</span> </span> <img src="https://avatars.githubusercontent.com/u/129324099?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p>Here’s how it looks like: <a href="https://slidev-theme-lk-carousel.netlify.app">https://slidev-theme-lk-carousel.netlify.app</a>.</p> <div><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/1.png" alt="" loading="lazy" decoding="async" width="200" height="150"><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/2.png" alt="" loading="lazy" decoding="async" width="200" height="150"><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/3.png" alt="" loading="lazy" decoding="async" width="200" height="150"><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/4.png" alt="" loading="lazy" decoding="async" width="200" height="150"><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/5.png" alt="" loading="lazy" decoding="async" width="200" height="150"><img src="https://cdn.jsdelivr.net/npm/slidev-theme-linkedin-carousel@latest/example-export/6.png" alt="" loading="lazy" decoding="async" width="200" height="150"></div> <div><h3 id="how-to-use-the-theme">How to Use the Theme</h3></div> <p>To use the theme, you just have to install it as a dev dependency:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>npm</span><span> </span><span>i</span><span> </span><span>-D</span><span> </span><span>slidev-theme-linkedin-carousel</span></div></div></code></pre></figure></div> <p>and then add the following frontmatter to your slides:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>---</span></div></div><div><div><span>theme</span><span>: </span><span>linkedin-carousel</span></div></div><div><div><span>---</span></div></div></code></pre></figure></div> <p>For more information on how to use the theme, check out the <a href="https://github.com/Open-reSource/slidev-theme-linkedin-carousel">README</a>.</p> <p>The <code dir="auto">example.md</code> file in the repository is a good starting point to create your own LinkedIn carousels. And from there, you can customize the slides to your liking, and even use custom components to make them more impacting.</p> <hr> <p>That’s how you can code LinkedIn carousels. It’s a great way to share information in a visually appealing format, and it’s also a fun way to learn new things. We hope you enjoyed this guide, and we can’t wait to see what you create!</p> <p>Don’t hesitate to share your LinkedIn carousels with us, we’d love to see them! See ya <a href="https://www.linkedin.com/company/open-re-source/">on LinkedIn</a>!</p> <p>If you liked this theme, use it, please consider <a href="https://github.com/Open-reSource/slidev-theme-linkedin-carousel">giving it a star on GitHub</a>, or even <a href="https://github.com/sponsors/Open-reSource/">sponsoring us</a>. It helps us a lot!</p>LinkedInSocial MediaToolsAdd Funding Links to Your 'package.json'https://openresource.dev/articles/add-funding-links-to-your-packagejson/https://openresource.dev/articles/add-funding-links-to-your-packagejson/Learn how to enhance your open-source project by adding funding links to your 'package.json'. This guide highlights the importance of supporting maintainers and explores various ways contributors can provide financial assistance, including platforms like GitHub Sponsors and Open Collective. By making your funding information visible, you can encourage users to support your project directly. &lt;br&gt;&lt;br&gt; We'll walk you through the process of implementing the funding field in your 'package.json', ensuring that your project is equipped to receive contributions. Whether it's a simple donation link or a Patreon page, letting the community know you're seeking support can make a difference. With just a few adjustments, you might find that your project receives the backing it deserves! Sun, 22 Sep 2024 00:00:00 GMT<p>Fund your open-source project by adding funding links to your <code>package.json</code> file. Who knows, you might get a coffee or two out of it!</p> <div><h2 id="funding-open-source-projects">Funding Open-Source Projects?</h2></div> <p>If you’re not new to the content of Open {re}Source, you know a thing or two about the importance of <a href="https://openresource.dev/guide/financing-open-source-projects">financing and funding open-source projects</a>. The time and effort that maintainers put into their projects are invaluable, and it’s essential to support them in any way possible.</p> <p>Supporting open-source projects can be as simple as starring a repository, contributing to the codebase, or even providing financial support. The latter can be done through platforms like <a href="https://github.com/sponsors">GitHub Sponsors</a>, <a href="https://opencollective.com/">Open Collective</a>, or even through direct donations.</p> <div><h2 id="packages-are-looking-for-funding">Packages Are Looking for Funding</h2></div> <p>Have you ever noticed the funding information displayed when you run the <code dir="auto">npm i</code> command in your terminal?</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>% npm install</span></div></div><div><div> </div></div><div><div><span>247 packages are looking for funding</span></div></div><div><div><span><span> </span></span><span>run `npm fund` for details</span></div></div></code></pre></figure></div> <div><h3 id="you-can-turn-it-off-by-the-way">You Can Turn It Off, by the Way</h3></div> <p>If you’re not a fan of the funding information displayed when installing packages, you can turn it off by setting the <code dir="auto">--no-fund</code> flag when running the <code dir="auto">npm install</code> command.</p> <p>You can also set it as a default behavior by running <code dir="auto">npm config set fund false</code>.</p> <p>Or you can turn it off in your <code dir="auto">.npmrc</code> file in your home directory (<code dir="auto">~/.npmrc</code>) manually or in your project’s <code dir="auto">.npmrc</code> file:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>fund = false</span></div></div></code></pre></figure></div> <div><h2 id="npm-fund-command"><code dir="auto">npm fund</code> Command</h2></div> <p>Have you already launched <code dir="auto">npm fund</code> in your terminal? If not, go ahead and do it now in one of your projects.</p> <p>Here’s what it looks like for this repository:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>[email protected]</span></div></div><div><div><span>├── https://opencollective.com/fakerjs</span></div></div><div><div><span>│ └── @faker-js/[email protected]</span></div></div><div><div><span>├── https://dotenvx.com</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/wooorm</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]</span></div></div><div><div><span>├── https://opencollective.com/vitest</span></div></div><div><div><span>│ └── [email protected], @vitest/[email protected], @vitest/[email protected], @vitest/[email protected], @vitest/[email protected], @vitest/[email protected], @vitest/[email protected], @vitest/[email protected], [email protected]</span></div></div><div><div><span>├─┬ https://paulmillr.com/funding/</span></div></div><div><div><span>│ │ └── [email protected]</span></div></div><div><div><span>│ ├── https://github.com/sponsors/jonschlinkert</span></div></div><div><div><span>│ │ └── [email protected], [email protected]</span></div></div><div><div><span>│ └── https://github.com/sponsors/sindresorhus</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]</span></div></div><div><div><span>├── https://github.com/prettier/prettier?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/epoberezkin</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/feross</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected]</span></div></div><div><div><span>├─┬ https://github.com/chalk/wrap-ansi?sponsor=1</span></div></div><div><div><span>│ │ └── [email protected], [email protected]</span></div></div><div><div><span>│ └── https://github.com/chalk/ansi-styles?sponsor=1</span></div></div><div><div><span>│ └── [email protected], [email protected]</span></div></div><div><div><span>├── https://opencollective.com/unified</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], @mdx-js/[email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]</span></div></div><div><div><span>├── https://locize.com</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/antfu</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/colinhacks</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├─┬ https://opencollective.com/postcss/</span></div></div><div><div><span>│ │ └── [email protected], [email protected]</span></div></div><div><div><span>│ └── https://github.com/sponsors/ai</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/isaacs</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected], [email protected]</span></div></div><div><div><span>├─┬ https://opencollective.com/babel</span></div></div><div><div><span>│ │ └── @babel/[email protected]</span></div></div><div><div><span>│ └── https://opencollective.com/browserslist</span></div></div><div><div><span>│ └── [email protected], [email protected], [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/sibiraj-s</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├─┬ https://github.com/chalk/strip-ansi?sponsor=1</span></div></div><div><div><span>│ │ └── [email protected]</span></div></div><div><div><span>│ └── https://github.com/chalk/ansi-regex?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/vitejs/vite?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://opencollective.com/libvips</span></div></div><div><div><span>│ └── [email protected], @img/[email protected], @img/[email protected]</span></div></div><div><div><span>├─┬ https://github.com/sponsors/fb55</span></div></div><div><div><span>│ │ └── [email protected], [email protected], [email protected]</span></div></div><div><div><span>│ ├── https://github.com/fb55/domhandler?sponsor=1</span></div></div><div><div><span>│ │ └── [email protected]</span></div></div><div><div><span>│ └─┬ https://github.com/fb55/domutils?sponsor=1</span></div></div><div><div><span>│ │ └── [email protected]</span></div></div><div><div><span>│ └── https://github.com/cheeriojs/dom-serializer?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/fb55/htmlparser2?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├── https://github.com/sponsors/NaturalIntelligence</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>├─┬ https://github.com/privatenumber/get-tsconfig?sponsor=1</span></div></div><div><div><span>│ │ └── [email protected]</span></div></div><div><div><span>│ └── https://github.com/privatenumber/resolve-pkg-maps?sponsor=1</span></div></div><div><div><span>│ └── [email protected]</span></div></div><div><div><span>└── https://github.com/sponsors/ljharb</span></div></div><div><div><span><span> </span></span><span>└── [email protected]</span></div></div></code></pre></figure></div> <p>As stated in the <a href="https://docs.npmjs.com/cli/commands/npm-fund">official npm documentation</a>, the <code dir="auto">npm fund</code> command shows funding information for the installed packages in your project.</p> <p>And there can be a lot of them!</p> <p>But you might wonder, how can you add funding information to your own project? It can be interesting to let know the world that you are looking for funding, right?</p> <div><h2 id="adding-funding-links-to-your-packagejson">Adding Funding Links to Your <code dir="auto">package.json</code></h2></div> <p>It’s quite simple in fact. You can add funding information to your <code dir="auto">package.json</code> file by using the <a href="https://docs.npmjs.com/cli/v10/configuring-npm/package-json#funding"><code dir="auto">funding</code> field</a>.</p> <p>As stated in the official npm documentation:</p> <blockquote> <p>You can specify an object containing a URL that provides up-to-date information about ways to help fund development of your package, a string URL, or an array of objects and string URLs:</p> </blockquote> <div><figure><figcaption></figcaption><pre><code><div><div><span>{</span></div></div><div><div><span> </span><span>"funding"</span><span>: [</span></div></div><div><div><span><span> </span></span><span>{</span></div></div><div><div><span> </span><span>"type"</span><span>: </span><span>"</span><span>individual</span><span>"</span><span>,</span></div></div><div><div><span> </span><span>"url"</span><span>: </span><span>"</span><span>http://example.com/donate</span><span>"</span></div></div><div><div><span><span> </span></span><span>},</span></div></div><div><div><span> </span><span>"</span><span>http://example.com/donateAlso</span><span>"</span><span>,</span></div></div><div><div><span><span> </span></span><span>{</span></div></div><div><div><span> </span><span>"type"</span><span>: </span><span>"</span><span>patreon</span><span>"</span><span>,</span></div></div><div><div><span> </span><span>"url"</span><span>: </span><span>"</span><span>https://www.patreon.com/my-account</span><span>"</span></div></div><div><div><span><span> </span></span><span>}</span></div></div><div><div><span><span> </span></span><span>]</span></div></div><div><div><span>}</span></div></div></code></pre></figure></div> <p>From there, those who install your package might see the funding information when they run some npm commands. And who knows, they might decide to support your project!</p> <p>On top of that, if your package is listed on the npm registry, the funding information will be displayed on the package’s page with a “Fund this package” button:</p> <div> <img src="https://openresource.dev/images/add-funding-links-to-your-package.json.png" alt="Screenshot the &#x27;Fund this package&#x27; npm registry button" loading="lazy" decoding="async" width="370" height="50"> </div> <hr> <p><strong>Funding your open-source project might be complicated</strong>, but referencing your funding links a the right places can make it easier for people to support you. And adding funding links to your <code dir="auto">package.json</code> file is a good start! It’s not going to make hundreds of people support you, for sure, but it’s a good way to let the world know that you are looking for funding; <strong>and little by little, you might get a coffee or two out of it!</strong></p>npmFundingTutorialGet Real-Time GitHub Stars Notifications in Discordhttps://openresource.dev/articles/get-real-time-github-stars-notifications-in-discord/https://openresource.dev/articles/get-real-time-github-stars-notifications-in-discord/After refactoring our website, we noticed a rise in statistics and new stars on our GitHub repository. While GitHub doesn't offer native notifications for new stars, we decided to create our own solution. &lt;br&gt;&lt;br&gt; This guide walks you through setting up a GitHub Actions workflow to send real-time notifications to a private Discord channel whenever your repository gains new stars. It's a fun way to track your project's popularity and engage with your community. Follow along as we share our journey of building and tweaking this automation, complete with a screenshot of the notification we received on our phone. Tue, 17 Sep 2024 00:00:00 GMT<p>After the refactoring of this website, folks (maybe you) started to spread the word about it. The statistics started to rise a little bit, and we discovered along the way that the repository holding this website also started to receive some new stars. To our knowledge, there’s no native way to get notified by GitHub when you receive stars on your repositories. So, we decided to do something about it!</p> <p>We know, we know, tracking stars is a little bit linked to the gamification of the open source world, but to be honest, it’s still a fun way to keep track of your project’s popularity and engage with your community.</p> <p>So, we decided to build a simple automation that would send a notification to a private Discord channel whenever our GitHub repository receives new stars. There are probably better ways to do this, existing solutions, but where is the fun in that?</p> <p>After a few times of tweaking and testing, we finally got it working! 🎉</p> <p>Here is the notification we received on our phone this afternoon:</p> <div> <img src="https://openresource.dev/images/get-real-time-github-stars-notifications-in-discord-1.png" alt="Screenshot of the mobile phone showing the Discord notification from the &#x27;Open {re}Source Community&#x27; Discord space sent by &#x27;GitHub Stars Bot&#x27;. The message is &#x27;The repository has gained new stars! Previous: 60 → Total: 61&#x27;" loading="lazy" decoding="async" width="458" height="133"> </div> <p>And when you click on the notification, here is how the notification appears on Discord, showing the new star count and the repository name:</p> <div> <img src="https://openresource.dev/images/get-real-time-github-stars-notifications-in-discord-2.png" alt="Screenshot of the Discord app showing the notification sent by a &#x27;GitHub Stars Bot&#x27; app, containing a GitHub star avatar, and the text: &#x27;The repository has gained new stars! Previous: 60 → Total: 61&#x27;" loading="lazy" decoding="async" width="458" height="166"> </div> <p><strong>Cool, right? Here’s how it’s been done!</strong></p> <div><h2 id="step-1-create-a-discord-webhook">Step 1: Create a Discord Webhook</h2></div> <p>To send notifications to Discord, you will need to set up a webhook in your Discord server. Here’s how to do it:</p> <ol> <li>Open your Discord server and navigate to the channel where you want to receive notifications. You can create a dedicated private channel for this purpose.</li> <li>Click on the gear icon next to the channel name to access the channel settings.</li> <li>Select the “Integrations” tab.</li> <li>Click on “Webhooks” and then “Create Webhook.”</li> <li>Give your webhook a name (e.g. “GitHub Stars Bot”), and select a nice image.</li> <li><strong>Copy the webhook URL, as you will need it later.</strong></li> </ol> <p>Here’s also a link to the <a href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks">Discord documentation - Intro to Webhooks</a> for more information.</p> <div><h2 id="step-2-create-a-github-repository">Step 2: Create a GitHub Repository</h2></div> <p>Now, let’s create a private GitHub repository to store our future GitHub Actions workflow. You can create a new repository or use an existing one, make it public or private, as you prefer.</p> <div><h2 id="step-3-create-a-secret-variable-in-github">Step 3: Create a Secret Variable in GitHub</h2></div> <p>To securely store your Discord Webhook URL to ensure that sensitive data isn’t exposed in your repository code, you will need to create a secret variable in your GitHub repository:</p> <ol> <li>Go to your GitHub repository and click on the “Settings” tab.</li> <li>In the left sidebar, click on “Secrets and variables” and then “Actions.”</li> <li>Click on the “New repository secret” button.</li> <li>Name your secret <code dir="auto">DISCORD_WEBHOOK_URL</code> and paste the webhook URL you copied from Discord.</li> </ol> <div><h2 id="step-4-create-a-github-actions-workflow">Step 4: Create a GitHub Actions Workflow</h2></div> <aside aria-label="What is GitHub Actions?"><p aria-hidden="true">What is GitHub Actions?</p><div><p>If your not familiar with GitHub Actions, it allows you to automate workflows directly in your GitHub repository, and it can be triggered based on various events. More information can be found in the <a href="https://docs.github.com/en/actions">GitHub Actions documentation</a>.</p></div></aside> <p>In this repository:</p> <ol> <li>Create a new directory called <code dir="auto">.github/workflows</code>.</li> <li>Create a new file called for instance <code dir="auto">gh-stars-to-discord.yml</code> (or choose a name you prefer).</li> </ol> <div><h3 id="the-algorithm">The Algorithm</h3></div> <p>The algorithm is rather simple:</p> <ul> <li>Every hour, the workflow will check the current number of stars on the repository using the GitHub API.</li> <li>While doing so, it will also check the rate limit of the API. <ul> <li>If the rate limit is low, the workflow will stop.</li> <li>If not, it will compare the current number of stars with the previous number of stars.</li> </ul> </li> <li>If there are new stars, it will send a notification to Discord using the webhook URL.</li> <li>Finally, it will save the current number of stars for the next comparison.</li> </ul> <div><h3 id="using-the-github-api">Using the GitHub API</h3></div> <p>To get started, you will need to use the <a href="https://docs.github.com/en/rest">GitHub REST API</a> to fetch the star count for your repository. The GitHub API provides a simple way to access information about your repositories, including the number of stars they have received.</p> <p>There is a public endpoint that you can use to get the star count for a specific repository:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>GET https://api.github.com/repos/{owner}/{repo}</span></div></div></code></pre></figure></div> <p>Replace <code dir="auto">{owner}</code> with your GitHub username and <code dir="auto">{repo}</code> with the name of your repository. The response will include a JSON object with various details about the repository, including the <code dir="auto">stargazers_count</code> field, which indicates the number of stars.</p> <p>So for our main repository, you would make a request to:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>GET https://api.github.com/repos/Open-reSource/openresource.dev</span></div></div></code></pre></figure></div> <aside aria-label="Try it out!"><p aria-hidden="true">Try it out!</p><div><p>You can try it out directly in your browser (or using a tool like <a href="https://github.com/curl/curl">Curl</a>) to see the JSON response. In the browser, you can simply paste the URL into the address bar and hit enter.</p></div></aside> <p>At the time of writing, Open {re}Source main repository has 61 stars, so the answer would be:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>{</span></div></div><div><div><span> </span><span>// ...</span></div></div><div><div><span> </span><span>"stargazers_count"</span><span>: </span><span>61</span></div></div><div><div><span> </span><span>// ...</span></div></div><div><div><span>}</span></div></div></code></pre></figure></div> <aside aria-label="Be mindful of the GitHub API rate limits"><p aria-hidden="true">Be mindful of the GitHub API rate limits</p><div><p>Be mindful of the GitHub API rate limits when making requests. You can find more information about the rate limits in the <a href="https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting">GitHub API documentation</a>.</p><p>At the time of writing, the GitHub API allows for up to 60 requests per hour for unauthenticated requests and up to 5,000 requests per hour for authenticated requests. If you plan to make frequent requests, consider using a personal access token for authentication.</p></div></aside> <div><h3 id="the-actual-workflow">The Actual Workflow</h3></div> <p>Now, let’s create the actual workflow:</p> <ol> <li>Clone your repository to your local machine or edit it directly on GitHub.</li> <li>Add the following YAML code to your <code dir="auto">gh-stars-to-discord.yml</code> file:</li> </ol> <aside aria-label="Note"><p aria-hidden="true">Note</p><div><ul> <li>Make sure to replace <code dir="auto">open-reSource/openresource.dev</code> with your own repository name.</li> <li>The workflow is set to run every hour, but you can adjust the schedule as needed by changing the <code dir="auto">cron</code> expression.</li> <li>You can change the text of the notification sent to Discord by modifying the <code dir="auto">curl</code> command in the <code dir="auto">Compare and notify if new stars</code> step.</li> </ul></div></aside> <div><figure><figcaption></figcaption><pre><code><div><div><span>name</span><span>: </span><span>GitHub Stars to Discord</span></div></div><div><div> </div></div><div><div><span>on</span><span>:</span></div></div><div><div><span> </span><span>schedule</span><span>:</span></div></div><div><div><span><span> </span></span><span>- </span><span>cron</span><span>: </span><span>'</span><span>0 * * * *</span><span>'</span><span> </span><span># Every 1 hour. You can change the frequency as needed.</span></div></div><div><div><span> </span><span>workflow_dispatch</span><span>: </span><span># Allows manual triggering</span></div></div><div><div> </div></div><div><div><span>env</span><span>:</span></div></div><div><div><span> </span><span>DISCORD_WEBHOOK_URL</span><span>: </span><span>${{ secrets.DISCORD_WEBHOOK_URL }}</span></div></div><div><div><span> </span><span>GITHUB_REPOSITORY</span><span>: </span><span>'</span><span>open-reSource/openresource.dev</span><span>'</span><span> </span><span># Change this to your repository</span></div></div><div><div> </div></div><div><div><span>jobs</span><span>:</span></div></div><div><div><span> </span><span>notify</span><span>:</span></div></div><div><div><span> </span><span>runs-on</span><span>: </span><span>ubuntu-latest</span></div></div><div><div> </div></div><div><div><span> </span><span>steps</span><span>:</span></div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Get the current number of stars and check rate limit</span></div></div><div><div><span> </span><span>id</span><span>: </span><span>get_stars</span></div></div><div><div><span> </span><span>run</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>response=$(curl -s -i https://api.github.com/repos/${{ env.GITHUB_REPOSITORY }})</span></div></div><div><div><span><span> </span></span><span>stars=$(echo "$response" | grep -oP '"stargazers_count":\s*\K\d+')</span></div></div><div><div><span><span> </span></span><span>rate_limit_remaining=$(echo "$response" | grep -Fi 'X-RateLimit-Remaining:' | awk -F': ' '{print $2}' | tr -d '\r')</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>echo "Current stars: $stars"</span></div></div><div><div><span><span> </span></span><span>echo "Rate limit remaining: $rate_limit_remaining"</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>echo "stars=$stars" >> $GITHUB_OUTPUT</span></div></div><div><div><span><span> </span></span><span>echo "rate_limit_remaining=$rate_limit_remaining" >> $GITHUB_OUTPUT</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Stop if rate limit is low</span></div></div><div><div><span> </span><span>if</span><span>: </span><span>${{ steps.get_stars.outputs.rate_limit_remaining &#x3C; 10 }}</span></div></div><div><div><span> </span><span>run</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>echo "Rate limit is low, exiting"</span></div></div><div><div><span><span> </span></span><span>exit 1</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Cache previous stars count</span></div></div><div><div><span> </span><span>id</span><span>: </span><span>cache_previous_stars</span></div></div><div><div><span> </span><span>uses</span><span>: </span><span>actions/cache@v4</span></div></div><div><div><span> </span><span>with</span><span>:</span></div></div><div><div><span> </span><span>path</span><span>: </span><span>previous_stars.txt</span></div></div><div><div><span> </span><span>key</span><span>: </span><span>stars-${{ github.repository }}-${{ github.run_id }}</span></div></div><div><div><span> </span><span>restore-keys</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>stars-${{ github.repository }}-</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Load the previous number of stars</span></div></div><div><div><span> </span><span>id</span><span>: </span><span>load_previous_stars</span></div></div><div><div><span> </span><span>run</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>if [ -f previous_stars.txt ]; then</span></div></div><div><div><span><span> </span></span><span>echo "Loading previous stars"</span></div></div><div><div><span><span> </span></span><span>PREVIOUS_STARS=$(cat previous_stars.txt)</span></div></div><div><div><span><span> </span></span><span>else</span></div></div><div><div><span><span> </span></span><span>echo "No previous stars found"</span></div></div><div><div><span><span> </span></span><span>PREVIOUS_STARS=0</span></div></div><div><div><span><span> </span></span><span>fi</span></div></div><div><div><span><span> </span></span><span>echo "Previous stars: $PREVIOUS_STARS"</span></div></div><div><div><span><span> </span></span><span>echo "previous_stars=$PREVIOUS_STARS" >> $GITHUB_OUTPUT</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Compare and notify if new stars</span></div></div><div><div><span> </span><span>if</span><span>: </span><span>${{ steps.get_stars.outputs.stars != steps.load_previous_stars.outputs.previous_stars }}</span></div></div><div><div><span> </span><span>run</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>NEW_STARS=${{ steps.get_stars.outputs.stars }}</span></div></div><div><div><span><span> </span></span><span>PREVIOUS_STARS=${{ steps.load_previous_stars.outputs.previous_stars }}</span></div></div><div><div><span><span> </span></span><span>if [ $NEW_STARS -gt $PREVIOUS_STARS ]; then</span></div></div><div><div><span><span> </span></span><span>echo "There are new stars: $NEW_STARS stars (previous: $PREVIOUS_STARS)"</span></div></div><div><div><span><span> </span></span><span>curl -H "Content-Type: application/json" \</span></div></div><div><div><span><span> </span></span><span>-d "{\"content\": \"The repository has gained new stars! Previous: $PREVIOUS_STARS → Total: $NEW_STARS\"}" \</span></div></div><div><div><span><span> </span></span><span>${DISCORD_WEBHOOK_URL}</span></div></div><div><div><span><span> </span></span><span>else</span></div></div><div><div><span><span> </span></span><span>echo "No new stars"</span></div></div><div><div><span><span> </span></span><span>fi</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Save current stars count</span></div></div><div><div><span> </span><span>run</span><span>: </span><span>|</span></div></div><div><div><span><span> </span></span><span>echo "${{ steps.get_stars.outputs.stars }}" > previous_stars.txt</span></div></div><div><div> </div></div><div><div><span><span> </span></span><span>- </span><span>name</span><span>: </span><span>Update cache with new stars count</span></div></div><div><div><span> </span><span>uses</span><span>: </span><span>actions/cache@v4</span></div></div><div><div><span> </span><span>with</span><span>:</span></div></div><div><div><span> </span><span>path</span><span>: </span><span>previous_stars.txt</span></div></div><div><div><span> </span><span>key</span><span>: </span><span>stars-${{ github.repository }}-${{ github.run_id }}</span></div></div></code></pre></figure></div> <div><h2 id="step-5-run-the-workflow">Step 5: Run the Workflow</h2></div> <p>The workflow has a <code dir="auto">workflow_dispatch</code> trigger, which means you can run it manually from the GitHub Actions tab in your repository. You can also wait for the next scheduled run (every hour) to see it in action.</p> <p>The first time you run the workflow, it will probably send a notification saying that you had 0 stars and now you have X stars (the current number of stars).</p> <aside aria-label="Note"><p aria-hidden="true">Note</p><div><p>We voluntarily left some logging in the workflow to help you debug if needed. You can remove or comment out the <code dir="auto">echo</code> statements if you want to clean up the logs.</p><p>To check the logs, once your YAML file is pushed to the repository, go to the “Actions” tab, select the workflow, and click on the latest run. All the logs will be displayed there.</p></div></aside> <p>To be honest, we are a little bit lazy, so we didn’t implement a complex logic to handle this first run, or even when the count of stars decreases. But you can always improve the workflow to suit your needs! This is just a starting point.</p> <hr> <p><strong>Automation is really cool!</strong> You could do the same thing for your followers in your GitHub profile, send notifications by email, Slack, etc. But automation is not limited to just notifications. You can also automate tasks like deploying your code, running tests, and much more.</p> <p><strong>The possibilities are endless!</strong></p> <p>A few words before we finish:</p> <ul> <li><strong>Want to spam us with stars?</strong> You can add some stars to <a href="https://github.com/Open-reSource/openresource.dev">https://github.com/Open-reSource/openresource.dev</a>. We will be happy to get some notifications on our mobile phones!</li> <li>Please let us know if you’d like to see more automation tutorials like this one!</li> <li>We haven’t created a reusable workflow, shared it in the Marketplace, nor created a GitHub Gist. We thought it was easier just to share a little bit of code in this article that you could start from and adapt. If you want it to be stored somewhere with a more formal MIT license, please let us know! But please feel free to use it as you wish.</li> </ul> <p><strong>Happy coding! 🎉</strong></p>AutomationDiscordDiscord WebhookGitHubGitHub ActionsGitHub APIGitHub StarsBluesky Starter Pack About Open Sourcehttps://openresource.dev/articles/bluesky-starter-pack/https://openresource.dev/articles/bluesky-starter-pack/On June 26, 2024, Bluesky, the decentralized social media platform, introduced starter packs to enhance user experience and facilitate community growth. These personalized invites allow users to bring friends directly into their customized Bluesky environments. A starter pack can include custom feeds and recommended follows, encouraging new users to connect with favorite accounts. Although not searchable, starter packs can be shared via links or embed previews within the Bluesky app. &lt;br&gt;&lt;br&gt; The Open {re}Source team has created a Bluesky starter pack focused on the open-source community. They curated a selection of accounts and individuals related to open source, along with a custom "Open Source" feed. This starter pack, available through a QR code or link, invites users to join and engage with the open source community on Bluesky. Feedback and suggestions are welcomed, fostering a collaborative and personalized social media experience. Mon, 01 Jul 2024 00:00:00 GMT<p>Bluesky released starter packs on June 26, 2024. They are personalized invites that allow users to bring people directly into your slice of Bluesky!</p> <p><a href="https://bsky.social">Bluesky</a>, the decentralized social media platform, has recently introduced starter packs, aiming to personalize user experiences and make it easier for communities to grow. <a href="https://bsky.social/about/blog/06-26-2024-starter-packs">On June 26, 2024, Bluesky launched these starter packs</a>, allowing users to bring friends directly into their customized Bluesky environment.</p> <div><h2 id="whats-in-a-bluesky-starter-pack">What’s in a Bluesky Starter Pack?</h2></div> <p>A Bluesky starter pack can include the following:</p> <ul> <li><strong>Custom feeds</strong>: On Bluesky, you can set any algorithm or topic as your home timeline.</li> <li><strong>Recommended follows</strong>: Add your favorite accounts and encourage new users to follow them.</li> </ul> <p>At the time of writing:</p> <ul> <li><strong>Starter packs do not show up in search</strong>, so you will need to have someone send you the link or see the embed preview within the Bluesky app.</li> <li><strong>Starter packs can recommend up to 150 people and up to 3 custom feeds</strong>. New users will automatically have Following and Discover pinned.</li> </ul> <div><h2 id="the-open-source-bluesky-starter-pack">The Open Source Bluesky Starter Pack</h2></div> <p>You can count on us! The Open {re}Source team is excited to introduce <strong>our very own Bluesky starter pack focused on open source</strong>! 🚀</p> <p>We followed the tutorial provided by Bluesky <a href="https://bsky.social/about/blog/06-26-2024-starter-packs">in their blog post</a>, but even without the tutorial, it is quite easy and intuitive to create a starter pack from the interface.</p> <p>Below is the link to our open source Bluesky starter pack:</p> <a href="https://go.bsky.app/BrzaZ72"><div> <img src="https://openresource.dev/images/bluesky-starter-pack.png" alt="Go to the Open {re}Source Bluesky starter pack" loading="lazy" decoding="async" width="300" height="430"> </div></a> <p>It contains accounts and individuals linked to the open-source world, as well as <a href="https://bsky.app/profile/did:plc:7qnsmqeluaybzzdfuaic4ulf/feed/aaaitsh7hqhew">the Open Source feed we created for Bluesky</a>.</p> <div><h2 id="get-involved">Get Involved!</h2></div> <p>We hope you enjoy our starter pack! 🎉</p> <p>Don’t hesitate to share your feedback <a href="https://bsky.app/profile/openresource.dev">with us on Bluesky</a>, suggest new accounts to follow, or even create your own starter pack and share it with us! 🙌</p> <div> <bsky-widget data-handle="openresource.dev"></bsky-widget> </div> <p>Find this Bluesky profile widget cool? Check this out:</p> <div> <div> <span> <a href="https://github.com/saurabhdaware/bsky-widget"> <span><span>saurabhdaware/</span><br>bsky-widget</span> </a> <span>Unofficial Bluesky widget to render cute profile cards in your website ^_^</span> </span> <img src="https://avatars.githubusercontent.com/u/30949385?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <hr> <p>Bluesky’s starter packs are an excellent way to foster community and personalize your social media experience. The Open {re}Source Bluesky starter pack is designed to connect you with the open-source community on Bluesky. Join us, and let’s continue to build and share together!</p> <p>Feel free to reach out with any questions or suggestions. Happy Blueskying! 🚀</p>BlueskySocial MediaToolsWho Is the Ghost User on GitHub?https://openresource.dev/articles/github-ghost-user/https://openresource.dev/articles/github-ghost-user/This morning, I woke up to over 200+ GitHub notifications, all spam discussions cluttering my inbox. Titles like "WATCH Kingdom of the Planet of the Apes FuLLMovie (.Free.)..." and "FREE-ROBUX-GENERATOR-2024-FREE-ROBUX-NEW-CODES-DAILY BONUS" demanded my attention. While deleting and reporting these, I mistakenly reported the user "ghost", which GitHub Support clarified is a placeholder for deleted users' contributions. The ghost user ensures that discussions, issues, and commits from deleted accounts remain intact. &lt;br&gt;&lt;br&gt; The ghost user plays a vital role in maintaining repository integrity and continuity. By attributing deleted users' contributions to the ghost user, GitHub preserves valuable historical insights and project cohesion. This mechanism activates when users delete their accounts or GitHub removes accounts for policy violations. The ghost user helps future contributors benefit from past discussions and maintains the overall project flow, highlighting its importance in the GitHub ecosystem. Sat, 18 May 2024 00:00:00 GMT<p>This morning, I woke up to a storm of 200+ GitHub notifications. My inbox, usually pristine, was drowning in a deluge of spams.</p> <p>As I scrolled through, my screen filled with an overwhelming array of spam discussions.</p> <div> <img src="https://openresource.dev/images/github-ghost-user-1.png" alt="Screenshot of the GitHub interface showing a spam GitHub discussion with &#x27;WATCH Kingdom of the Planet of the Apes FuLLMovie (.Free.)...&#x27; title, and a content matching this title, with big &#x27;Watch now&#x27; and &#x27;Download&#x27; buttons" loading="lazy" decoding="async" width="720" height="570"> </div> <div> <img src="https://openresource.dev/images/github-ghost-user-2.png" alt="Screenshot of the GitHub interface showing a spam GitHub discussion with &#x27;FREE-ROBUX-GENERATOR-2024-FREE-ROBUX-NEW-CODES-DAILY BONUS-[Jo)ztyr]&#x27; title, and a content matching this title, with links to get it" loading="lazy" decoding="async" width="720" height="386"> </div> <p><strong>OK, cool, we are being productive today! 200+ GitHub discussions to delete!</strong></p> <p>We can’t see it in the screenshots, but there were several authors of the discussions, or answering to the discussions. I couldn’t block them for this specific repository as I am not the owner of the repository, but I could report them. So, one by one, I started to delete the discussions and report the users without looking at their profile.</p> <p>The usual process happened on GitHub side, except for one user: <a href="https://github.com/ghost">ghost</a>!</p> <p>The GitHub Developer Support answered:</p> <blockquote> <p>“The <strong>ghost</strong> username is in place to designate accounts that have been deleted by their owners, but that still have content that is visible across the GitHub platform.”</p> </blockquote> <p><strong>Oops!</strong></p> <p>Indeed, I didn’t check the GitHub profile of the user before reporting it, and it is pretty obvious when you are looking at it:</p> <div> <div> <span> <a href="https://github.com/ghost"> <span>ghost</span> </a> <span>Hi, I'm <a href="https://github.com/ghost">@ghost</a>! I take the place of user accounts that have been deleted. 👻</span> </span> <img src="https://avatars.githubusercontent.com/u/10137?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p>The ghost user is a placeholder account used by GitHub to manage contributions and commits from users who have been deleted or whose accounts are no longer active. So it is not a spam account, and not especially an account to report. 😅</p> <p>When a user is deleted from GitHub, their contributions, such as commits, issues, and comments, are not erased. Instead, these contributions are attributed to the Ghost user to maintain the integrity and history of the repository.</p> <div><h2 id="the-role-of-the-ghost-user">The Role of the Ghost User</h2></div> <p>The primary purpose of the ghost user is to preserve the history and context of projects.</p> <p>It helps with <strong>maintaining repository integrity</strong>. When a user is deleted, removing their contributions would disrupt the continuity and understanding of the project. By attributing these contributions to the ghost user, GitHub ensures that the project’s history remains intact.</p> <p>It also helps with <strong>contextual continuity</strong>. Comments on issues and pull requests often provide valuable insights and discussions. Reassigning these to the ghost user ensures that future contributors can still benefit from these historical discussions.</p> <div><h2 id="when-does-the-ghost-user-appear">When Does the Ghost User Appear?</h2></div> <p>You might see the ghost user <strong>when a GitHub user decides to delete their account</strong>, all their contributions are transferred to the Ghost user.</p> <p>It can also happen when <strong>GitHub removes an account</strong> due to policy violations or other reasons. In this case, the contributions are reassigned to the Ghost user.</p> <hr> <p>In conclusion, the ghost user on GitHub is an essential mechanism to preserve the continuity and integrity of projects.</p> <p>You can even follow it, it has already 9.5k followers! 😅</p>GitHubcontrib.rocks: Generate an Image of GitHub Repositories Top Contributorshttps://openresource.dev/articles/contrib-rocks/https://openresource.dev/articles/contrib-rocks/contrib.rocks is an online tool that generates an image showcasing the top contributors of a GitHub repository, which can be embedded in websites or Markdown files, including README files. This free service, provides a visual representation of repository activity, celebrating and encouraging contributions. &lt;br&gt;&lt;br&gt; Using contrib.rocks is straightforward: visit the website, enter a GitHub repository name, and generate an image representing its top contributors. The tool offers options to customize the image, such as setting the maximum number of contributors and the number of columns. This visual representation can be embedded using provided HTML or Markdown code, enhancing the visibility and appeal of a project's README or website. Sat, 27 Apr 2024 00:00:00 GMT<p><a href="https://contrib.rocks/">contrib.rocks</a> is a an online tool that generates an image of the top contributors of a GitHub repository that can be embedded in any website or Markdown file; including its README file.</p> <p>It is completely free and maintained by Suguru Inatomi, a.k.a. <a href="https://github.com/lacolaco">lacolaco</a>. The source code is available on GitHub:</p> <div> <div> <span> <a href="https://github.com/lacolaco/contributors-img"> <span><span>lacolaco/</span><br>contributors-img</span> </a> </span> <img src="https://avatars.githubusercontent.com/u/1529180?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p>This service allows to give a visual representation of the top contributors of any GitHub repository.</p> <p>Generating such an image of your GitHub repository top contributors can be a great way to show the activity of your GitHub repository and encourage people to contribute, but also to celebrate your top contributors.</p> <div><h2 id="how-to-use">How to Use</h2></div> <p>Usage is pretty straightforward:</p> <ol> <li>Go to <a href="https://contrib.rocks/">https://contrib.rocks/</a></li> <li>Enter a GitHub repository (e.g., <code dir="auto">open-reSource/openresource.dev</code>)</li> </ol> <p>And that’s it! You will get the image representing the top contributors of the GitHub repository you entered.</p> <p>Then, you can click on the “Get Image URL!” button to get the Markdown code to embed the image in your README file for instance.</p> <div><figure><figcaption></figcaption><pre><code><div><div><span><span>&#x3C;</span><span>a</span><span> </span></span><span>href</span><span>=</span><span>"</span><span>https://github.com/open-reSource/openresource.dev/graphs/contributors</span><span>"</span><span>></span></div></div><div><div><span> </span><span><span>&#x3C;</span><span>img</span><span> </span></span><span>src</span><span>=</span><span>"</span><span>https://contrib.rocks/image?repo=open-reSource/openresource.dev</span><span>"</span><span> /></span></div></div><div><div><span><span>&#x3C;/</span><span>a</span><span>></span></span></div></div><div><div> </div></div><div><div><span>Made with [contrib.rocks](https://contrib.rocks).</span></div></div></code></pre></figure></div> <p>You will notice that the first part of the generated Markdown code is in reality HTML code. You can use this HTML code to embed the image in any website or Markdown file.</p> <div><h2 id="rendering">Rendering</h2></div> <p>Here is what it looks like for our <a href="https://github.com/Open-reSource/openresource.dev">openresource.dev GitHub repository</a>:</p> <hr> <a href="https://github.com/open-reSource/openresource.dev/graphs/contributors"><img src="https://contrib.rocks/image?repo=open-reSource/openresource.dev"></a> <p>Made with <a href="https://contrib.rocks">contrib.rocks</a>.</p> <hr> <p>And here is the same rendering, but on a more active repository like <a href="https://github.com/godotengine/godot">godot</a>:</p> <div> <div> <span> <a href="https://github.com/godotengine/godot"> <span><span>godotengine/</span><br>godot</span> </a> <span>Godot Engine – Multi-platform 2D and 3D game engine</span> </span> <img src="https://avatars.githubusercontent.com/u/6318500?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <hr> <a href="https://github.com/godotengine/godot/graphs/contributors"><img src="https://contrib.rocks/image?repo=godotengine/godot"></a> <p>Made with <a href="https://contrib.rocks">contrib.rocks</a>.</p> <hr> <p>Some parameters can be added to the URL to customize the image:</p> <ul> <li><code dir="auto">max={number}</code>: Max contributor count (100 by default)</li> <li><code dir="auto">columns={number}</code>: Max columns (12 by default)</li> <li><code dir="auto">anon={0|1}</code>: Include anonymous users (false by default)</li> </ul> <p>So if we add <code dir="auto">&#x26;max=10&#x26;columns=2</code> to the image URL <code dir="auto">https://contrib.rocks/image?repo=godotengine/godot</code> we get the following image with only the top 10 contributors and 2 columns:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span><span>&#x3C;</span><span>a</span><span> </span></span><span>href</span><span>=</span><span>"</span><span>https://github.com/godotengine/godot/graphs/contributors</span><span>"</span><span>></span></div></div><div><div><span> </span><span><span>&#x3C;</span><span>img</span><span> </span></span><span>src</span><span>=</span><span>"</span><span>https://contrib.rocks/image?repo=godotengine/godot&#x26;max=10&#x26;columns=2</span><span>"</span><span> /></span></div></div><div><div><span><span>&#x3C;/</span><span>a</span><span>></span></span></div></div><div><div> </div></div><div><div><span>Made with [contrib.rocks](https://contrib.rocks).</span></div></div></code></pre></figure></div> <hr> <a href="https://github.com/godotengine/godot/graphs/contributors"><img src="https://contrib.rocks/image?repo=godotengine/godot&#x26;max=10&#x26;columns=2"></a> <p>Made with <a href="https://contrib.rocks">contrib.rocks</a>.</p>GitHubMarkdownReadmeToolsRepobeats: GitHub README analyticshttps://openresource.dev/articles/repobeats/https://openresource.dev/articles/repobeats/Repobeats is a tool that provides analytics for GitHub repositories, allowing users to embed detailed visual representations of repository activity into any Markdown file, including README files. Maintained by axiom.com, Repobeats is free to use but not open source. It offers insights like the number of contributions in the last 30 days, the ratio of opened to closed issues, the number of PRs opened and commits, and a heatmap showcasing top contributors' activity. This visual representation highlights repository activity, encourages contributions, and celebrates top contributors. &lt;br&gt;&lt;br&gt; To install Repobeats, users need a GitHub account. Simply log into Repobeats with GitHub credentials, select the repository to analyze, and obtain a URL for embedding the analytics image into Markdown files. This URL provides a comprehensive snapshot of repository activity, demonstrated with examples from repositories like openresource.dev and freeCodeCamp. Repobeats' ability to display real-time data makes it a valuable resource for promoting and managing open-source projects on GitHub. Tue, 02 Apr 2024 00:00:00 GMT<p><a href="https://repobeats.axiom.co/">Repobeats</a> is a tool that provides analytics of a GitHub repository that can be embedded in any Markdown file; including its README file.</p> <p>It is completely free and maintained by <a href="https://axiom.co/">axiom.com</a>, but does not seem to be an open-source project as it is not referenced in <a href="https://github.com/axiomhq">github.com/axiomhq</a>.</p> <p>This service allows to give a visual representation of the activity of your GitHub repository:</p> <ul> <li>the number of contributions in the last 30 days</li> <li>the number of opened/closed issues ratio with an associated bar chart of the past month</li> <li>the number of PRs opened with an associated bar chart of the past month</li> <li>the number of commits with an associated bar chart of the past month</li> <li>the top contributors with their GitHub green square activity; their contribution heatmap</li> </ul> <p>It can be a great way to show the activity of your GitHub repository and encourage people to contribute, but also to celebrate your top contributors.</p> <p>Behind the scene, Repobeats uses public data available on GitHub.</p> <div><h2 id="installation">Installation</h2></div> <p>Installing Repobeats requires a GitHub account.</p> <aside aria-label="Caution"><p aria-hidden="true">Caution</p><div><p>Please consult their <a href="https://repobeats.axiom.co/">Frequency Asked Questions</a> for more information before installing it. They explain for example how they use your email address.</p></div></aside> <p>To install Repobeats, it is pretty straightforward:</p> <ol> <li>Go to <a href="https://repobeats.axiom.co/">https://repobeats.axiom.co/</a></li> <li>Login with your GitHub account</li> <li>Select the owner and repository you want to analyze</li> </ol> <p>And that’s it! You will get a URL like ours that you can use in your README file or any Markdown file:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>// Add the following to your README.md to embed Repobeats</span></div></div><div><div><span>![</span><span>Alt</span><span>]</span><span>(</span><span>https://repobeats.axiom.co/api/embed/da1c940f0135aece8b9942f518b44dacc39bd9ce.svg</span><span> </span><span><span>'</span><span>Repobeats analytics image</span><span>'</span></span><span>)</span></div></div></code></pre></figure></div> <div><h2 id="rendering">Rendering</h2></div> <p>Here is what it looks like for our <a href="https://github.com/Open-reSource/openresource.dev">openresource.dev GitHub repository</a>:</p> <p><img src="https://repobeats.axiom.co/api/embed/da1c940f0135aece8b9942f518b44dacc39bd9ce.svg" alt="Alt" title="Repobeats analytics image for openresource.dev GitHub repository"></p> <p>And here is the same kind of data, but on a more active repository like freeCodeCamp:</p> <div> <div> <span> <a href="https://github.com/freeCodeCamp/freeCodeCamp"> <span><span>freeCodeCamp/</span><br>freeCodeCamp</span> </a> <span>freeCodeCamp.org's open-source codebase and curriculum. Learn to code for free.</span> </span> <img src="https://avatars.githubusercontent.com/u/9892522?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p><img src="https://repobeats.axiom.co/api/embed/89be0a1a1c8f641c54f9234a7423e7755352c746.svg" alt="Alt" title="Repobeats analytics image for freeCodeCamp GitHub repository"></p> <p>freeCodeCamp is using it in the <a href="https://github.com/freeCodeCamp/freeCodeCamp?tab=readme-ov-file#contributing">“Contributing” section of their README file</a> and it looks great!</p> <p>We can see right away that this repository is very active with a lot of contributions, issues, PRs, and commits.</p>GitHubMarkdownReadmeToolsGitHub Marketplace: Social Preview for Your GitHub Actionshttps://openresource.dev/articles/github-marketplace-social-preview-for-your-github-actions/https://openresource.dev/articles/github-marketplace-social-preview-for-your-github-actions/When sharing a GitHub Action on social media, the default preview image might prominently display your GitHub profile picture, as seen with the "Update Issue Body" action on the GitHub Marketplace. To make a more informative and visually appealing preview, you can add a custom social preview image to your GitHub repository. This custom image enhances the appearance of social media posts and is also used when sharing links to your GitHub Action on the Marketplace. &lt;br&gt;&lt;br&gt; Creating a custom social preview image is straightforward and guided by GitHub's documentation. The recommended size is 1280x640 pixels for optimal display on high-resolution devices. GitHub provides a template with safe zones to use as a starting point. After designing and uploading the image, tools like opengraph.xyz can verify its appearance across social media platforms. For a ready-made solution, a reusable Figma template named "GitHub Actions and Repo Social Previews" simplifies the creation of custom images. Fri, 15 Sep 2023 00:00:00 GMT<p>You are finally ready to share your GitHub Action with the world. You have spent hours working on it, and now it is time to show it off. You open your favorite social media platform, start typing your post, link your GitHub Action on the GitHub Marketplace, click on send, and… your big face is on people’s screen!</p> <div> <img src="https://openresource.dev/images/github-marketplace-social-preview-for-your-github-actions-1.png" alt="Screenshot of the rendering of the social media preview of the link of my GitHub Action on the GitHub Marketplace with my big face on it" loading="lazy" decoding="async" width="458" height="327"> </div> <p>This is what happened to me when I shared the <a href="https://github.com/marketplace/actions/update-issue-body">marketplace link of my GitHub Action named “Update Issue Body”</a>.</p> <p>To be fair, the rendering is different and way better if one shares a link to the <a href="https://github.com/julien-deramond/update-issue-body">GitHub Action repository itself</a>.</p> <div> <img src="https://openresource.dev/images/github-marketplace-social-preview-for-your-github-actions-2.png" alt="Screenshot of the rendering of the social media preview of the link of my GitHub Action repository that shows useful information" loading="lazy" decoding="async" width="449" height="318"> </div> <div><h2 id="what-can-we-do-about-it">What Can We Do About It?</h2></div> <p>It is possible to add a social preview image to your GitHub repository. This image will be used when you share the link to your repository on social media platforms. But this image will also be used when you share the link to your GitHub Action on the GitHub Marketplace!</p> <p>It is rather easy to do as everything is explained directly in the GitHub documentation <a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/customizing-your-repositorys-social-media-preview">Customizing your repository’s social media preview</a>.</p> <p>At the times of writing, images are recommended to be 1280x640px for best display on high-resolution devices.</p> <p>While not visible in the documentation itself, GitHub provides in the settings of your repository a template for the social preview image which is pretty handy to get started and to have the safe zones.</p> <div> <img src="https://openresource.dev/images/github-marketplace-social-preview-for-your-github-actions-3.png" alt="Repo card template provided by GitHub with safe zones" loading="lazy" decoding="async" width="720" height="360"> </div> <p>I am not a designer, so I used the template to create my social preview image which has the following rendering:</p> <div> <img src="https://openresource.dev/images/github-marketplace-social-preview-for-your-github-actions-4.png" alt="Social preview of my GitHub Action based on the repo card template provided by GitHub with my profile picture, the project name as a title, a description of the project, and my GitHub username" loading="lazy" decoding="async" width="720" height="360"> </div> <div><h2 id="how-to-check-if-it-works">How To Check If It Works?</h2></div> <p>After having uploaded the image to your repository, you can check if it works by using online tools like <a href="https://www.opengraph.xyz/">opengraph.xyz</a>.</p> <p>Whether you use the marketplace link or the repository link, you should see the social preview image.</p> <div> <img src="https://openresource.dev/images/github-marketplace-social-preview-for-your-github-actions-5.png" alt="Screenshot of the rendering provided by opengraph.xyz when my new social preview image has been uploaded which works well with all social media platforms" loading="lazy" decoding="async" width="446" height="1272"> </div> <div><h2 id="find-this-template-on-figma">Find This Template On Figma</h2></div> <p>Based on this rendering, I have created <a href="https://www.figma.com/community/file/1285681647987701740">a reusable Figma template named “GitHub Actions and Repo Social Previews”</a> that you can use to create your own social preview image.</p>CommunicationGitHubGitHub ActionsDisplay Your Sponsors in Your GitHub READMEshttps://openresource.dev/articles/display-your-sponsors-in-your-github-readmes/https://openresource.dev/articles/display-your-sponsors-in-your-github-readmes/Showcasing your sponsors in GitHub READMEs is a great way to acknowledge their support and attract potential sponsors. An easy way to do this is by using SponsorKit, developed by Anthony Fu. SponsorKit generates sponsor images compatible with GitHub Sponsors, Open Collective, Patreon, and Afdian. By following a few steps, you can create and display these sponsor images in your project's README file. You'll need a GitHub account, at least one sponsor, and a personal access token. A template repository is available to simplify the setup process. Thu, 18 May 2023 00:00:00 GMT<p>A simple nice way to reward your sponsors could be to showcase them in the projects you create on GitHub. And what a better place to do that than in your READMEs? This article will show you how to do that easily!</p> <p>There are several ways to display your sponsors in your GitHub READMEs, but this article will focus on a single one by using <a href="https://github.com/antfu/sponsorkit">SponsorKit</a> created by <a href="https://github.com/antfu">Anthony Fu</a>.</p> <div> <div> <span> <a href="https://github.com/antfu/sponsorkit"> <span><span>antfu/</span><br>sponsorkit</span> </a> <span>💖 Toolkit for generating sponsors images 😄</span> </span> <img src="https://avatars.githubusercontent.com/u/11247099?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p><strong>SponsorKit</strong> is a toolkit for generating sponsors images that supports GitHub Sponsors, Open Collective, Patreon, and Afdian.</p> <p>Here’s how Anthony uses it himself in <a href="https://github.com/antfu/unplugin-auto-import#sponsors">antfu/unplugin-auto-import README</a>.</p> <p>Let’s do our own sponsors image showcasing our GitHub sponsors!</p> <div><h2 id="prerequisites">Prerequisites</h2></div> <p>Before starting, you will need to have a GitHub account and have at least one sponsor.</p> <p>Then, you will need to create a new GitHub personal access token (classic) with the <code dir="auto">read:org</code>, and <code dir="auto">read:user</code> scopes that you can name whatever you want, and keep its value somewhere for the next steps of this tutorial.</p> <p>You can find more information about how to create a GitHub token in the <a href="https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token">GitHub documentation</a>.</p> <div><h2 id="create-your-repository">Create Your Repository</h2></div> <p>In order to facilitate the process, we have created for you a template repository that you can use to create your own repository: <a href="https://github.com/Open-reSource/sponsorkit-starter">https://github.com/Open-reSource/sponsorkit-starter</a>.</p> <div> <div> <span> <a href="https://github.com/Open-reSource/sponsorkit-starter"> <span><span>Open-reSource/</span><br>sponsorkit-starter</span> </a> <span>Starter template for SponsorKit</span> </span> <img src="https://avatars.githubusercontent.com/u/129324099?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <div><h3 id="from-the-starter-template">From the Starter Template</h3></div> <p>You can click on the “Use this template” button to create your own repository.</p> <p>Then, you will need to fill the form with the name of your repository, a description, and choose if you want to make it public or private. Click on the “Create repository from template” button to create your repository.</p> <p>It will launch a GitHub Action that will fail, but don’t worry, we will fix that in the next steps.</p> <div><h3 id="from-a-new-repository">From a New Repository</h3></div> <p>It is also possible to create your repository from scratch, clone it locally, and then running the following command:</p> <div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>npx</span><span> </span><span>degit</span><span> </span><span>Open-reSource/sponsorkit-starter</span></div></div></code></pre></figure></div> <div><h2 id="configure-your-repository">Configure Your Repository</h2></div> <p>Your new repository is now created, and should contain the following files:</p> <ul> <li><code dir="auto">.github/workflows/scheduler.yml</code> that runs the SponsorKit action on a schedule every day, for each merge on the main branch, or manually.</li> <li><code dir="auto">.env.example</code> as described in <a href="https://github.com/antfu/sponsorkit/#usage">SponsorKit usage</a>.</li> <li><code dir="auto">build.sh</code> script to generate the sponsors images.</li> <li><code dir="auto">package.json</code> relying on the latest version of SponsorKit and containing the build script.</li> <li><code dir="auto">sponsor.config.ts</code> that contains the configuration for the generation of the sponsors images.</li> </ul> <div><h3 id="change-default-permissions-of-github_token">Change Default Permissions of GITHUB_TOKEN</h3></div> <p>First important thing to do is to change the default permissions of the <code dir="auto">GITHUB_TOKEN</code> that is used by the GitHub Action to commit and push the generated sponsors images.</p> <p>It can be changed by going to your repository settings, then to the “Actions” section, and choose “Read an write permissions” for the “Workflow permissions” option.</p> <p>You can find more information about this configuration in the <a href="https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#configuring-the-default-github_token-permissions">GitHub documentation</a>.</p> <div><h3 id="set-up-the-environment-variable">Set up the environment variable</h3></div> <p>By looking at <code dir="auto">.github/worfklows/scheduler.yml</code>, we can see that it relies on a <code dir="auto">${{ secrets.SPONSORS_TOKEN }}</code> environment variable.</p> <p>We will need to set it up in the GitHub repository settings with “SPONSORS_TOKEN” as a name, and with the value of the GitHub personal access token that we have created in the prerequisites.</p> <p>You can find more information about how to create a new repository secret in the <a href="https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository">GitHub documentation</a>.</p> <div><h3 id="configure-the-github-action">Configure the GitHub Action</h3></div> <p>Either after having cloned your repository locally, or directly on GitHub, you will need to edit the <code dir="auto">.github/worfklows/scheduler.yml</code> to indicate your GitHub username as a value for “SPONSORKIT_GITHUB_LOGIN”.</p> <p>Commit and push your changes.</p> <div><h2 id="check-your-generated-images">Check Your Generated Images</h2></div> <p>This latter change will trigger the GitHub Action that will generate your sponsors images, commit, and push them at the root level of your repository with the message <em>” chore: update sponsors.svg”</em>.</p> <p>For example, you can see the generated sponsors images of the <a href="https://github.com/julien-deramond/static">julien-deramond/static</a> repository created from this same template.</p> <div><h2 id="optional-generate-the-images-locally">(Optional) Generate The Images Locally</h2></div> <details><summary>More information</summary><p>It might be useful to know, even if rarely useful, it is also possible to run it locally.</p><p>You will need to install the dependencies by running <code dir="auto">npm i</code> in your terminal.</p><p>Then, copy <code dir="auto">.env.example</code> to <code dir="auto">.env</code> still at the root level of your repository with the following content:</p><div><figure><figcaption></figcaption><pre><code><div><div><span>; GitHub provider.</span></div></div><div><div><span>; Token requires the `read:user` and `read:org` scopes.</span></div></div><div><div><span>SPONSORKIT_GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxx</span></div></div><div><div><span>SPONSORKIT_GITHUB_LOGIN=username</span></div></div></code></pre></figure></div><ul> <li><code dir="auto">SPONSORKIT_GITHUB_TOKEN</code> is the GitHub token you created earlier.</li> <li><code dir="auto">SPONSORKIT_GITHUB_LOGIN</code> is your GitHub username.</li> </ul><p>The final step is to run <code dir="auto">npm run build</code> in your terminal to generate the static files:</p><div><figure><figcaption><span></span></figcaption><pre><code><div><div><span>ju</span><span> </span><span>߷</span><span> </span><span>~/j/static</span><span> </span><span>➤</span><span> (main) npm run build (</span><span>0.060674</span><span> </span><span>hrs</span><span>)</span></div></div><div><div><span> </span><span>17:48:16</span></div></div><div><div><span>SponsorKit</span><span> </span><span>v0.8.3</span></div></div><div><div> </div></div><div><div><span>✔</span><span> </span><span>Loaded</span><span> </span><span>from</span><span> </span><span>cache</span><span> </span><span>./.cache.json</span><span> </span><span>17:48:16</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.json</span><span> </span><span>17:48:16</span></div></div><div><div><span>ℹ</span><span> </span><span>Composing</span><span> </span><span>SVG...</span><span> </span><span>17:48:16</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.svg</span><span> </span><span>17:48:16</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.png</span><span> </span><span>17:48:16</span></div></div><div><div><span> </span><span>17:48:17</span></div></div><div><div><span>SponsorKit</span><span> </span><span>v0.8.3</span></div></div><div><div> </div></div><div><div><span>✔</span><span> </span><span>Loaded</span><span> </span><span>from</span><span> </span><span>cache</span><span> </span><span>./.cache.json</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.wide.json</span><span> </span><span>17:48:17</span></div></div><div><div><span>ℹ</span><span> </span><span>Composing</span><span> </span><span>SVG...</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.wide.svg</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.wide.png</span><span> </span><span>17:48:17</span></div></div><div><div><span> </span><span>17:48:17</span></div></div><div><div><span>SponsorKit</span><span> </span><span>v0.8.3</span></div></div><div><div> </div></div><div><div><span>✔</span><span> </span><span>Loaded</span><span> </span><span>from</span><span> </span><span>cache</span><span> </span><span>./.cache.json</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part1.json</span><span> </span><span>17:48:17</span></div></div><div><div><span>ℹ</span><span> </span><span>Composing</span><span> </span><span>SVG...</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part1.svg</span><span> </span><span>17:48:17</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part1.png</span><span> </span><span>17:48:18</span></div></div><div><div><span> </span><span>17:48:18</span></div></div><div><div><span>SponsorKit</span><span> </span><span>v0.8.3</span></div></div><div><div> </div></div><div><div><span>✔</span><span> </span><span>Loaded</span><span> </span><span>from</span><span> </span><span>cache</span><span> </span><span>./.cache.json</span><span> </span><span>17:48:18</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part2.json</span><span> </span><span>17:48:18</span></div></div><div><div><span>ℹ</span><span> </span><span>Composing</span><span> </span><span>SVG...</span><span> </span><span>17:48:18</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part2.svg</span><span> </span><span>17:48:18</span></div></div><div><div><span>✔</span><span> </span><span>Wrote</span><span> </span><span>to</span><span> </span><span>./sponsors.part2.png</span></div></div></code></pre></figure></div><p>All the images are now generated at the root level of your repository. You can check them out in your file explorer.</p><p><strong>Warning</strong>: Once it’s done, please don’t forget to remove at some point your GitHub token from the <code dir="auto">.env</code> file for security reasons. You won’t probably never re-run it from your local machine.</p></details> <div><h2 id="use-the-generated-images-in-your-readmes">Use the Generated Images in Your READMEs</h2></div> <p>Now that the GitHub Action has run, you can use the generated images in your READMEs.</p> <p>For example, you can use the <code dir="auto">sponsors.svg</code> image in your <code dir="auto">README.md</code> file by adding the following code. Don’t forget to replace <code dir="auto">username</code> by your GitHub username in the link’s <code dir="auto">href</code>, link’s <code dir="auto">aria-label</code>, and image’s <code dir="auto">src</code> attributes.</p> <div><figure><figcaption></figcaption><pre><code><div><div><span><span>&#x3C;</span><span>p</span><span> </span></span><span>align</span><span>=</span><span>"</span><span>center</span><span>"</span><span>></span></div></div><div><div><span> </span><span><span>&#x3C;</span><span>a</span><span> </span></span><span>href</span><span>=</span><span>"</span><span>https://github.com/sponsors/username/</span><span>"</span><span> </span><span>aria-label</span><span>=</span><span>"</span><span>Go to username's sponsors page</span><span>"</span><span>></span></div></div><div><div><span> </span><span><span>&#x3C;</span><span>img</span><span> </span></span><span>src</span><span>=</span><span>"</span><span>https://cdn.jsdelivr.net/gh/username/static/sponsors.svg</span><span>"</span><span> /></span></div></div><div><div><span> </span><span><span>&#x3C;/</span><span>a</span><span>></span></span></div></div><div><div><span><span>&#x3C;/</span><span>p</span><span>></span></span></div></div></code></pre></figure></div> <p><strong>Warning</strong>: GitHub can take a while to render the image in your README. If you don’t see it, wait and refresh the page. On my side, it took around 10 minutes to be displayed. As long as the <code dir="auto">https://cdn.jsdelivr.net/gh/username/static/sponsors.svg</code> URL is showing the image, don’t worry, it will be displayed in your README soon.</p> <div><h2 id="final-result">Final Result</h2></div> <p>You can check my own personal sponsors list generated by following this article:</p> <div> <img src="https://cdn.jsdelivr.net/gh/julien-deramond/static/sponsors.svg" alt="Julien Déramond sponsors list" loading="lazy" decoding="async" width="720" height="272"> </div> <p>And find it integrated in one of my projects: <a href="https://github.com/julien-deramond/update-issue-body#sponsors">https://github.com/julien-deramond/update-issue-body#sponsors</a>.</p>GitHubSponsorsTutorialCan I Take This Issue?https://openresource.dev/articles/can-i-take-this-issue/https://openresource.dev/articles/can-i-take-this-issue/Open-source software development thrives on the contributions of volunteers with varying skills and backgrounds. Project maintainers play a critical role in ensuring these contributions are of high quality and align with the project's goals. However, issues arise when contributors do not read guidelines or maintainers do not assign issues, leading to confusion and frustration. This lack of clear communication can leave contributors feeling undervalued and discourage them from contributing further. &lt;br&gt;&lt;br&gt; Maintainers have different reasons for not assigning issues, such as limited resources and large communities. Assigning issues can enhance efficiency, accountability, and resource management but may also create perceptions of favoritism or stifle collaboration. To address these challenges, maintainers should establish clear communication channels, use tools like saved replies, and maintain comprehensive contribution guidelines. By fostering a transparent and supportive environment, maintainers can better manage contributions and maintain a healthy, active community. Mon, 15 May 2023 00:00:00 GMT<p>Open-source software development is a collaborative effort that relies on volunteers to contribute to the project. Contributors have different skill levels and come from various backgrounds. As such, project maintainers have a crucial role in ensuring that the contributions received are of high quality and meet the project’s goals. One way maintainers do this is by providing clear guidelines on how contributors can submit their work. Unfortunately, contributors don’t always take the time to read these guidelines, and maintainers don’t always assign issues, which can lead to confusion and frustration on both sides. In this article, we’ll explore the issue of unassigned contributions and discuss what can be done to address it.</p> <div><h2 id="so-can-i-take-it-or-not">So Can I Take It or Not?</h2></div> <div> <div> Contributor </div> <div> <p>Hey! Can I take this issue?</p> </div> </div> <div> <div> Maintainer </div> <div> <p>Hello! As mentioned in <span>our contributing guidelines</span>, we do not assign issues in this repository. However, if you’d like to contribute a solution, feel free to create a PR directly. Thank you for your interest!</p> </div> </div> <div> <div> Contributor </div> <div> <p>OK thanks!</p> </div> </div> <p>This is a common scenario in open-source projects. A contributor sees an issue that they think they can solve, so they ask if they can take it.</p> <div> <div> Maintainer </div> <div> <p>Seriously, again… What do I usually answer? Hmmm…</p> </div> </div> <p>If you are the maintainer of this open-source project, you start by receiving a notification. You then go to the issue and take the time to respond to the contributor something you may have already said ten times this week. You then go back to your work, and receive another notification from the same contributor saying basically “OK thanks!”.</p> <div> <div> Contributor </div> <div> <p>Seriously? I have already checked the issue, I have the solution!!! They don’t trust me. They think I’m not good enough, they don’t deserve my contribution…</p> </div> </div> <p>If you are the contributor, you may feel frustrated. You may have spent time looking for an issue to work on, and you may have even started working on it. You then ask if you can take it, and the maintainer responds by saying that they don’t assign issues. You then feel discouraged and decide not to contribute to the project.</p> <p><strong>This is a frustrating experience for both the contributor and the maintainer</strong>.</p> <p>The contributor is left wondering if they can actually work on the issue, and the maintainer is left wondering why the contributor didn’t read the contributing guidelines.</p> <div><h2 id="why-do-some-maintainers-assign-issues">Why Do Some Maintainers Assign Issues?</h2></div> <p>Maintaining an open-source project is a challenging task that involves multiple responsibilities. One of them is managing issues reported by contributors or users. Assigning issues to specific maintainers or contributors is a common practice that can help ensure that problems are addressed in a timely and efficient manner and that contributions align with the project’s vision and goals. However, not all maintainers assign issues, or they may only assign a small number of them. In this part, we will explore the reasons why some maintainers choose to assign issues and what are the benefits of assigning issues.</p> <div><h3 id="efficiency">Efficiency</h3></div> <p>Assigning issues to specific individuals helps ensure that they are addressed promptly and efficiently, reducing the likelihood of issues being overlooked or forgotten. It allows maintainers to manage issues more efficiently, ensuring they are resolved in a timely and effective manner. However, the assignee can still benefit from the feedback of the community and maintainers, and this approach is particularly useful for larger projects that receive many issues.</p> <div><h3 id="accountability-and-responsibility">Accountability and Responsibility</h3></div> <p>Assigning issues can help to clarify the responsibilities of different contributors and maintainers. It’s clear who is responsible for resolving an issue when it’s assigned to a specific person. This can reduce confusion and ensure that issues are addressed by the right people. In larger projects, where multiple contributors and maintainers may be working simultaneously.</p> <p>Assigning issues can also create a clear sense of accountability and responsibility. When an issue is assigned to a specific person, they become responsible for resolving it. This accountability can motivate contributors and maintainers to take ownership of the issue and work towards a solution. When contributors know that they are responsible for resolving an issue, they are more likely to focus their efforts on finding a solution. This sense of ownership can also lead to a more engaged and invested community.</p> <div><h3 id="encouraging-contributions">Encouraging Contributions</h3></div> <p>Assigning issues to specific contributors can foster community involvement and collaboration. Assignees have a clear understanding of what needs to be done, leading to increased contributions and a more active community. Additionally, assigning issues can encourage collaboration between contributors and maintainers, leading to more efficient issue resolution and a stronger sense of community.</p> <p>To address unassigned contributions, both contributors and maintainers need to work together.</p> <p>Contributors can help by taking the time to read the project’s contribution guidelines carefully. They should also review the issue tracker and try to find issues that align with their skills and interests. If an issue is not assigned, contributors can reach out to maintainers or community managers for guidance.</p> <p>Maintainers can also take steps to address unassigned contributions. One way is to review the issue tracker regularly and assign issues promptly. They can also update the contribution guidelines and make them more visible to ensure that contributors are aware of them. Maintainers can also provide feedback on contributions, highlighting areas for improvement and encouraging contributors to continue their work.</p> <div><h3 id="better-resource-management">Better Resource Management</h3></div> <p>Assigning issues can also help to manage resources more effectively.</p> <p>By assigning issues to specific contributors or maintainers, the workload can be distributed more evenly. It also helps prevent duplicated work, as contributors can see what others are working on and avoid duplicating their efforts.</p> <p>Assigning issues can also help maintainers to manage their workload. By assigning issues to specific people, maintainers can ensure that they are not overwhelmed with too many tasks at once.</p> <p>This approach can help to prevent burnout and ensure that contributors and maintainers are working on issues that are within their skill level and expertise. It can ensure that maintainers’ time and energy are focused on the issues that matter most.</p> <div><h3 id="avoiding-confusion">Avoiding Confusion</h3></div> <p>Assigning issues can also help to avoid confusion. When multiple people are working on the same issue, it can be difficult to know who is responsible for what. By assigning issues to specific people, maintainers can ensure that everyone knows what they are responsible for and what their role is in addressing the issue.</p> <div><h2 id="why-do-some-maintainers-not-assign-issues">Why Do Some Maintainers Not Assign Issues?</h2></div> <p>Despite the benefits of assigning issues, there are also some challenges that maintainers may face. So there are some maintainers who choose not to assign issues, quite a lot in fact. This lack of assignment can result in contributors not knowing what to work on or feeling discouraged about contributing to the project. In this part, we will explore the reasons why some maintainers do not assign issues, or sometimes only a small amount of them.</p> <div><h3 id="limited-resources">Limited Resources</h3></div> <p>Maintaining an open-source project can be a daunting task, and the responsibility is often shouldered by a handful of maintainers. These maintainers are responsible for reviewing contributions, triaging issues, and coordinating with contributors to ensure the project’s growth and success. However, due to limited resources, some maintainers may not be able to assign issues effectively, which can lead to frustration among contributors and a decline in the project’s growth.</p> <p>Maintaining an open-source project requires a significant amount of time and effort, and it can be a voluntary and unpaid job for many maintainers. As such, they may not have the financial resources or personnel to manage every issue that is reported.</p> <p>Assigning an issue without proper analysis and discussion is inadequate and can impede its development. This is especially true for issues coming from the community, as they may lack sufficient details. Prioritizing, analyzing, and discussing the issue is necessary before assigning it to a maintainer or contributor for resolution. Assigning issues to specific people requires time and effort, and some maintainers may prefer to focus their attention on other aspects of the project, such as code review or documentation. Furthermore, some maintainers may be juggling multiple projects or other commitments in their personal and professional lives, which can limit their ability to assign issues.</p> <p>They are often already too busy reviewing contributions. Open-source projects are often community-driven, and they can receive a large number of contributions, especially when they gain traction. Each contribution requires review, testing, and integration, which can be time-consuming, especially for maintainers who have other responsibilities. In such cases, maintaining the project can become a daunting task, and maintainers may be unable to keep up with the influx of contributions, leading to a backlog of unassigned issues and sometimes even unassigned pull requests.</p> <p>The issue tracker can become overwhelming, making it difficult to assign issues to the right people. The issue tracker serves as a central hub for the project’s issues, feature requests, and pull requests. As the project grows, the number of issues and pull requests can quickly pile up, leading to confusion on the part of contributors. Without proper triaging and assignment, contributors may not know what to work on or feel discouraged about contributing to the project, resulting in a decline in contributions.</p> <div><h3 id="large-communities">Large Communities</h3></div> <p>As the community expands or is already large, maintainers may struggle to keep track of all its members and their capabilities. In such cases, assigning issues can become a daunting task, as maintainers may be uncertain of the skill level and commitment of potential contributors. Junior developers and new open source members may be attracted to issues in already popular projects, seeking mentorship and opportunities to contribute, but this can overwhelm maintainers who cannot mentor everyone or have limited resources for reviewing contributions.</p> <p>To assign issues appropriately, maintainers may need to review past contributions, evaluate code quality, and reach out to potential contributors to discuss their interest in the project. However, this can be a time-consuming process, leading some maintainers to avoid assigning issues altogether. This can create a backlog of issues that go unaddressed, causing frustration among contributors.</p> <p>And this approach can backfire, as it can create a backlog of issues that are not being addressed, which can cause frustration among contributors. In such cases, it is essential to establish clear guidelines for issue assignment and ensure that all members of the community are aware of them.</p> <div><h3 id="collaborative-approach">Collaborative Approach</h3></div> <p>Some maintainers believe that assigning issues can create silos and discourage collaboration. They may prefer to have an open forum where anyone can contribute to resolving issues. This approach allows the community to work together and share knowledge and expertise. They encourage contributors to take ownership of the project and work together to resolve issues, rather than relying on a single maintainer to manage all aspects of the project.</p> <p>While this approach can be effective, it can also result in a lack of direction and oversight. Without clear guidance or leadership, contributors may not know what to work on or how to approach a particular issue.</p> <p>To address this, maintainers can provide clear documentation on the project goals and how to get involved. Additionally, they can establish communication channels for contributors to ask questions or provide feedback, or even encourage contributors to work in pairs or small groups to resolve issues. Another potential solution is to use a rotating ownership model, where issues are assigned to a specific contributor for a set period of time, after which ownership of the issue rotates to another contributor. This approach allows for individual ownership of issues while still promoting collaboration and knowledge-sharing.</p> <p>By doing so, maintainers can foster a collaborative environment while still maintaining some level of oversight and direction.</p> <div><h3 id="avoiding-favoritism">Avoiding Favoritism</h3></div> <p>Assigning issues can also lead to accusations of favoritism or bias. Some maintainers may choose not to assign issues to avoid any perception of preferential treatment. By allowing anyone to work on any issue, maintainers can ensure that everyone has an equal opportunity to contribute. This approach can help to create a more inclusive and welcoming community, where all contributors are valued and respected.</p> <p>However, this approach can also result in confusion and duplication of effort. If multiple contributors are working on the same issue, it can lead to wasted time and resources.</p> <p>One way to ensure that everyone has a fair opportunity to contribute to a project is through establishing clear guidelines and protocols for contribution. For instance, the project can have a clearly defined process for claiming issues, stating who is responsible for which tasks, and how contributors can go about resolving issues. This approach allows contributors to work together in a coordinated fashion and avoid duplication of effort. In some cases, it may even foster a sense of friendly competition amongst contributors, which can help to drive innovation and progress.</p> <p>They can also provide feedback on contributions to ensure that everyone is working towards the same goal, thus minimizing duplication of effort and confusion.</p> <div><h3 id="trust-community">Trust Community</h3></div> <p>Another reason why some maintainers do not assign issues is that they trust the community to self-organize and take ownership of issues without assigning them to specific individuals. This approach is based on the belief that a highly engaged and motivated community will work together to resolve issues and prioritize tasks. It can be an effective approach in projects with a large and active community where multiple contributors can work on the same issue simultaneously.</p> <p>When maintainers trust the community to self-organize, they can focus on other aspects of the project such as developing new features, maintaining documentation, or mentoring new contributors. This approach can also be useful in situations where maintainers have limited resources or are unable to keep up with the volume of incoming issues. By allowing the community to take ownership of the project, maintainers can create a sense of ownership and belonging within the community, leading to increased participation and collaboration.</p> <p>However, relying solely on the community to self-organize can also have its drawbacks. Without clear guidance or leadership, contributors may not know how to prioritize tasks or resolve issues effectively. Sometimes, the issues are not yet read by the maintainers and contributors start the development of something useless which is not what the maintainers want. This can result in duplication of effort, wasted time and resources, and may lead to frustration and disengagement among contributors.</p> <p>To address these issues, maintainers can establish clear guidelines on how to claim an issue and work on it. They can also provide feedback on contributions to ensure that everyone is working towards the same goal. Additionally, maintaining open communication channels for contributors to ask questions or provide feedback can help foster a collaborative environment while still maintaining some level of oversight and direction.</p> <div><h3 id="lack-of-familiarity">Lack of Familiarity</h3></div> <p>We may tend to forget it but not all the maintainers know everything about open source so some maintainers may “choose” not to assign issues simply because they are not familiar with the process. Assigning issues can be a complex task, especially in large projects with many contributors. If a maintainer is not comfortable with the process, they may choose to avoid it altogether. Additionally, some maintainers may be new to the project and may not yet have a good understanding of the various roles and responsibilities. This can make it difficult to assign issues to the appropriate parties.</p> <p>In this case, this article may be a good starting point 🙂</p> <div><h2 id="hybrid-approach">Hybrid Approach</h2></div> <p>An open-source project can be maintained by a core team working full-time, often linked to a company. Then, issues assignments may be handled differently than in other open-source projects. Indeed, they can rely on a specific agenda and deadlines, so they may assign issues to ensure accountability, clear ownership, prioritization, expertise, and consistency. At the same time, the core team may also allow external contributors to contribute to the project for diverse perspectives, community building, increased productivity, and learning opportunities. In that case, they could not assign issues to external contributors. Here comes our hybrid approach.</p> <p>As an external contributor, you won’t probably be assigned to an issue for several reasons:</p> <ul> <li>The issue must be tackled soon and they can’t rely on an outsider to deliver a specific task with a deadline.</li> <li>The issue requires extra internal information the contributor can’t have access to or internal discussions that happened or will happen and are not tracked, or won’t be tracked in the repository.</li> </ul> <p>However, it might happen, depending on their contributing guidelines, for unprioritized issues that don’t have any deadline yet. Most repositories use a dedicated label in this case to let know outsiders that they can help and contribute. And of course, they will probably be happy to review code not related to already planned issues or fixes.</p> <p>By allowing external contributions to the project, the core team might benefit from:</p> <ul> <li>A wide range of new perspectives and ideas.</li> <li>Building a community around the project.</li> <li>Increasing productivity by leveraging the contributions of others.</li> <li>Recruiting members of the community.</li> <li>Learning from the contributions of others and improving their own skills and knowledge.</li> </ul> <div><h2 id="how-to-address-the-issue-of-not-assigning-issues">How to Address the Issue of Not Assigning Issues</h2></div> <p>Not assigning issues is a choice made by the maintainers based on several criteria as seen in the previous sections.</p> <div><h3 id="strong-workflow">Strong Workflow</h3></div> <p>To counter-balance the fact that issues are not assigned, projects often rely on a strong issues workflow with a powerful system of labeling and triage to help identify the complexity of the tasks, the status of the analysis, whether the issue is ready to develop or not, the target versions, the scope, etc. so that the community can be autonomous, but also to reduce the noise for the maintainers who have most of the time really limited resources.</p> <p>This full backlog can be accompanied by a schema representing the whole workflow of states of issues and sometimes even pull requests, the actors, etc. It can be linked to a roadmap.</p> <p>To make the most of their limited resources, maintainers can set up automatic triage systems that categorize and prioritize issues based on their severity or complexity so that the community can be autonomous and evaluate where they could be helpful depending on their level and expertise. High-priority or high-complexity issues can be tackled by experienced contributors or reserved for the core team while low-priority or low-complexity might be left for the new contributors to help them gain experience.</p> <p>Additionally, maintainers can reach out to the community to encourage contributions and provide guidance on how to best help with the project so that the whole process runs smoothly. By doing so, maintainers can ensure that they are making the most of their limited resources, while also making it easier for contributors to get involved.</p> <p>Labeling is very powerful as it can filter the backlog by elements but also be used for automation in projects.</p> <p>Everything can start from the creation of these issues with the issues templates to guide contributors in providing the necessary information when they create an issue. This can include a checklist of requirements that need to be met before an issue can be treated, such as providing a clear description of the problem, steps to reproduce, any relevant logs or errors messages, or motivation if this is a new feature.</p> <ul> <li><a href="https://docs.gitlab.com/ee/user/project/description_templates.html">Description templates on GitLab</a></li> <li><a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository">Configuring issue templates on GitHub</a></li> </ul> <aside aria-label="Tip"><p aria-hidden="true">Tip</p><div><p>When you don’t assign issues in your repository, it can be reminded at the end of the issues!</p></div></aside> <p>At the time of writing, GitHub doesn’t provide any options to add some Markdown content at the end of the issues when using issue templates. However, you can use GitHub Actions to do that. Here is an example of a GitHub Action that adds a message for newly created issues:</p> <div> <div> <span> <a href="https://github.com/Open-reSource/labs-append-markdown-to-issues"> <span><span>Open-reSource/</span><br>labs-append-markdown-to-issues</span> </a> <span>[Labs] Automatically append Markdown to issues</span> </span> <img src="https://avatars.githubusercontent.com/u/129324099?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p>An infinite way of managing labels is possible. Let’s imagine, for example, a <span>to analyze</span> label that can be picked up only by a core team member. When this core team member analyzed the issue and provided expectations, clarity, and guidance, the label could be transformed into an <span>analyzed</span> label, and a new <span>ready for dev</span> label could be applied combined to <span>high priority</span> and <span>low complexity</span> labels, and a <span>version 12</span> label, <span>bug</span> or <span>feature</span>, <span>core team</span> if it is reserved for the core team, or <span>pr welcome</span> when it is OK for external contributors to work on it. When doing that, contributors can start to help or not, filter the backlog by labels, and the core team can focus on the most important issues. If the workflow is automated, the issue can go to one or another project, be in a roadmap, etc. This is just an example, but you can imagine how powerful it can be.</p> <div><h3 id="communicate-clearly">Communicate Clearly</h3></div> <p>By establishing clear communication channels, maintainers can provide guidance to contributors and answer any questions they may have about the assignment process and issues workflow. This can also help build trust and foster a sense of community among contributors, which can lead to greater collaboration and more successful outcomes.</p> <p>By taking the time to establish clear guidelines and protocols for issues assignment and maintaining open communication with contributors, maintainers can help ensure that each issue is addressed by the most qualified contributor, leading to more successful outcomes for the project as a whole.</p> <p>Whether maintainers put in place a simple or advanced workflow, it must be clearly explained somewhere. Depending on the amount of information, it can be directly in the Contributing Guidelines or in a Wiki, documentation, etc. linked from the Contributing Guidelines.</p> <p><strong>If issues are assigned, make sure that it’s clearly explained in the Contributing Guidelines</strong>.</p> <p><strong>If issues are not assigned, make sure that it’s clearly explained in the Contributing Guidelines</strong>.</p> <div><h4 id="the-importance-of-contribution-guidelines">The Importance of Contribution Guidelines</h4></div> <p>Yes, it is important for open-source projects to have Contributing Guidelines to provide critical information about the project, including its goals, coding standards, how to submit changes, how to ask for help, and how to get involved in the community.</p> <p>This is also the place where are explained how contributors can report issues and how maintainers will manage them. <strong>The guidelines should include information on whether issues will be assigned or left unassigned, and why</strong>. This will help to set expectations for both contributors and maintainers and ensure that everyone is on the same page.</p> <p>If an open-source project is maintained by a core team working for a company, the contribution guidelines should make it clear that issues will be managed by the core team and may or may not be assigned to individual team members. The guidelines should also explain the reasons behind this approach, such as the need to ensure that issues are addressed in a timely and efficient manner, and the fact that the core team has the expertise and resources to manage the project effectively.</p> <p>If an open-source project is maintained by a community of volunteers, the contribution guidelines should explain how issues will be managed and whether they will be assigned or left unassigned. The guidelines should also provide guidance on how contributors can help to manage the issue tracker, such as by reviewing and triaging issues, and how they can get involved in the project’s decision-making process.</p> <p>Regardless of the approach taken by an open-source project, it’s important to have clear and transparent contribution guidelines that set expectations for both contributors and maintainers. This will help to ensure that the project is sustainable and that issues are addressed in a timely and efficient manner. On top of explaining what is the process, it is also interesting to explain why this choice has been made by the maintainers. It will help contributors who will read the contributing guidelines, but can also be useful to remind this rule for those who don’t read the contributing guidelines. It happens sometimes, isn’t it? ;)</p> <div><h4 id="often-contributors-dont-read-the-contributing-guidelines">Often, contributors don’t read the contributing guidelines</h4></div> <p>First of all, contributors may not even know their existence. Always remind that each day, there are newcomers in the open source world who don’t know how it works. But let’s be honest, apart if the Contributing Guidelines are not at the right place, contributors don’t always take the time to read them because they may be in a hurry to start working on the project, or because they assume that their previous experience will suffice.</p> <p>So the frustration of maintainers can be understood rather easily, especially if they spent time writing down a thorough explanation of why the repository doesn’t assign issues. Reminding days after days for years that the repository doesn’t assign issues feels like repeating over and over the same thing. But always remind that you are not talking to the same person who has a different background regarding OSS and probably does not have the same expertise as you in the field.</p> <p>Streamers, for example, use pre-defined messages, videos, or FAQs in order not to repeat the same information to the newcomers (who almost always ask the same things based on the streamer’s point of view) so that they are not bothered when they are streaming, and the viewers can still have the information. Having tools answering for you, either semi-automatic or automatic, will help not become angry at contributors after repeating the same thing over and over.</p> <p>In a nutshell:</p> <ul> <li><strong>Make the Contributing Guidelines clear and easy to find.</strong> Ensure that they are prominently displayed on the project’s website, README file, in the documentation, in the issues templates, etc. Make sure they are easy to read and understand, with clear instructions on how to contribute and how the issues are handled in the global workflow.</li> <li><strong>Communicate clearly with contributors.</strong> Even if it is mentioned everywhere, always remind nicely this information to the contributors who make mistakes. Provide clarity and guidance.</li> <li><strong>Be consistent.</strong> Ensure that the rules for assigning issues are consistent across the project and that all maintainers are aware of them. This can help prevent confusion and ensure that all contributors are treated fairly. Having a unique reference stored in only one place is really handy because maintainers will be able to link this reference instead of reinterpreting the content every time, and maybe not being consistent. Plus, it’s always true even if the reference changes.</li> <li><strong>Consider revisiting the guidelines.</strong> If you find that many contributors are not following the guidelines, it may be worth revising them to be clearer or to better reflect the needs of the project. However, be sure to communicate any changes clearly to existing contributors and provide guidance on how to adjust their contributions accordingly.</li> </ul> <p>Overall, the key is to be patient, clear, and helpful in your interactions with contributors. By doing so, you can create a welcoming and productive community around your open-source project</p> <div><h3 id="manual-semi-automatic-and-automatic-tools">Manual, Semi-automatic, and Automatic Tools</h3></div> <p>Overall, by using a combination of manual, semi-automatic, and automatic tools, maintainers can help to manage the influx of questions from contributors who are unsure about taking up an issue. This can help to ensure that contributors are able to contribute effectively and that maintainers can focus on other aspects of the project.</p> <p>There are several manual and automatic tools that maintainers can use to help handle these questions and politely refuse them by mentioning the contribution guidelines.</p> <p><strong>Direct communication</strong> is not really a tool, but this is often the way it is handled by maintainers. They can engage with contributors who are unsure about taking up an issue, write down a specific <strong>personalized message</strong>, help clarify any confusion and ensure that contributors feel supported and empowered to contribute in the right way, and even provide alternative issues or areas of the project where the contributor can help. But it takes a huge amount of time, especially in a big community, and the content can be inconsistent.</p> <p>In most of the Git source code platforms, it is possible to set up <strong>saved replies</strong>:</p> <ul> <li><a href="https://docs.gitlab.com/ee/user/profile/comment_templates.html">Comment templates on GitLab</a></li> <li><a href="https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies/using-saved-replies">Using saved replies on GitHub</a></li> </ul> <p>It is only a semi-automatic tool but it can help save a lot of time by not repeating over and over the same thing. Maintainers will lose the personalized side but will gain consistency with a clear and precise answer accompanied by links pointing to unique resources.</p> <p>If you are maintaining OSS projects or communities on different platforms, you may opt for <strong>decentralized messages and actions</strong> stored in your own environment for transversal usage. Tools like <a href="https://www.alfredapp.com/">Alfred</a> on macOS could be used in this spirit.</p> <p>Writing this article was the occasion to try creating a <strong>semi-automation tool based on labels</strong>. Maintainer can add a <span>we don't assign issues</span> label to an issue right after a comment asking to be assigned. This label will trigger a GitHub action that will write a personalized comment explaining that the repo is not handled that way, and then remove this label automatically. We could even hide the original contributor’s comment in the process.</p> <div> <img src="https://user-images.githubusercontent.com/17381666/236413271-12b7b2f2-12b1-4498-99d0-19db8b4b97d8.png" alt="" loading="lazy" decoding="async" width="720" height="274"> </div> <p>The source code of this experiment is available on GitHub via the card below.</p> <div> <div> <span> <a href="https://github.com/Open-reSource/labs-we-don-t-assign-issues"> <span><span>Open-reSource/</span><br>labs-we-don-t-assign-issues</span> </a> <span>[Labs] "we don't assign issues" label that writes a comment and is then auto-deleted</span> </span> <img src="https://avatars.githubusercontent.com/u/129324099?s=50" alt="" loading="lazy" decoding="async" width="50" height="50"> </div> </div> <p>Unfortunately, if there are intermediate comments before maintainers have the time to use this label, it won’t work. And it stays semi-automatic.</p> <p>This was a nice experiment, but <strong>can we go further with full automation?</strong> Actions can already be triggered when a comment is created or updated, it would only be a matter of time to create a bot that would be able to answer automatically to the contributor.</p> <p>We keep seeing new AI tools popping up every day in our feeds. They are pretty powerful and help automation. But so far, we haven’t had the occasion to find or test such tools for this specific use case. If you have any suggestions, or links, you can <a href="https://github.com/Open-reSource/openresource.dev/issues/new/choose">create an issue</a> so that we can test them and improve this article. Or come talk about it on <a href="https://discord.gg/fpUDwEMGwE">our Discord</a>.</p>CommunityContributionHow to Create a Code of Conduct for an Open-Source Projecthttps://openresource.dev/articles/how-to-create-a-code-of-conduct-for-an-open-source-project/https://openresource.dev/articles/how-to-create-a-code-of-conduct-for-an-open-source-project/Creating a code of conduct is vital for fostering a safe and welcoming community within an open-source project. Often, this document is prepared before the community even forms, setting clear expectations and behavioral guidelines from the outset. The process includes defining goals and scope, researching existing codes of conduct, drafting, reviewing and approving the document, publishing, and regularly updating it. Having a code of conduct helps establish a positive social atmosphere, protecting participants and maintainers from unproductive attitudes and ensuring a supportive environment for all. &lt;br&gt;&lt;br&gt; A well-defined code of conduct outlines expected behaviors, the scope of its application, and procedures for handling violations. The Contributor Covenant is a widely-adopted example, promoting respect and inclusion within open source communities. By researching existing codes like the Contributor Covenant, Ubuntu Code of Conduct, and others, project maintainers can identify best practices to incorporate. Once drafted, the document should be reviewed by key stakeholders and communicated clearly to the community. Regular reviews ensure the code remains relevant and effective, fostering a healthy, collaborative environment and addressing any violations appropriately to maintain community standards. Thu, 13 Apr 2023 00:00:00 GMT<p>Creating a code of conduct is an essential step in ensuring a safe and welcoming community for an open-source project. In many cases, the code of conduct may be created before the community even exists. This can be beneficial as it ensures that the project starts with clear expectations and guidelines for behavior. The process of creating a code of conduct involves several steps, including defining goals and scope, researching existing codes of conduct, drafting the document, reviewing and approving the document, publishing and communicating the code of conduct, and regularly reviewing and updating the document.</p> <div><h2 id="why-do-we-need-one">Why do we need one?</h2></div> <p>By adopting a code of conduct for your open-source project, you can establish clear expectations for participant behavior, which can help foster a positive social atmosphere within your community. In turn, this can not only protect your participants, but also yourself as the project maintainer, as unproductive attitudes from participants can ultimately make you feel drained or unhappy about your work. By being proactive and enforcing a code of conduct, you can facilitate healthy and constructive behavior, which can reduce the likelihood of issues arising and make your project a more welcoming and supportive environment for all.</p> <div><h2 id="define-the-goals-and-scope">Define the Goals and Scope</h2></div> <p>The first step is to define the goals and scope of the project. This involves considering the project’s purpose, its intended audience, and the types of behavior that are expected from contributors and users. The goals of the code of conduct should be clear and concise and should outline the expectations for all contributors, users, maintainers, and community members.</p> <p>Defining the goals and scope of a project is the first step in creating a code of conduct. This involves identifying the project’s purpose, intended audience, and expected behavior from contributors and users. The code of conduct should have clear and concise goals that outline the expectations for all community members, including contributors, users, and maintainers.</p> <p>Additionally, a code of conduct should also specify where it applies, who it applies to (including sponsors), what actions will be taken if someone violates it, and how individuals can report any violations. Considering “where it applies”, we are often thinking only about issues, pull requests, and discussions, but it can apply also to community events, social media, communication applications, etc.</p> <div><h2 id="research-existing-codes-of-conduct">Research Existing Codes of Conduct</h2></div> <p>Whether the community already exists or not, the next step is to research existing codes of conduct to identify what works and what doesn’t, but also to have a base to work on. This can be done by reviewing codes of conduct from similar projects or industries. The goal is to identify best practices and guidelines that can be incorporated into the code of conduct.</p> <div><h3 id="contributor-covenant">Contributor Covenant</h3></div> <p>The <a href="https://www.contributor-covenant.org/">Contributor Covenant</a> is a widely-used code of conduct to free and open-source software projects, created by <a href="https://github.com/CoralineAda">Coraline Ada Ehmke</a> in 2014. This code of conduct outlines specific behaviors that are expected from contributors, such as being respectful of differing viewpoints, avoiding offensive language, and refraining from harassment or discrimination. The goal of the Contributor Covenant is to ensure that everyone can participate in open-source projects without fear of being marginalized or excluded and to promote a culture of kindness and empathy in the tech industry.</p> <p>It has been adopted by thousands of open-source projects and many prominent companies including Google, Intel, GitLab, and open-source projects including Vue.js, Symfony, Bootstrap. The code outlines specific behaviors expected of contributors, such as being respectful of differing viewpoints and avoiding offensive language. In 2021, it has been included in the <a href="https://ethicalsource.dev/">Organization for Ethical Source</a>. The Contributor Covenant has played a significant role in promoting a culture of kindness and empathy within the open source community.</p> <p>Adopting the Contributor Covenant as your code of conduct offers several benefits:</p> <ul> <li>It is widely recognized within the community, meaning that the values of the community can be instantly communicated and understood.</li> <li>It has been reviewed and adopted by many which makes it a trusted and reliable option.</li> <li>If you are unsure about how to create your own code of conduct, the Contributor Covenant is readily available and can provide a practical starting point for creating conduct that reflects the values of your community.</li> <li>It has been <a href="https://www.contributor-covenant.org/translations/">translated into multiple languages</a>, making it accessible and inclusive for a diverse range of contributors.</li> </ul> <aside aria-label="Looking to make a big impact as an open source contributor?"><p aria-hidden="true">Looking to make a big impact as an open source contributor?</p><div><p>Translate or help to translate the Contributor Covenant into your non-English language. With only five languages currently available in the latest version at the time of writing this article, your contribution can help make the open source community more accessible and inclusive. Visit the <a href="https://github.com/EthicalSource/contributor_covenant#translating">Contributor Covenant GitHub repository</a> for instructions on how to get started and make a significant difference.</p></div></aside> <div><h3 id="other-existing-codes-of-conduct">Other Existing Codes of Conduct</h3></div> <p>There are several other well-known codes of conduct in open source, in addition to the Contributor Covenant, or based on it. Here are a few examples:</p> <ul> <li>The <a href="https://ubuntu.com/community/ethos/code-of-conduct">Ubuntu Code of Conduct</a>;</li> <li>The <a href="https://www.mozilla.org/en-US/about/governance/policies/participation/">Mozilla Community Participation Guidelines</a> with a very interesting explanation: <blockquote cite="https://www.mozilla.org/en-US/about/governance/policies/participation/"><p>“These guidelines have been adapted with modifications from Mozilla’s original Community Participation Guidelines, the <a href="https://www.ubuntu.com/about/about-ubuntu/conduct">Ubuntu Code of Conduct</a>, Mozilla’s <a href="https://viewsourceconf.org/berlin-2016/code-of-conduct/">View Source Conference Code of Conduct</a>, and the <a href="https://www.rust-lang.org/conduct.html">Rust Language Code of Conduct</a>, which are based on Stumptown Syndicate’s <a href="http://citizencodeofconduct.org/">Citizen Code of Conduct</a>. Additional text from the <a href="http://lgbtq.technology/coc.html">LGBTQ in Technology Code of Conduct</a> and the <a href="http://wiscon.net/policies/anti-harassment/code-of-conduct/">WisCon code of conduct</a>. This document and all associated processes are only possible with the hard work of many, many Mozillians.”</p></blockquote> </li> <li>The <a href="https://www.djangoproject.com/conduct/">Django Code of Conduct</a>;</li> <li>The <a href="https://www.rust-lang.org/policies/code-of-conduct">Rust Code of Conduct</a> adapted from the <a href="https://blog.izs.me/2012/08/policy-on-trolling/">Node.js Policy on Trolling</a> as well as the <a href="https://www.contributor-covenant.org/version/1/3/0/code-of-conduct/">Contributor Covenant v1.3.0</a>;</li> <li>The <a href="https://github.com/cncf/foundation/blob/main/code-of-conduct.md">CNCF Code of Conduct</a> adapted from the <a href="http://contributor-covenant.org/version/2/0/code_of_conduct/">Contributor Covenant v2.0</a>;</li> </ul> <p>These are just a few examples of the many codes of conduct that exist in the open source community. Each code of conduct may have its own unique focus and guidelines, but they all share the goal of promoting a respectful and inclusive environment for collaboration and contribution.</p> <div><h2 id="draft-the-code-of-conduct">Draft the Code of Conduct</h2></div> <p>After gathering research and input, the code of conduct can be drafted. The code of conduct should be written in clear and concise language and should be easily understood by all members of the community.</p> <p>It should include guidelines on behavior, as well as consequences for violating the code of conduct.</p> <p>It’s crucial to specify the actions that will be taken if there is a violation of the code of conduct. Doing so will convey the seriousness with which you take the code of conduct, assure the community that complaints will be fairly and transparently reviewed, and demonstrate your commitment to enforcing the code of conduct. Providing a private way for people to report violations and specifying who will receive those reports are also essential. Lastly, it’s important to offer an alternative option for people to report violations if they are related to someone who receives those reports.</p> <div><h2 id="review-and-approval">Review and Approval</h2></div> <p>Once the code of conduct is drafted, it is important to review it with key stakeholders, including legal advisors in some cases, and any other relevant parties. These individuals could provide feedback on the code of conduct and ensure that it is legally sound.</p> <div><h2 id="publication-and-communication">Publication and Communication</h2></div> <p>Once the code of conduct is finalized, it should be published and communicated to the community.</p> <p>This can be done through the:</p> <ul> <li>project’s website or documentation <ul> <li>with a link in the footer or elsewhere to a code of conduct stored anywhere.</li> <li>by creating a dedicated page like in <a href="https://about.gitlab.com/community/contribute/code-of-conduct/">GitLab Code of Conduct</a>.</li> </ul> </li> <li>other communication channels like Slack, Discord, Mattermost, etc.. <ul> <li>In <a href="https://astro.build/chat">Astro Lounge Discord</a>, they have it for example in their “rules” channel which contains a link to their code of conduct stored on GitHub.</li> </ul> </li> <li>source code repositories. <ul> <li>For open-source projects, this is mainly where you’re going to find it at the root level of the main repository of the organization.</li> </ul> </li> </ul> <p>It is important to ensure that all members of the community are aware of the code of conduct and understand its expectations. But it is also important to have it available accessible by anyone and in order to link it if one must be reminded of the rules.</p> <div><h3 id="how-to-add-it-to-source-code-repositories">How to add it to source code repositories</h3></div> <div><h4 id="github-provides-some-templates">GitHub Provides Some Templates</h4></div> <p>GitHub offers guidance on creating a Code of Conduct through templates available on their website. When adding a new <code dir="auto">CODE_OF_CONDUCT</code> or <code dir="auto">CODE_OF_CONDUCT.md</code> file through the interface at the root level of your repository, you can select from two different templates to add to your project:</p> <ul> <li>Contributor Covenant;</li> <li>Citizen Code Of Conduct;</li> </ul> <div> <img src="https://openresource.dev/images/add-a-code-of-conduct-to-your-project-1.png" alt="Screenshot of GitHub interface showing what happens at this stage of the tutorial" loading="lazy" decoding="async" width="720" height="190"> </div> <p>You can then complete your code of conduct by filling out a simple form with the required information.</p> <div> <img src="https://openresource.dev/images/add-a-code-of-conduct-to-your-project-2.png" alt="Screenshot of GitHub interface showing Contributor Covenant and a form on the right hand side to fill out the contact method and a button to review and submit the form." loading="lazy" decoding="async" width="720" height="482"> </div> <div> <img src="https://openresource.dev/images/add-a-code-of-conduct-to-your-project-3.png" alt="Screenshot of GitHub interface showing Citizen Code of Conduct and a form on the right hand side with different fields and a button to review and submit the form." loading="lazy" decoding="async" width="720" height="502"> </div> <p>After reviewing your changes, submit them and a <code dir="auto">CODE_OF_CONDUCT.md</code> file will be created at the root level of your repository. You can then view a special display by visiting your repository. An example of this rendering can be seen in the <a href="https://github.com/community/community">GitHub Community repository</a>.</p> <div> <img src="https://openresource.dev/images/add-a-code-of-conduct-to-your-project-4.png" alt="Screenshot of GitHub interface showing the rendering of the Code of conduct reference." loading="lazy" decoding="async" width="285" height="65"> </div> <p>This article may be obsolete in the future regarding some details, please check the latest version of the GitHub documentation for <a href="https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/adding-a-code-of-conduct-to-your-project">Adding a code of conduct to your project</a>.</p> <div><h4 id="manually">Manually</h4></div> <p>Adding a code of conduct in your repository is a straightforward process that works for all source code repository services, including GitHub, GitLab, BitBucket, and more. Simply create a <code dir="auto">CODE_OF_CONDUCT</code> or <code dir="auto">CODE_OF_CONDUCT.md</code> file at the root level of your repository, depending on whether you prefer the Markdown or simple text format.</p> <p>While GitHub provides guidance with templates, you can in fact use any code of conduct you prefer. Except for GitHub, even if most of the source code repository services do not offer a dedicated display in repositories for code of conduct files, it is still crucial for open-source projects to incorporate one, as it is considered a best practice. By storing it at the root level of the project, it can be easily referenced and used as a standard for appropriate behavior within the community.</p> <p>If you have selected the Contributor Covenant as your code of conduct, there is a neat trick to add a badge to your README.md file. You can do this by adding the following code:</p> <div><figure><figcaption></figcaption><pre><code><div><div><span>[</span><span>![</span><span>Contributor Covenant</span><span>]</span><span>(</span><span>https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg</span><span>)</span><span>]</span><span>(</span><span>code_of_conduct.md</span><span>)</span></div></div></code></pre></figure></div> <div> <img src="https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg" alt="Contributor Covenant Badge" loading="lazy" decoding="async" width="156" height="20"> </div> <div><h4 id="reusable-code-of-conduct-in-github">Reusable Code of Conduct in GitHub</h4></div> <p>GitHub provides a convenient feature for reusing a code of conduct across multiple repositories by creating a default code of conduct. This default code of conduct is part of a list of default community health files, including <code dir="auto">CONTRIBUTING</code>, <code dir="auto">FUNDING</code>, and issue and pull request templates. Any repository owned by the account that does not have its own code of conduct file will use this default one. To set this up, you can create a <code dir="auto">.github</code> public repository and add a <code dir="auto">CODE_OF_CONDUCT</code> or <code dir="auto">CODE_OF_CONDUCT.md</code> file at the root level of the repository.</p> <p>To see an example of how this works, you can take a look at <a href="https://github.com/Open-reSource/.github">our <code dir="auto">.github</code> public GitHub repository</a>.</p> <p>This article may be obsolete in the future regarding some details, please check the latest version of the GitHub documentation for <a href="https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file">Creating a default community health file</a>.</p> <div><h2 id="regular-review-and-updates">Regular Review and Updates</h2></div> <p>Finally, the code of conduct should be reviewed and updated regularly to ensure that it remains relevant and effective. This review process should involve the entire community and should be conducted at regular intervals, such as annually.</p> <p>A useful tip for those using the Contributor Covenant is to subscribe to release notifications <a href="https://github.com/EthicalSource/contributor_covenant">in project’s GitHub repository</a>. This way, you can easily stay informed and be alerted when a new version of the code of conduct is released, ensuring that your project stays up-to-date.</p> <div><h2 id="enforcing-the-code-of-conduct">Enforcing the Code of Conduct</h2></div> <p>It’s rare, but in any community, there may come a time when a member violates the code of conduct. When this happens, there are several steps that moderators or maintainers can take to address the situation.</p> <p>The first step is to gather information about the situation. It’s important to treat each community member’s voice as important as your own and take any reports seriously. Investigate the matter even if it doesn’t match your own experience with that person. Before responding, take time to understand what happened by reading through the person’s past comments and conversations to better understand who they are and why they might have acted in such a way. Try to gather perspectives other than your own about this person and their behavior.</p> <p>Once you have gathered sufficient information, it’s important to take appropriate action. Remember that your goal as a moderator or maintainer is to foster a safe, respectful, and collaborative environment. Consider not only how to deal with the situation in question, but how your response will affect the rest of your community’s behavior and expectations moving forward. Depending on the severity of the violation, you may choose to give the person in question a public warning and explain how their behavior negatively impacted others or privately reach out to the person to explain how their behavior negatively impacted others. In some cases, stronger action may be necessary, such as suspending or permanently banning the person from the project.</p>CommunityContribution