- django as a backend
- nextjs as a frontend
- this project uses uv
cd backend
uv run manage.py runserver
cd frontend
npm i
npm run dev
localhost:8000
for the backendlocalhost:3000
for the frontend
- username:
admin
- password:
admin
The application follows a standard client-server architecture with a complete separation of concerns:
- Backend: Django REST Framework API serving data via JSON endpoints
- Frontend: Next.js React application consuming the API
The application uses JWT (JSON Web Token) authentication:
- Token Generation: When a user logs in or registers, the backend generates an access token and refresh token
- Token Storage: Tokens are stored as cookies in the client browser
- Request Authentication: The frontend automatically includes the JWT in the Authorization header for all API requests
- Token Refresh: When the access token expires, the refresh token can be used to obtain a new one
- Token Validation: The backend validates the token on protected routes
The frontend handles authentication state through React Context API (AuthContext
), which provides:
- User state management
- Login/register/logout functionality
- Token handling
- Protected routes
- The frontend makes axios requests to the backend API
- Authentication is handled via JWT interceptors that automatically attach the token
- CRUD operations are performed through REST endpoints
- Data is rendered in React components with proper loading and error states
To extend the application with additional models beyond the current TestModel
:
- Define a new model in
backend/apis/models.py
:
class NewModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
- Create a serializer in
backend/apis/serializers.py
:
class NewModelSerializer(serializers.ModelSerializer):
class Meta:
model = NewModel
fields = '__all__'
- Add a view in
backend/apis/views.py
:
class NewModelViewSet(viewsets.ModelViewSet):
queryset = NewModel.objects.all()
serializer_class = NewModelSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
- Register the view in
backend/apis/urls.py
:
router.register(r'newmodel', NewModelViewSet)
- Run migrations:
uv run manage.py makemigrations
uv run manage.py migrate
- Create a new interface in your component file:
export interface NewModel {
id: number;
name: string;
description: string;
created_at: string;
}
-
Create components for displaying and managing the model:
- List component
- Item component
- Form component for adding/editing
-
Use the API utility to perform CRUD operations:
// Fetch data
const fetchData = async () => {
const response = await api.get("/newmodel/");
setData(response.data);
};
// Add item
const addItem = async (name: string, description: string) => {
await api.post("/newmodel/", { name, description });
fetchData();
};
// Delete item
const deleteItem = async (id: number) => {
await api.delete(`/newmodel/${id}/`);
fetchData();
};
- Update your UI components to include the new model functionality
The existing pattern in the codebase provides a solid template for extending the application with additional models while maintaining a clean separation between frontend and backend concerns.