
Modern web applications are often built by large teams using many different tools and programming languages. As projects grow bigger, it becomes harder to make sure that everyone is following the same rules and writing code the right way. This is especially true when using a monorepo a single codebase that contains multiple apps, packages, or services.
To solve this, developers use linters tools that automatically check code and point out mistakes. But while most linters check for general issues like code formatting or unused variables, sometimes businesses need more. They need rules that match their own special requirements. This is where custom linters come in.
Custom linters help teams enforce their unique business logic across all the apps and services in a monorepo. In this blog, we’ll explore how to build and use custom linters in monorepos, and why it’s an important topic in modern full stack development. This concept is often included in full stack developer classes, where students learn not only how to code, but also how to build strong and scalable systems.
What Is a Monorepo?
A monorepo (short for “monolithic repository”) is a single code repository that stores code for multiple projects. These could be:
- A frontend app
- A backend API
- Shared utility functions
- Multiple microservices
For example, instead of having separate repos for your website, mobile app, and API, you keep all of them in one place.
Benefits of a monorepo:
- Easier code sharing
- Consistent tools and libraries
- Simpler project setup
- Centralized version control
But monorepos also have challenges, especially around consistency. One developer might change something in a shared area that breaks another part of the project. That’s where linters help.
What Is a Linter?
It is a tool that checks your code for problems. It runs through your files and looks for errors, style issues, or bad practices. If it finds something wrong, it gives a warning or an error.
Some popular linters include:
- ESLint (for JavaScript/TypeScript)
- Pylint (for Python)
- RuboCop (for Ruby)
Example: If a developer writes var instead of let in JavaScript, ESLint can warn them to use the modern keyword.
Most linters come with default rules. But sometimes, your team or company has special rules that are not included. That’s when you need a custom linter.
Why Use Custom Linters?
Custom linters let you enforce business-specific rules in your code. These rules are not about coding style they are about how your business works.
Examples of Business Logic Rules:
- Do not call a payment API directly always use a shared billing service.
- Only team A can modify files in the /security folder.
- Log every user action in the analytics service.
- Always validate user input before saving to the database.
These rules are unique to your company. A regular linter cannot check them. But with a custom linter, you can write rules that match your own policies.
How Custom Linters Work
Custom linters work the same way as regular linters, but you write the rules yourself. They read code, look for patterns, and raise errors or warnings if the code breaks a rule.
You can:
- Extend existing tools like ESLint or TSLint
- Build your own linter from scratch
- Use tools like AST (Abstract Syntax Tree) parsers to understand code structure
You run these linters as part of your development process, either manually or automatically (like in a CI/CD pipeline).
Steps to Build a Custom Linter
Let’s look at a simple step-by-step guide to creating a custom linter rule using ESLint (a common linter for JavaScript and TypeScript).
Step 1: Set Up ESLint
If your project doesn’t already use ESLint, install it:
npm install eslint –save-dev
npx eslint –init
This will create a .eslintrc configuration file.
Step 2: Create a Plugin Directory
Make a folder for your custom rules:
/eslint-plugins/custom-rules
Inside that folder, create a file no-direct-api-call.js:
module.exports = {
meta: {
type: “problem”,
docs: {
description: “Disallow direct calls to external APIs”,
},
messages: {
avoidDirectCall: “Use the billing service instead of calling the API directly.”,
},
},
create(context) {
return {
CallExpression(node) {
if (
node.callee.name === “fetch” &&
node.arguments[0].value.includes(“payments.example.com”)
) {
context.report({ node, messageId: “avoidDirectCall” });
}
},
};
},
};
Step 3: Register the Rule
In your ESLint config (.eslintrc.js), include your rule:
module.exports = {
rules: {
“custom/no-direct-api-call”: “error”,
},
plugins: [“custom”],
overrides: [
{
files: [“*.js”],
rules: {
“custom/no-direct-api-call”: “error”,
},
},
],
settings: {
“import/resolver”: {
node: {
extensions: [“.js”],
},
},
},
};
Now when someone tries to call the API directly, ESLint will give an error.
Enforcing Rules Across a Monorepo
In a monorepo, you often have many apps and services. You can use tools like Nx, Turborepo, or Lerna to manage them. Here’s how to enforce custom linter rules in a monorepo:
- Create a shared linter configuration in a tools or packages folder.
- Include your custom rules in that shared configuration.
- Extend that shared config in every app or service.
This makes sure that everyone follows the same rules, no matter where they are working in the repo.
Common Use Cases for Custom Linters
- Security Rules
- Prevent direct use of sensitive functions
- Block access to secret files
- Code Ownership
- Only certain teams can edit certain folders
- Best Practices
- Force use of internal libraries over third-party tools
- Require error handling for all async functions
- Architecture Enforcement
- Prevent circular dependencies
- Control access between layers (e.g., UI should not talk to database directly)
Benefits of Custom Linters
- Catch bugs early: Stops bad code before it gets to production.
- Save time: Developers fix issues while coding, not after reviews.
- Improve consistency: Everyone follows the same patterns.
- Reduce code review time: Reviewers can focus on logic, not rules.
- Build better habits: New team members learn company rules quickly.
Real-World Example
Imagine you work at a fintech company. You have a rule: “Never store card numbers directly in the database.”
You can write a custom linter rule that checks for insert or save statements containing the field cardNumber. If it finds one, it throws an error and blocks the code from being pushed.
This protects users, follows legal rules (like PCI-DSS), and reduces human error.
Tools That Help
Here are tools that support custom linters in JavaScript/TypeScript monorepos:
- ESLint – Most popular, great plugin support
- AST Explorer – Helps you write and test custom rules visually
- Nx – For managing large monorepos with shared configs
- Prettier – Not a linter, but helps format code alongside
Tips for Writing Good Custom Rules
- Start small – Focus on one rule at a time.
- Make rules clear – Include helpful error messages.
- Allow overrides – Not every rule should be strict.
- Test your rules – Use real project code to check.
- Involve your team – Make sure everyone agrees on the rules.
Why Developers Should Learn This
Modern web development is not just about writing code. It’s about writing the right code, that follows rules, protects users, and supports the business.
That’s why topics like custom linters are now included in full stack developer course in Hyderabad. These programs teach students how to work in real-world environments where code quality and business safety matter.
Conclusion
Custom linters are powerful tools for keeping your codebase clean, safe, and aligned with your business rules. In large projects or monorepos, they help teams avoid mistakes, work faster, and stay consistent.
By learning how to build and use custom linters, full stack developers can go beyond just writing features they can shape how the whole system works. This is a must-have skill in today’s tech world, and something you’ll often learn in structured programs like developer classes.
Whether you’re enforcing simple style rules or complex business logic, custom linters make your team stronger and your code smarter.
Contact Us:
Name: ExcelR – Full Stack Developer Course in Hyderabad
Address: Unispace Building, 4th-floor Plot No.47 48,49, 2, Street Number 1, Patrika Nagar, Madhapur, Hyderabad, Telangana 500081
Phone: 087924 83183
