<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Theo Ephraim</title>
    <description>The latest articles on DEV Community by Theo Ephraim (@theoephraim).</description>
    <link>https://dev.to/theoephraim</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F351051%2F0ebb5388-aad7-415c-8efb-6a5152af33d7.jpeg</url>
      <title>DEV Community: Theo Ephraim</title>
      <link>https://dev.to/theoephraim</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/theoephraim"/>
    <language>en</language>
    <item>
      <title>Level up your env var tooling in Next.js with DMNO</title>
      <dc:creator>Theo Ephraim</dc:creator>
      <pubDate>Mon, 22 Jul 2024 19:20:11 +0000</pubDate>
      <link>https://dev.to/theoephraim/level-up-your-env-var-tooling-in-nextjs-with-dmno-2d43</link>
      <guid>https://dev.to/theoephraim/level-up-your-env-var-tooling-in-nextjs-with-dmno-2d43</guid>
      <description>&lt;h2&gt;
  
  
  Type-safety, validation, leak detection, and more
&lt;/h2&gt;

&lt;p&gt;Dealing with config is Next.js has usually been an afterthought - use &lt;code&gt;process.env&lt;/code&gt;, maybe a &lt;code&gt;.env&lt;/code&gt; file, and call it a day. But the whole experience is clunky and leaves you open to some major security risks.&lt;/p&gt;

&lt;p&gt;Over at &lt;a href="https://dmno.dev?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;DMNO&lt;/a&gt;, we've been building a framework agnostic config &amp;amp; secrets management tool that provides a unified way to manage your config across your entire stack. We're super excited to finally announce that our &lt;a href="https://dmno.dev/docs/integrations/nextjs/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;Next.js integration&lt;/a&gt; is ready - and we believe it is the BEST way to manage configuration in Next.js apps.&lt;/p&gt;

&lt;p&gt;Here's a quick overview of the main problems and how DMNO solves them:&lt;/p&gt;

&lt;h3&gt;
  
  
  👷 Beyond type-safety
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Environment variables are always plain strings, so you must coerce and validate them yourself (if at all). You also won't get any types on &lt;code&gt;process.env&lt;/code&gt; unless you manually add them, and you probably shouldn't put a coerced non-string values back into &lt;code&gt;process.env&lt;/code&gt; anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; DMNO lets you define a simple schema for your config. Aside from being more clear, this lets us do some magical things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easily add &lt;strong&gt;coercion and validation&lt;/strong&gt; to your config, so you are guaranteed the data is what you think it is&lt;/li&gt;
&lt;li&gt;Validates your config during your build and &lt;strong&gt;before boot&lt;/strong&gt;, so you'll know exactly what's wrong before bringing down prod&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-generated TypeScript types&lt;/strong&gt; that match your schema, including detailed JSDoc comments explaining what each config item does&lt;/li&gt;
&lt;/ul&gt;

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

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

&lt;h3&gt;
  
  
  🔐 Effortless secure collaboration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Every time we onboard a new team member or add a new external service, we often need to share some set of secrets. You've &lt;em&gt;never&lt;/em&gt; sent anything like that over slack... right?? Not to mention needing to keep all the various platforms we build, test, and run our applications on all in sync.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; With your schema as part of your repo, you'll never pull down the latest only to be met with unexpected crashes due to missing config. Inline documentation and validations let you know exactly what each config item does, and whether it is required. Plugins let you sync sensitive config securely, either &lt;a href="https://dmno.dev/docs/plugins/encrypted-vault/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;encrypted in your repo&lt;/a&gt;, or with secure backends like &lt;a href="https://dmno.dev/docs/plugins/1password/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;1Password&lt;/a&gt;. Plus unifying how config is managed makes it much easier to reason about and debug.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhflu16v7ffccv2oaxhxs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhflu16v7ffccv2oaxhxs.png" alt="1Password demo" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🤐 Leak detection
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; With the edges of client and server getting blurrier each day, it has become easier to accidentally leak sensitive config. Your secrets can end up in server-rendered pages and data, built javascript code, or be sent to the wrong 3rd party - especially logging and error tracking tools. With all the magic Next.js is doing under the hood, it can be very hard to predict what will end up being sent to the client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; DMNO does &lt;a href="https://dmno.dev/docs/get-started/security/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;everything possible&lt;/a&gt; to protect you from accidental leaks. These features are opt-in but we think they are invaluable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DMNO patches global &lt;code&gt;console&lt;/code&gt; methods to &lt;strong&gt;scrub sensitive data from logs&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Built client JS files and outgoing &lt;strong&gt;server responses are scanned&lt;/strong&gt; for leaks before they are sent over the wire&lt;/li&gt;
&lt;li&gt;outgoing HTTP &lt;strong&gt;requests are scanned&lt;/strong&gt; to make sure secrets can only be sent to whitelisted domains - e.g., only send your Stripe key to api.stripe.com&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4lisgy3pcwvtby7w7io.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4lisgy3pcwvtby7w7io.png" alt="Log redaction demo" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyaz8tit2jvwvgk6e7xxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyaz8tit2jvwvgk6e7xxe.png" alt="Leak detection demo" width="800" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5t9s0z7rh879wy8fni8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5t9s0z7rh879wy8fni8.png" alt="HTTP interception demo" width="800" height="207"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  📐 Dynamic configuration control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; The &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; prefix controls whether config is public AND whether it will be static, meaning replaced at build time. If you want build once and deploy for multiple contexts, you'll have to awkwardly wire up fetching the config on your own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; DMNO decouples the concepts of "sensitive" and "dynamic", and supports both &lt;strong&gt;sensitive+static&lt;/strong&gt; and &lt;strong&gt;public+dynamic&lt;/strong&gt; config, and lets you set them explicitly in your config schema. This finer control is easier to reason about and we handle the hard part for you. See our &lt;a href="https://dmno.dev/docs/guides/dynamic-config/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;dynamic config guide&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5cfamv0mvtv7v0qyqwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy5cfamv0mvtv7v0qyqwa.png" alt="Dynamic schema demo" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🌲 Unified config system
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; In a larger projects, especially monorepos, each part of your system ends up with its own hacked together config tooling, and there's no way to share config across services. Keeping things in sync is error-prone and awkward, and dealing with many different tools is a pain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; DMNO lets you easily define config once and share it across your entire monorepo. Even outside of monoepos, using the same config system across your entire project will make your life much easier.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  ⛓️ Flexible value dependencies
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Ideally we could set config values based on other values. While Next.js does have some built-in handling of multiple environment specific &lt;code&gt;.env&lt;/code&gt; files (e.g., &lt;code&gt;.env.production&lt;/code&gt;), this behavior is tied to the value of &lt;code&gt;NODE_ENV&lt;/code&gt;. Since npm module installation behavior is also affected by this, often you'll end up running your build with &lt;code&gt;NODE_ENV&lt;/code&gt; as &lt;code&gt;development&lt;/code&gt; even when doing a non-production build. You can also use &lt;a href="https://nextjs.org/docs/pages/building-your-application/configuring/environment-variables#referencing-other-variables" rel="noopener noreferrer"&gt;$ expansion&lt;/a&gt; to do some basic referencing, but it's extremely limited.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; DMNO's config resolution logic allows you to reference other values however you like. You can define switching logic based on any value (not just &lt;code&gt;NODE_ENV&lt;/code&gt;) and reuse values within arbitrary functions. Your configuration schema all forms a reactive DAG, which can also be visualized for simple debugging.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngofgua2x8jq6fid12pi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngofgua2x8jq6fid12pi.png" alt="Value reuse demo" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  So what's &lt;em&gt;Next&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;While much of what was described above is not specific to Next.js, a &lt;strong&gt;TON&lt;/strong&gt; of specific work went into making sure our Next.js integration &lt;em&gt;just works&lt;/em&gt; without additional setup on your part. We want this to become the default way that everyone deals with configuration in their Next apps, and for JS/TS in general. This stuff may seem like it's not a problem, and day to day it may not be - until it bites you. Setting up your schema isn't much harder than writing a &lt;code&gt;.env.example&lt;/code&gt; file and you get SO much more, so please &lt;a href="https://dmno.dev/docs/get-started/quickstart/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;give it a try&lt;/a&gt;, and let us know what you think!&lt;/p&gt;




&lt;h3&gt;
  
  
  Ready to give it a try?
&lt;/h3&gt;

&lt;p&gt;Hopefully the benefits are obvious, and we know once you try out DMNO, you'll love it 🥰.&lt;/p&gt;

&lt;p&gt;Getting started is incredibly easy and it's 100% free and open-source.&lt;/p&gt;

&lt;p&gt;All it takes is &lt;code&gt;npx dmno init&lt;/code&gt; 🎉&lt;/p&gt;

&lt;p&gt;For more detailed information, visit the &lt;a href="https://dmno.dev/docs/integrations/nextjs/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=nextjs-launch" rel="noopener noreferrer"&gt;DMNO Next.js Integration Guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>security</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Using eslint to its fullest -- and introducing 🛠️lint-fix-nodemon!</title>
      <dc:creator>Theo Ephraim</dc:creator>
      <pubDate>Sun, 15 Mar 2020 20:37:31 +0000</pubDate>
      <link>https://dev.to/theoephraim/using-eslint-to-its-fullest-and-introducing-lint-fix-nodemon-2don</link>
      <guid>https://dev.to/theoephraim/using-eslint-to-its-fullest-and-introducing-lint-fix-nodemon-2don</guid>
      <description>&lt;p&gt;There are lots of articles about why you should be using eslint (and prettier if you're into that) to lint your JavaScript code, so I'm not going to waste your time trying to convince you of that. Instead I'm here to tell you, don't just use them...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DEEPLY INTEGRATE THESE TOOLS INTO YOUR CODEBASE&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;make it easier to use the linter than not&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whether you're building a single page app, an API, or a library to publish on NPM, doing this will save you and your collaborators tons of time and effort. So what do I mean specifically?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto "fix" every time you save&lt;/strong&gt; - 
trust me, this is magic and gives you superpowers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't rely on IDE plugins to do your linting&lt;/strong&gt; - 
add the tools into your repo and dev workflow directly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use git hooks to enforce rules before code gets committed&lt;/strong&gt; -
don't let the infractions build up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're already on board and just want some tooling recommendations, just skip down to the bottom :) Otherwise, let me briefly explain why.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run eslint "fix" every time you save
&lt;/h3&gt;

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

&lt;p&gt;I recently started working in a codebase that doesn't use semicolons. While I prefer (and am used to) using them and we can argue about it for an hour, the truth is it doesn't really matter these days. But I'm going to keep typing them because my fingers are in charge. But while I'm coding, if I realize I typed one, then have to go back and remove it, it's just a complete waste of time if I could let a robot do it for me. With auto-fix enabled, when I save, they just disappear.&lt;/p&gt;

&lt;p&gt;I once had a coworker who refused to use the tooling I had set up (and insisted on using vim but was bad at it). I'd be helping him debug something, and watching him code. Everything would take an extra 20% longer, because I'd watch him write some code, then spot trivial formatting errors, and go back to fix them one by one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT IT'S CHANGING THINGS?!&lt;/strong&gt; That is the point. Learn to work with it and use it to your advantage. When I want to move a block of code into an adjacent if statement, I just move one bracket, hit save, and all the indentation is now magically fixed. Multiply each of those tasks times a few seconds and I've just saved a huge amount of time every day, not to mention the mental energy of thinking about these decisions. This is especially important when working on a project with many people who may have different habits.&lt;/p&gt;

&lt;p&gt;Occasionally you may run into problems with one auto-fixing rule conflicting with another, like preferring short arrow functions vs keeping lines shorter than 100 characters. I'm not going to lie, it can be annoying, and sometimes I've had to add an eslint ignore, or write a statement a different way. But you fine-tune your rules, and you get used to it. The balance of time/effort saved is well worth the occasional hazard.&lt;/p&gt;

&lt;h3&gt;
  
  
  IDE plugins vs integrated tools in your repo
&lt;/h3&gt;

&lt;p&gt;An IDE plugin can be great if you want to highlight linting errors in your code directly. But relying on the plugin to fix on save or keep the code clean for your team is a recipe for not everyone playing by the rules. Not everyone uses the same editor. Not everyone has the same plugins or plugin  settings enabled. &lt;strong&gt;Build it into the repo and make it easier to use the linter than not.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use git hooks to enforce your rules
&lt;/h3&gt;

&lt;p&gt;I've seen countless codebases that have an eslintrc file, but the rules are not actually followed. If you're going to have linting rules, you should enforce them. The easiest way to make sure that is the case is to not let people commit/push code until they follow the rules. Yes it can be annoying, but by always following the rules, you avoid letting the linting errors/warnings build up to the point that they are overwhelming, which makes them less useful. You can always skip the checks during a crisis or set up your rules to be more relaxed for certain scenarios.&lt;/p&gt;

&lt;p&gt;On a related note - also add a linting check in your CI tools!&lt;/p&gt;

&lt;h1&gt;
  
  
  Great - just show me how already &lt;a&gt;
&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;What tools to use really depend on what kind of project you are working on, but here are a few quick suggestions. I'll add more resources here as I find new great tools.&lt;/p&gt;




&lt;h3&gt;
  
  
  Git hooks
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/typicode/husky" rel="noopener noreferrer"&gt;Husky&lt;/a&gt; is an awesome tool that adds configurable git hooks to your repo. It has a ton of options, and is super easy to use. After installing as a dev dependency, you define hooks in your package.json file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;


  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eslint ./"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"husky"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pre-commit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NODE_ENV=production npm run lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"pre-push"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run test"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Enabling lint+fix in a webpack project
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://github.com/webpack-contrib/eslint-loader" rel="noopener noreferrer"&gt;eslint-loader&lt;/a&gt; to add eslint into your (dev) webpack build process. After installing as a devDependency, you need to add the following to the module.rules section your development config:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// enable eslint + fix&lt;/span&gt;
  &lt;span class="nl"&gt;enforce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pre&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// runs on the original file&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// adjust for your project&lt;/span&gt;
  &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eslint-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;emitWarning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// false to show errors in browser overlay&lt;/span&gt;
    &lt;span class="nx"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// enable fixing!&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  Enabling lint+fix in a vue-cli project
&lt;/h3&gt;

&lt;p&gt;Vue cli just uses webpack under the hood, but abstracts away the webpack config. Use &lt;a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" rel="noopener noreferrer"&gt;@vue/cli-plugin-eslint&lt;/a&gt; to add eslint-loader into your build process. Install using the vue-cli with &lt;code&gt;vue add eslint&lt;/code&gt;. Lint on save is enabled by default.&lt;/p&gt;




&lt;h3&gt;
  
  
  Enabling lint+fix in a backend / api project
&lt;/h3&gt;

&lt;p&gt;This is why I wrote this article - to share a new tool I've released :)&lt;br&gt;
&lt;strong&gt;Say hello to &lt;a href="https://github.com/theoephraim/lint-fix-nodemon" rel="noopener noreferrer"&gt;lint-fix-nodemon&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Confused? Already using eslint with &lt;a href="https://github.com/remy/nodemon" rel="noopener noreferrer"&gt;nodemon&lt;/a&gt;? It's not too hard, but here are the problems I encountered with all the different setups I tried:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Double restarts&lt;/strong&gt; - nodemon detects a first change when you save the file, and then again after eslint fixes it. Restarting twice may not be a huge deal, but anything that slows you down that happens 100 times a day adds up quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ESLint failures can get stuck&lt;/strong&gt; - in certain circumstances (like starting up your &lt;code&gt;npm run dev&lt;/code&gt; script at the beginning of a coding session) if eslint fails, it can fail the process so it doesn't start watching your files. Why should things work differently the first time I run it? If you have a lot of errors to fix, this can be a big pain...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tool (which I've been using as an unpublished script for a long time) fixes both of these issues. It watches your files, runs eslint on change, and only restarts nodemon AFTER fixes have been applied. Also if anything fails on the first run, no problem - it will keep watching and try again when you save.&lt;/p&gt;

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

&lt;p&gt;So after installing (&lt;code&gt;npm i lint-fix-nodemon --save-dev&lt;/code&gt;), configure things in your package.json file. I usually add script called "dev" to start the tool. By default nodemon will run the "main" script (or you can pass one to the script), and it will respect the "nodemonConfig" settings it finds. By default it will ignore "node_modules" and any files/folders that start with ".". The same files that are "watched" will be linted.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lint-fix-nodemon api/start.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nodemonConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;watch:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api/"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;ignore:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"api/scripts"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;h3&gt;
  
  
  So what's next?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I could probably add a lot more options to this library. Please open issues if you run into problems!&lt;/li&gt;
&lt;li&gt;I use a similar script to run the linter (with fixes) and then run my tests (using jest) on each save. Hello TDD! I'll probably release something more generalized soon, maybe a tool called &lt;code&gt;lint-fix-and&lt;/code&gt; :)&lt;/li&gt;
&lt;li&gt;I still have been wanting to spend some time to set up automated linting   to auto fix the css/less/sass and pug in my vue single file components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this article and &lt;a href="https://github.com/theoephraim/lint-fix-nodemon" rel="noopener noreferrer"&gt;lint-fix-nodemon&lt;/a&gt; are helpful for a few folks. Please let me know if you have any other suggestions to add, or are stuck on something.&lt;/p&gt;

&lt;p&gt;Cheers!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>productivity</category>
      <category>node</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
