DEV Community

Cover image for Day 86 of #100DaysOfCode — DevCollab: Planning a Full-Stack Developer Collaboration Platform
M Saad Ahmad
M Saad Ahmad

Posted on

Day 86 of #100DaysOfCode — DevCollab: Planning a Full-Stack Developer Collaboration Platform

The final stretch. 15 days, one project, deployed and live by day 100. Today is planning day, no code, just thinking through the entire system before a single line gets written. Getting this right up front means cleaner decisions during building and fewer painful pivots mid-project.


What is DevCollab?

DevCollab is a platform for developers with project ideas or ongoing projects who are looking for collaborators. The idea is that, instead of posting in random Discord servers or Reddit threads hoping someone sees it, developers post their projects on DevCollab with the roles they need, the tech stack involved, and what they're building. Other developers browse, find something interesting, and send a collaboration request. The project owner reviews requests and accepts or rejects them.

Everyone has a profile showing their skills, bio, GitHub link, and the projects they're involved in, either as owner or collaborator.

The problem it solves: Finding people to build with is one of the most common frustrations for independent developers. This gives the problem a dedicated space.


MVP Scope

What's in:

  • User registration and login with JWT authentication
  • User profiles with skills, bio, GitHub link, and avatar
  • Post a project with title, description, tech stack, and roles needed
  • Browse all projects with search and filter by tech stack or role
  • Send a collaboration request to join a project with a message
  • Project owner can accept or reject incoming requests
  • Dashboard showing your projects and incoming requests
  • Status tracking — collaborators see if their request is pending, accepted, or rejected

What's explicitly out:

  • Real-time messaging or notifications — too complex for the timeline
  • Comments on projects — scope creep
  • Following other users — not core to the collaboration use case
  • Email verification — adds infrastructure complexity not needed for a portfolio build
  • Payment or premium features — completely out of scope

Tech Stack and Why

Backend: Django + Django REST Framework
Django because the data has real relationships: users, projects, requests, and Django's ORM handles that cleanly. DRF because I need a proper REST API with serializers, viewsets, and permission classes. I know both deeply from the past few weeks.

Authentication: JWT with djangorestframework-simplejwt
JWT because the frontend is a separate Next.js app. Session-based auth doesn't work cleanly across different domains. JWT tokens in the Authorization header work everywhere.

Database: PostgreSQL
SQLite for development, PostgreSQL for production on Railway. dj-database-url handles switching between the two with a single environment variable change.

Frontend: Next.js
Next.js, because I know it from the first 60 days of this challenge, it handles routing cleanly, and it works naturally with API-driven backends. No server-side rendering needed here, all pages fetch data client-side from the Django API.

Styling: Tailwind CSS
Consistent with what I've been using. No new tools mid-project.

Deployment: Railway (backend) + Vercel (frontend)
Both are the simplest deployment options for their respective frameworks. Railway for Django and PostgreSQL together, Vercel for Next.js with one-click GitHub deploys.


Data Models

User

The custom user model extends AbstractUser. Fields: username, email, password, is_active, date_joined. Authentication fields only, profile data lives separately.

Profile

One-to-one with User. Fields: bio, avatar (ImageField), skills (comma-separated text), github_url, linkedin_url, website_url, location. Auto-created via signal when a User is created.

Project

Belongs to a User (owner). Fields: title, description, tech_stack (comma-separated), roles_needed (comma-separated), status (active/completed/on_hold), is_open (boolean; accepting requests or not), created_at, updated_at. A project has one owner and many collaboration requests.

CollaborationRequest

Links a User (requester) to a Project. Fields: project (ForeignKey), requester (ForeignKey to User), message (the cover note), status (pending/accepted/rejected), created_at. Unique together on the project and requester, one request per user per project.

Relationships Summary

User ──── Profile          (one-to-one)
User ──── Project          (one-to-many, owner)
User ──── CollaborationRequest  (one-to-many, requester)
Project ── CollaborationRequest (one-to-many)
Enter fullscreen mode Exit fullscreen mode

API Endpoints

Authentication

POST   /api/auth/register/        — create account, return tokens
POST   /api/auth/login/           — return access + refresh tokens
POST   /api/auth/token/refresh/   — get new access token
POST   /api/auth/logout/          — blacklist refresh token
Enter fullscreen mode Exit fullscreen mode

Users and Profiles

GET    /api/users/<username>/     — get public profile (open)
GET    /api/users/me/             — get current user's profile (auth)
PUT    /api/users/me/             — update current user's profile (auth)
PATCH  /api/users/me/             — partial update profile (auth)
Enter fullscreen mode Exit fullscreen mode

Projects

GET    /api/projects/             — list all open projects (open, filterable)
POST   /api/projects/             — create a project (auth)
GET    /api/projects/<id>/        — get project detail (open)
PUT    /api/projects/<id>/        — update project (owner only)
PATCH  /api/projects/<id>/        — partial update (owner only)
DELETE /api/projects/<id>/        — delete project (owner only)
GET    /api/projects/mine/        — get current user's projects (auth)
Enter fullscreen mode Exit fullscreen mode

Collaboration Requests

POST   /api/projects/<id>/requests/          — send request (auth, not owner)
GET    /api/projects/<id>/requests/          — list requests for project (owner only)
PATCH  /api/projects/<id>/requests/<req_id>/ — accept or reject (owner only)
GET    /api/requests/mine/                   — get current user's sent requests (auth)
Enter fullscreen mode Exit fullscreen mode

Frontend Pages

Public Pages (no auth required)

/                    — landing page, what DevCollab is, CTA to register
/projects            — browse all projects with search and filter
/projects/[id]       — project detail with collaboration request button
/profile/[username]  — public user profile
Enter fullscreen mode Exit fullscreen mode

Auth Pages

/login               — login form
/register            — registration form
Enter fullscreen mode Exit fullscreen mode

Protected Pages (auth required)

/dashboard           — summary of your projects and incoming requests
/projects/new        — create a new project
/projects/[id]/edit  — edit your project
/profile/edit        — edit your own profile
/requests            — your sent requests and their statuses
Enter fullscreen mode Exit fullscreen mode

Authentication Flow

Registration: POST to /api/auth/register/ with username, email, password. Backend creates User, auto-creates Profile via signal, returns access token and refresh token.

Login: POST to /api/auth/login/ with email and password. Backend returns access token and refresh token.

Token Storage: Access token and refresh token stored in localStorage. Access token has a short expiry (15 minutes). Refresh token has a longer expiry (7 days).

Authenticated Requests: Every API request that requires auth includes the access token in the Authorization: Bearer <token> header. An Axios instance with an interceptor handles this automatically; the interceptor reads the token from localStorage and attaches it to every request.

Token Refresh: When an API request returns 401, an Axios response interceptor automatically posts to /api/auth/token/refresh/ with the refresh token, gets a new access token, stores it, and retries the original request. Transparent to the user.

Protected Routes: A ProtectedRoute wrapper component in Next.js checks for the token in localStorage on mount. If no token, redirect to /login with the intended URL in the query string.

Logout: Clear tokens from localStorage, redirect to /login.


Folder Structure

Django Backend

devcollab-backend/
    devcollab/
        settings.py
        urls.py
        wsgi.py
    accounts/
        models.py       — User, Profile
        serializers.py
        views.py
        urls.py
        signals.py      — auto-create Profile
    projects/
        models.py       — Project, CollaborationRequest
        serializers.py
        views.py
        urls.py
        permissions.py  — IsOwner custom permission
    .env
    requirements.txt
Enter fullscreen mode Exit fullscreen mode

Next.js Frontend

devcollab-frontend/
    src/
        app/
            page.js              — landing page
            login/page.js
            register/page.js
            dashboard/page.js
            projects/
                page.js          — browse projects
                new/page.js      — create project
                [id]/page.js     — project detail
                [id]/edit/page.js
            profile/
                [username]/page.js
                edit/page.js
            requests/page.js
        components/
            ui/                  — buttons, inputs, badges, cards
            layout/              — Navbar, Footer, PageWrapper
            projects/            — ProjectCard, ProjectForm, TechStackTag
            requests/            — RequestCard, RequestForm
            profile/             — ProfileCard, SkillTag
        hooks/
            useAuth.js           — auth state and token management
            useProjects.js       — project data fetching hooks
        services/
            api.js               — Axios instance with interceptors
            auth.js              — register, login, logout functions
            projects.js          — project API calls
            requests.js          — collaboration request API calls
        context/
            AuthContext.js       — global auth state
Enter fullscreen mode Exit fullscreen mode

Here's the conclusion paragraph:


What's Next

The plan is as detailed as it needs to be. Models are defined, endpoints are mapped, pages are listed, the auth flow is clear, and the folder structure is decided. Every major decision that can be made without writing code has been made. What's left is execution, and that starts tomorrow. Fifteen days, one project, one live URL by day 100. Let's build.

Thanks for reading. Feel free to share your thoughts!

Top comments (0)