Have you ever pushed a perfectly working Next.js app to Netlify and suddenly got a wall of red text saying:
Module not found: Can't resolve '@/components/Button'
Don’t worry — you didn’t break anything.
I ran into the same issue while deploying Sellexa, a social-commerce marketplace for minority entrepreneurs, and learned that the problem isn’t your code — it’s how your environment handles path aliases and case sensitivity.
Let’s unpack it.
Why It Happens
This error usually means one of two things:
1. Your local environment is forgiving — Netlify’s isn’t.
macOS and Windows use case-insensitive file systems, but Netlify’s Linux servers are case-sensitive.
So:
import Button from "@/components/ui/button";
will work locally even if your file is named Button.tsx,
but it fails on Netlify because button ≠ Button.
2. Your alias (@) isn’t configured for the build
Many Next.js starters and tutorials assume your editor or TypeScript magically knows what @ means.
But unless you explicitly tell both TypeScript and Webpack, Netlify’s build system will have no clue how to resolve it.
The Fix
Follow these four steps and you’ll never see this error again.
Step 1 — Add paths to tsconfig.json
At the project root, open (or create) tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
This tells TypeScript and your IDE that @ refers to your /src folder.
Step 2 — Add a Webpack alias in next.config.mjs
Next.js still needs to understand the alias during the production build.
Open next.config.mjs and add this snippet:
import path from "node:path";
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config) => {
config.resolve.alias = {
...(config.resolve.alias ?? {}),
"@": path.resolve(process.cwd(), "src"),
};
return config;
},
};
export default nextConfig;
Now @ will resolve properly both locally and on Netlify.
Step 3 — Match file and import casing
On Linux, Button.tsx and button.tsx are different files.
Run this to double-check your imports:
git grep -i "@/components"
Ensure your import casing matches your filenames exactly.
Step 4 — Clear cache and redeploy
In Netlify:
Go to your site → Deploys
Click “Trigger deploy” → “Clear cache and deploy site”
A clean build after the alias fix should succeed immediately.
Bonus — If you see this with Supabase
If your logs say:
Module not found: Can't resolve '@/integrations/supabase/client'
It just means the client.ts file is missing.
Here’s the correct structure:
src/
integrations/
supabase/
client.ts
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
Quick Summary
| Problem | Root Cause | Solution |
|---|---|---|
| Alias error on build |
@ not configured |
Add alias in next.config.mjs
|
| Works locally, fails on Netlify | Case sensitivity | Match file & import names |
| Supabase client error | Missing file | Add client.ts in correct folder |
| Still fails after fix | Cached build | Clear cache & redeploy |
Lessons Learned
Linux is unforgiving about file casing.
Your IDE might “see”
@/paths — but Webpack won’t unless configured.Always define aliases in both
tsconfig.jsonandnext.config.mjs.CI/CD issues are often environmental, not code-related.
Final Thoughts
When I first hit this issue, I wasted hours hunting for missing files that weren’t missing.
One line in next.config.mjs fixed everything.
If you’re facing this same problem, copy these configs and save yourself the headache.
Next time your Netlify build goes red, you’ll know exactly what to do.
Author: Ifedayo “Sam” Agboola
Founding Engineer — Sellexa.app
Building inclusive tech, one deploy at a time.
Top comments (1)
Saving this for future reference
Thanks!!