What Causes This Error?
This error occurs when you try to import a server-only module (like database clients, file system modules, or server utilities) in client-side code. Some modules can only run on the server.
The Problem
---
import { db } from '../lib/database';
---
<script>
// ❌ Can't use server module in client script
import { db } from '../lib/database';
const data = await db.query('SELECT * FROM users');
</script>
The Fix
Keep Server Code in Frontmatter
---
// ✅ Server code in frontmatter
import { db } from '../lib/database';
const users = await db.query('SELECT * FROM users');
---
<ul>
{users.map(user => <li>{user.name}</li>)}
</ul>
Use API Routes for Client Access
// src/pages/api/users.ts
import { db } from '../../lib/database';
export async function GET() {
const users = await db.query('SELECT * FROM users');
return Response.json(users);
}
---
// Page without server imports
---
<ul id="users"></ul>
<script>
// ✅ Fetch from API instead
const response = await fetch('/api/users');
const users = await response.json();
const list = document.getElementById('users');
users.forEach(user => {
const li = document.createElement('li');
li.textContent = user.name;
list.appendChild(li);
});
</script>
Common Scenarios
Database Clients
---
// ✅ Database queries in frontmatter only
import { prisma } from '../lib/prisma';
const posts = await prisma.post.findMany();
---
<!-- Don't import prisma in <script> tags -->
File System Access
---
// ✅ File operations in frontmatter
import fs from 'node:fs';
const content = fs.readFileSync('./data.json', 'utf-8');
---
<!-- fs is not available in browser -->
Environment Variables
---
// ✅ Server-side env vars in frontmatter
const apiKey = import.meta.env.API_SECRET_KEY;
const data = await fetchWithKey(apiKey);
---
<script>
// ❌ Can't access server env vars
// const key = import.meta.env.API_SECRET_KEY;
// ✅ Use public env vars prefixed with PUBLIC_
const publicKey = import.meta.env.PUBLIC_API_KEY;
</script>
Marking Server-Only Modules
// src/lib/database.ts
import 'server-only'; // Explicitly mark as server-only
import { Pool } from 'pg';
export const db = new Pool({
connectionString: process.env.DATABASE_URL,
});
Shared Types (OK to Import)
// src/types/user.ts
// ✅ Types can be imported anywhere
export interface User {
id: string;
name: string;
}
<script>
// ✅ Type imports are fine (erased at runtime)
import type { User } from '../types/user';
const users: User[] = await fetch('/api/users').then(r => r.json());
</script>
Pass Data to Client via Props
---
import { db } from '../lib/database';
const initialData = await db.getData();
---
<div id="app" data-initial={JSON.stringify(initialData)}></div>
<script>
// ✅ Read server data from DOM
const el = document.getElementById('app');
const initialData = JSON.parse(el.dataset.initial);
</script>
Framework Components
// src/components/DataDisplay.jsx
// ❌ Can't import server modules in framework components
// ✅ Pass data as props
export default function DataDisplay({ data }) {
return <ul>{data.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}
---
import { db } from '../lib/database';
import DataDisplay from '../components/DataDisplay.jsx';
const data = await db.query('...');
---
<DataDisplay client:load data={data} />
Quick Checklist
- Database/file system code goes in frontmatter only
- Use API routes for client-server communication
- Pass data to client via props or data attributes
- Type imports are always OK
- Use
PUBLIC_prefix for client env vars