Careeroza
Server-only Code
Keep Secrets on the Server
Modules that use secrets or the database must never be imported by a Client Component by mistake. Add import 'server-only' at the top: if a client file imports it, the build fails instead of leaking code.
Example
npm install server-onlyExample output
added 1 package in 1s
lib/payments.ts
import 'server-only';
const RAZORPAY_SECRET = process.env.RAZORPAY_KEY_SECRET!;
export async function createPaymentOrder(amountPaise: number) {
const auth = Buffer.from(process.env.RAZORPAY_KEY_ID + ':' + RAZORPAY_SECRET).toString('base64');
const res = await fetch('https://api.razorpay.com/v1/orders', {
method: 'POST',
headers: { Authorization: 'Basic ' + auth, 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: amountPaise, currency: 'INR' }),
});
return res.json();
}The Build Error You Want
Example
If components/PayButton.tsx (a client file) imports lib/payments.ts:
npm run buildExample output
Error: x 'server-only' cannot be imported from a Client Component module. | It should only be used from a Server Component. Import trace for requested module: ./lib/payments.ts ./components/PayButton.tsx
Note: Environment variables without NEXT_PUBLIC_ are already undefined in the browser, but the code (URLs, logic) would still leak. server-only protects the whole module. There is also client-only for browser-only modules.