nextjs-django-client
Version:
A comprehensive, type-safe SDK for seamlessly integrating Next.js 15+ applications with Django REST Framework backends
522 lines (401 loc) โข 13.4 kB
Markdown
# Next.js Django Client SDK
๐ **The easiest way to connect your Next.js app to Django REST Framework**
A comprehensive, type-safe SDK that makes integrating Next.js applications with Django backends simple and powerful. Perfect for beginners and experts alike!
## โจ Why Choose This SDK?
- ๐ฏ **Beginner-Friendly**: Get started in minutes with our step-by-step guide
- ๐ **Secure by Default**: Built-in JWT authentication and CSRF protection
- ๐ **Full TypeScript**: Complete type safety for your API calls
- ๐ค **Auto-Generated Code**: Generate API clients from your OpenAPI specs
- โก **Modern React**: Built for Next.js 15+ with React 18+ hooks
- ๐งช **Well Tested**: Comprehensive test suite with 95%+ coverage
## ๐ Quick Start (5 minutes)
### Step 1: Install the Package
```bash
npm install nextjs-django-client
# or
yarn add nextjs-django-client
# or
pnpm add nextjs-django-client
```
#### Bundle Options
Choose the right bundle for your needs:
```typescript
// Full bundle (258 KB) - All features included
import { createDjangoApiClient, useAuth, useRBAC } from 'nextjs-django-client';
// Core bundle (136 KB) - Basic features only (recommended for most users)
import { createDjangoApiClient, useAuth } from 'nextjs-django-client/core';
// Advanced bundle (171 KB) - RBAC, social login, advanced auth
import { useRBAC, useSocialLogin, AdvancedAuthProvider } from 'nextjs-django-client/advanced';
```
### Step 2: Create Your API Client
Create a new file `lib/api.ts` in your Next.js project:
```typescript
import { createDjangoApiClient } from 'nextjs-django-client';
// Replace with your Django API URL
export const apiClient = createDjangoApiClient('http://localhost:8000/api');
```
### Step 3: Add Authentication (Optional)
Wrap your app with the AuthProvider in `app/layout.tsx` or `pages/_app.tsx`:
```tsx
import { AuthProvider } from 'nextjs-django-client';
import { apiClient } from '@/lib/api';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<AuthProvider apiClient={apiClient}>
{children}
</AuthProvider>
</body>
</html>
);
}
### Step 4: Start Making API Calls
Now you can use the API client anywhere in your app:
```tsx
'use client'; // For Next.js 13+ App Router
import { useState, useEffect } from 'react';
import { apiClient } from '@/lib/api';
interface User {
id: number;
email: string;
name: string;
}
export default function UsersPage() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchUsers() {
try {
const response = await apiClient.get<User[]>('/users/');
setUsers(response);
} catch (error) {
console.error('Failed to fetch users:', error);
} finally {
setLoading(false);
}
}
fetchUsers();
}, []);
if (loading) return <div>Loading...</div>;
return (
<div>
<h1>Users</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} ({user.email})</li>
))}
</ul>
</div>
);
}
```
## ๐ Authentication Made Easy
### Simple Login Form
```tsx
'use client';
import { useAuth } from 'nextjs-django-client';
export default function LoginForm() {
const { login, isLoading, error } = useAuth();
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
await login({
email: formData.get('email') as string,
password: formData.get('password') as string,
});
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="email">Email:</label>
<input
id="email"
name="email"
type="email"
required
className="border rounded px-3 py-2"
/>
</div>
<div>
<label htmlFor="password">Password:</label>
<input
id="password"
name="password"
type="password"
required
className="border rounded px-3 py-2"
/>
</div>
{error && <p className="text-red-500">{error.message}</p>}
<button
type="submit"
disabled={isLoading}
className="bg-blue-500 text-white px-4 py-2 rounded disabled:opacity-50"
>
{isLoading ? 'Logging in...' : 'Login'}
</button>
</form>
);
}
```
### Protected Routes
```tsx
'use client';
import { useAuth } from 'nextjs-django-client';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
export default function ProtectedPage() {
const { user, isLoading, error } = useAuth(); // error property available for error handling
const router = useRouter();
useEffect(() => {
if (!isLoading && !user) {
router.push('/login');
}
}, [user, isLoading, router]);
if (isLoading) return <div>Loading...</div>;
if (!user) return null;
return (
<div>
<h1>Welcome, {user.name}!</h1>
<p>This is a protected page.</p>
</div>
);
}
```
## ๐ค Auto-Generate Your API Client (Recommended!)
The easiest way to get started is by generating your API client from your Django OpenAPI schema. This gives you:
- โ
**100% Type Safety**: All your API endpoints are fully typed
- โ
**Auto-completion**: Your IDE knows all available methods and parameters
- โ
**Always Up-to-date**: Regenerate when your API changes
- โ
**Zero Boilerplate**: No manual API client code to write
### Step 1: Export Your Django OpenAPI Schema
First, make sure your Django project exports an OpenAPI schema. Add this to your Django `urls.py`:
```python
# urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.schemas import get_schema_view
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('your_app.urls')),
# Add this line to export your schema
path('api/schema/', get_schema_view(
title="Your API",
description="API for your awesome project",
version="1.0.0"
), name='openapi-schema'),
]
```
### Step 2: Generate Your API Client
```bash
# Download your schema (replace with your URL)
curl http://localhost:8000/api/schema/ > openapi.json
# Generate your API client
npx nextjs-django-codegen generate -i openapi.json -o src/generated
```
### Step 3: Use Your Generated Client
```tsx
// src/generated/index.ts is automatically created
import { GeneratedApiClient, useGetUsers, useCreateUser } from '@/generated';
// Create your client instance
const client = new GeneratedApiClient('http://localhost:8000/api');
// Use in React components with generated hooks
export default function UsersPage() {
const { data: users, isLoading, error } = useGetUsers();
const createUser = useCreateUser();
const handleCreateUser = async () => {
await createUser.mutateAsync({
name: 'John Doe',
email: 'john@example.com'
});
};
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Users</h1>
<button onClick={handleCreateUser}>Add User</button>
<ul>
{users?.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
}
```
### Configuration File (Optional)
Create `openapi.config.js` for custom settings:
```javascript
module.exports = {
input: './openapi.json',
output: './src/generated',
generateTypes: true,
generateClient: true,
generateHooks: true,
clientName: 'GeneratedApiClient', // Default changed to avoid naming conflicts
prettier: true,
};
```
## ๐ Manual Configuration (Advanced)
If you prefer manual setup or need custom configuration:
### Authentication Configuration
```typescript
import { configureAuth } from 'nextjs-django-client';
const authConfig = configureAuth({
loginEndpoint: '/api/auth/login/',
refreshEndpoint: '/api/auth/refresh/',
userEndpoint: '/api/auth/user/',
useEmailAsUsername: true,
secureTokens: true,
});
```
### API Client Configuration
```typescript
import { createApiClient } from 'nextjs-django-client';
const apiClient = createApiClient({
baseURL: 'https://api.example.com',
timeout: 30000,
defaultHeaders: {
'Content-Type': 'application/json',
},
retries: 3,
retryDelay: 1000,
});
```
## TypeScript Support
The SDK is built with TypeScript-first approach:
```typescript
interface CustomUser extends User {
customField: string;
}
// Type-safe authentication
const { user } = useAuth<CustomUser>();
// Type-safe API calls
const response = await apiClient.get<CustomUser[]>('/users/');
```
## ๐ Production Ready
### Bundle Optimization
Choose the right bundle for your needs to minimize bundle size:
- **Core Bundle** (136 KB): Basic HTTP client, authentication, and OpenAPI generation
- **Advanced Bundle** (171 KB): RBAC, social login, and advanced authentication features
- **Full Bundle** (259 KB): All features included
### Browser Compatibility
- โ
**No Node.js dependencies** in browser bundles
- โ
**Tree-shakeable** exports for optimal bundle size
- โ
**ES2022+ target** for modern browsers
- โ
**Separate CLI bundle** with Node.js dependencies
## Testing
```bash
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
```
## Development
```bash
# Install dependencies
npm install
# Start development build
npm run dev
# Run linting
npm run lint
# Format code
npm run format
# Type checking
npm run type-check
```
## Project Structure
```
src/
โโโ auth/ # Authentication system
โ โโโ providers/ # React context providers
โ โโโ hooks/ # Authentication hooks
โ โโโ types/ # TypeScript types
โ โโโ utils/ # Auth utilities
โโโ client/ # HTTP client
โ โโโ http/ # Core HTTP client
โ โโโ interceptors/ # Request/response interceptors
โ โโโ types/ # HTTP client types
โโโ state/ # State management (coming soon)
โโโ hooks/ # React hooks
โโโ utils/ # Utility functions
โโโ types/ # Global TypeScript types
```
## Roadmap
### Sprint 2 (Weeks 3-4)
- JWT auto-refresh mechanism
- Enhanced `useAuth` hook with auto-refresh
- Secure cookie handling improvements
### Sprint 3 (Weeks 5-6)
- Customizable authentication endpoints
- Role-based access control (RBAC)
- Social login providers
### Sprint 4 (Weeks 7-8)
- Advanced state management with optimistic updates
- Tag-based cache invalidation
- Batch mutations
## Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes with tests
4. Ensure all tests pass and coverage is maintained
5. Submit a pull request
## ๐จ Troubleshooting
### Common Issues and Solutions
#### 1. CORS Errors
```python
# In your Django settings.py
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000", # Your Next.js dev server
"https://yourdomain.com", # Your production domain
]
CORS_ALLOW_CREDENTIALS = True
```
#### 2. Authentication Token Issues
```typescript
// Check if token is being sent
apiClient.addInterceptor({
request: (config) => {
console.log('Headers:', config.headers);
return config;
}
});
```
#### 3. TypeScript Errors with Generated Code
```bash
# Regenerate your API client
npx nextjs-django-codegen generate -i openapi.json -o src/generated
# Make sure your OpenAPI schema is valid
npx nextjs-django-codegen validate -i openapi.json
```
#### 4. Network Errors in Development
```typescript
// Use the correct Django dev server URL
const apiClient = createDjangoApiClient('http://127.0.0.1:8000/api');
// Not localhost if you're having issues
```
### Getting Help
- ๐ **Documentation**: Check our [full documentation](docs/)
- ๐ **Bug Reports**: [Open an issue](https://github.com/taqiudeen275/nextjs-django-client/issues)
- ๐ฌ **Questions**: [Start a discussion](https://github.com/taqiudeen275/nextjs-django-client/discussions)
- ๐ง **Email**: support@nextjs-django-client.com
## ๐ค Contributing
We love contributions! Here's how you can help:
1. **Fork the repository**
2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
3. **Make your changes** and add tests
4. **Run tests**: `npm test`
5. **Submit a pull request**
See our [Contributing Guide](CONTRIBUTING.md) for detailed instructions.
## ๐ License
MIT License - see [LICENSE](LICENSE) file for details.
---
**Made with โค๏ธ for the Django + Next.js community**