# 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**
