A full-stack Django web app for DJs to share and discover new mixes.
- Tech Stack
- Project Overview
- User Guide
- Planning
- Design
- Development
- Testing
- Use of AI Tools
- Getting Started
- Future Development
DJ Depo is a full-stack web application built for DJs and mix enthusiasts to discover and upload their own DJ mixes. It facilitates community-orientated sharing of fresh music mixes curated by DJs.
-
Users of the site can register a username and upload their mp3 mix - which is added to the homepage discovery section for visitors to enjoy.
-
The goal was to create a simplified solution for DJs to upload their mixes in a community setting, with future development plans to expand interactions including social sharing and comments.
-
Success criteria for the application were to build a simplified, responsive and easy-to-use interface for users to seamlessly upload and share their music onto the site.
-
Where similar websites have a focus on the user, DJ Depo is focused on building the community of users and a shared ethos to create a platform with an ever-expanding collection of DJ mixes for users to access and enjoy.
To register for an account, click signup and enter a username and password.
If you are not logged in automatically, navigate to the login page and enter the details you used to sign up.
Only staff and superusers have admin access.
Users can edit or delete their own posts only.
Once your account is created, you can login and share uploads to the homepage. Click upload a mix to navigate to the upload page.
Add a title, description and audio file then click upload. If successful, you should be redirected to the homepage and see this message.
DJ Depo is still in production and currently it cannot support large files.
If you are testing the site, please find a demo MP3 track to upload here .
Made a mistake? No problem, you can choose to edit or delete your upload from the homepage.
To speed up development time, I asked Chat GPT to generate a set of user stories based on a description of the project.
- User Registration & Login: As a DJ, I want to create an account and log in so that I can securely upload and manage my mixes.
- Uploading a Mix: As a site user, I want to upload my mix file along with its title, date, and description so that listeners can discover and play my latest work.
- CRUD functionality (front-end): As a site user, I want to edit the title, description or file, or delete an upload entirely.
- Discover Mixes: As a site visitor, I want to browse a list of the most recent mixes so that I can find new music and discover different DJs.
- Play Mixes: As a visitor, I want to listen to a mix directly from the website using an audio player so that I don’t need to download files to hear them.
- Responsive Design: As a user, I want to navigate and play mixes easily on my phone, tablet or large screen devices.
- Mix Tags or Genres: As a DJ, I want to add tags or select a genre for each mix so that listeners can easily filter and discover mixes by style.
Github project board — click image to open
As a development team of one, working agile was essential. I used Github Projects to track user story requirements and for sprints I used a separate Trello board.
This ensured I was able to meet the criteria for site functionality and keep a check on time constraints for the project as a whole.
The sprints ran for one week and focused on key areas of development
- Week 1 sprint: Backend setup and authentication (Django).
- Week 2 sprint: JavaScript model and custom templates (HTML).
- Week 3 sprint: Frontend design (CSS) and testing.
Trello sprint board
For this project, I used Figma to create a wireframe and interactive front-end mockup of the site. In the design of my homepage, I have largely stuck to the original designs as well as making improvements to the overall style and layout.
Wireframe
As there was not enough development time to implement genre tags, I modified the design by simplifying the discovery page with the latest mixes appearing.
Figma mock-up — click image to open
Admin panel
After creating a remote repository, I set up the Django environment ready to use the Model View Template Framework.
I then connected a PostgreSQL database to make the application functional and enable the creation of an admin panel, users and begin to develop CRUD functionality.
Admin view
From the admin panel, staff users can create and edit users and manage posts made via the mixes app.
Custom mix model
The main component of the DJ Depo app is this AudioPost model, with custom elements to enhance UX.
Enables users to:
- Upload audio posts associated with their accounts.
- Store a title, description and an audio file.
- Integrates with Cloudinary for storage in the cloud.
- Bypasses Cloudinary during tests and stores files locally.
- Records timestamp for uploads.
The AudioPost model in /mix/models.py explicitly sets the database table name to hello_world_audiopost.
This is because the hello_world app was the original location of the model, and it was later moved to mixes.
Despite the move, the database table name remains hello_world_audiopost to maintain compatibility with existing data.
This change does not affect the functionality of the application, as Django seamlessly handles the mapping between the model and the database table.
Wavesurfer
I chose this plugin because it was open-source and met the basic requirement for my MVP.
During development, I customised the visualiser so that it matched the style of the site. I also adapted the play/pause and progress bars for improved accessibility and site UX.
I also integrated it into the Bootstrap cards used for uploads, so that it would appear along with user mixes in the feed.
The mixes app includes a comprehensive suite of unit tests to ensure the functionality and reliability of its models, views, and workflows. These tests cover:
- Model Tests: Validation of the AudioPost model, including its creation and string representation.
- View Tests: Verification of view accessibility, login requirements, and CRUD operations for audio posts.
- Integration Tests: End-to-end testing of workflows, such as creating, editing, and deleting audio posts.
- Error Handling Tests: Validation of 404 errors and form submission error handling.
All tests were executed successfully on 10 November 2025, with the following results:
| Test Suite | Result |
|---|---|
| AudioPostModelTest | Ok |
| HomePageViewTest | Ok |
| UploadAudioViewTest | Ok |
| EditPostViewTest | Ok |
| DeleteAudioPostViewTest | Ok |
| IntegrationTests | Ok |
| ErrorHandlingTests | Ok |
Total Tests: 12 Passed: 12 Failed: 0
To run your own tests in development use the command:
python3 manage.py test mixes or
python manage.py test mixes depending on your device.
Unit tests
Lighthouse report score (Google Dev Tools)
| Performance | Accessibility | Best Practices |
|---|---|---|
| 73 | 100 | 100 |
Lighthouse score
Markup Validation Service HTML (W3C)
| HTML | Validator pass/fail |
|---|---|
templates>base.html |
PASS |
templates>registration>login.html |
PASS |
templates>registration>signup.html |
PASS |
templates>registration>signup.html |
PASS |
mixes>templates>mixes>signup.html>edit_audio_post.html |
PASS |
mixes>templates>mixes>signup.html>home.html |
PASS |
mixes>templates>mixes>signup.html>post_confirm_delete.html |
PASS |
mixes>templates>mixes>signup.html>upload_audio.html |
PASS |
CSS Validation Service (W3C)
| CSS | Validator pass/fail |
|---|---|
static>style.css |
PASS |
jshint.com
mixes/static/mixes/js/wavesurfer-init.js
| Metric | Value | Notes |
|---|---|---|
| Total functions | 14 | — |
| Max function parameters | 2 | Median: 0.5 |
| Max statements per function | 18 | Median: 10.5 |
| Max cyclomatic complexity | 8 | Median: 4 |
CI Python Linter (Pep8)
| File | Validator pass/fail | Screenshot |
|---|---|---|
mixes>admin.py |
PASS | |
mixes>apps.py |
PASS | |
mixes>forms.py |
PASS | |
mixes>models.py |
PASS | |
mixes>tests.py |
PASS | |
mixes>urls.py |
PASS | |
mixes>views.py |
PASS | |
config>settings.py |
PASS |
| Device | Mockup | Notes |
|---|---|---|
| Small device (iPhone SE) | Menu collapses to hamburger; audio player fits screen width; homepage layout remains usable. | |
| Medium device (iPad Pro 11) | Audio player scales correctly, mixes display in grid view | |
| Large device (Macbook Pro 13) | Full desktop layout with 3 mixes per row |
Throughout this project, I leveraged Microsoft Co-Pilot’s AI agent integration in VS Code to enhance productivity, support decision-making, and improve code quality. Key areas where AI contributed include:
- Error troubleshooting: Diagnosing HTTP errors (e.g., 400, 500) and suggesting actionable solutions.
- Feature customisation: Assisting with Django model adjustments and JavaScript waveform integration.
- Code review: Providing feedback on accessibility, maintainability, and overall code quality.
AI played a pivotal role in debugging, helping me overcome blockers efficiently while also providing learning opportunities. For example, when customising the Wavesurfer.js plugin—a critical component of the front-end UX—the default progress bar obstructed the waveform. Using Co-Pilot, I was able to understand the underlying issue and implement a workaround (applying a drop-shadow instead of a solid shape).
Although the solution was not perfect, AI enabled me to extend the project’s functionality beyond my immediate JavaScript expertise, accelerating development while reinforcing my problem-solving skills.
Co-Pilot was also instrumental in ensuring visual and functional consistency. For instance, I used AI to apply Bootstrap styling across modals so that interactions like editing or deleting posts matched the design of login and signup templates. This allowed me to make rapid, coherent updates that maintained a polished front-end UX.
Finally, AI assisted in creating Django unit tests, which proved invaluable for debugging and verifying application functionality. Co-Pilot helped automate repetitive testing tasks, allowing me to focus on higher-level logic and ensuring the app worked reliably.
AI assistance was essential in maximising time for development by producing documentation including structuring and improving readme., generating concise inline code descriptions, responding to project ideas and assisting with planning and providing user stories ready to implement into the project board.
Overall, AI augmentation strongly benefitted my workflow as a junior developer working on a first full-stack project.
Automating testing and debugging when errors were thrown has helped to elevate the potential of this project in line with my concept and vision.
You can clone the repository via the DJ Depo github and using terminal in your IDE.
git clone <repo> pip install -r requirements.txt python manage.py migrate python manage.py runserver
Before deploying to a hosting environment such as Heroku, remember to set DEBUG to False.
Never commit passwords or sensitive information to the repository!
Use environment variables and .gitignore for managing secret keys and configurations.
This project uses Cloudinary for media storage in production. Before deploying, make sure one of the following is set in the environment:
CLOUDINARY_URL(recommended) — e.g.cloudinary://<api_key>:<api_secret>@<cloud_name>- or the three separate vars:
CLOUDINARY_CLOUD_NAME,CLOUDINARY_API_KEY,CLOUDINARY_API_SECRET
If you need to run management commands (for example collectstatic) in CI without production secrets, you can opt-in to skipping the Cloudinary credentials check by setting:
SKIP_CLOUDINARY_CHECK=1
This skip is conservative: it must be explicitly enabled and is intended for CI or build jobs where media uploads are not performed. Skipping will emit a warning in the process output so the decision is visible in logs. Do not rely on skipping for normal production deployments — ensure credentials are present for the running application.
Looking ahead, I plan to introduce more social-based functionality including comments, ratings, and shared playlists along with the genre tags and search function that I ran out of time to implement in this project.
Furthermore, I would improve the branding from its basic, minimal theme to something more energetic and unique. Moving away from the Bootstrap heavy layout and implementing a different, more kinetic framework such as React.
- For use of an excellent open-source plugin
- To Mark, Lewis, Jade and the team for their ongoing support.
- To Aleksandr Neplokhov, Gigxels, Odin Reyna and Kei Scampa for their images.























