Full StackFastAPINext.jsPostgreSQL

VeloWiKi: How I Built a Custom CRM and Directory for VeloCET

Published: June 21, 20267 min readSource Code ↗

Why I Built This

As my club VeloCET, grew in members and projects, a simple Google sheet was no longer an option to track members,project status,active members, club alumni and industry connections. A need for a custom database catering to my club's needs was imminent. Although i explored other open source alternatives, they were too feature-rich or too complex for my needs. I decided to come up with my own solution

I decided to build a custom tool called VeloWiKi. My main goal was to create a secure, reliable dashboard where coordinators can quickly view everyone's details, assign members to projects, and keep data clean.

How the System Works

The application is split into three main parts: a FastAPI backend, a Next.js web application and a PostgreSQL database.

Next.js Web Portal

My primary interface. It handles lists of club members, project boards, and admin tools behind a secure login.

FastAPI Backend

The core API that handles database queries, input validation, and checks if user emails are authorized.

PostgreSQL DB

Stores all user login lists, member records, and project assignments securely.

[Next.js Frontend ] <--- JSON REST API ---> [FastAPI Backend] <--- SQLAlchemy ORM ---> [PostgreSQL Database]

Database Layout

I designed the database to track active members, mentors, and graduates cleanly. Here is a look at the main tables. It may not be normalised and scalable for a big setup.but yea, for the club this seemed almost good (Atleast for a few years).

TablePrimary ColumnsPurpose
personsid, name, email, phone, type (MEMBER, ALUMNI, MENTOR)Stores details of everyone connected to the club
membershipsid, person_id, doj (Date of Joining), dol (Date of Leaving)Tracks when members join or leave the club over time
projectsid, name, description, status (IN_PROGRESS, COMPLETED, ABORTED)Tracks team projects and their status
project_membersperson_id, project_idMaps people to specific projects they work on
usersid, email, role (admin, viewer)Lists people allowed to sign into the dashboard

By splitting profiles (persons) from their start/end dates (memberships), I can keep contact details clean. If a student graduates, I change their type to ALUMNIand set their end date, without losing their history or project connections.

FastAPI Backend API

I built the backend API using Python and FastAPI. It is simple, fast, and gives auto-generated documentation endpoints out of the box.

When a user signs in on the website, Next.js checks their credentials by sending a request to this backend endpoint to verify if their email exists in the user database table:

# Verify user email endpoint
@app.get("/users/verify")
def verify_user(email: str, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.email == email).first()
    if not user:
        raise HTTPException(status_code=404, detail="User email not authorized")
    return {"email": user.email, "role": user.role}

Next.js Web Portal & Google Login

The web app is the center of my project. The reason i choose Next.js is for its fast response and SSR which drastically improvd speed and providing a good user experience.

I used NextAuth.js to set up Google login. When someone signs in with their Google account, Next.js calls the FastAPI backend behind the scenes to verify if their email is listed in the users database table. If they are in the database, they get a token containing their role (either admin or viewer). If not, they are immediately signed out and shown an access denied message.

Experimental Discord Bot Trial

Earlier in the project, I tried building a Discord bot in Python using discord.py. The idea was to let coordinators type slash commands in the server (like /addpersonor /getproject) to update records directly.

However, with just a few options built i found it s usage too riugh for a platform at this scale. with more user data discord would become too messy provided its limitation to add only 5 inputs whenever a user form has to be created. Personally making a portfolio in nNextjs earlier made me decide to use the same for this project too. This version seemed more easier to use and manage than a discord server and a bot.

Security & Privacy

Although i really wanted to give a deployment URL here, Since the app stores real club data, Im afraid (or rather not risk) exposing user data to the public. The frontend has been locked for the puclic and is now available only to the club members.

Challenges & Issues Faced

Since this was my first time working through a complete full-stack deployment like this, I ran into quite a few roadblocks along the way:

  • The "Works on My Machine" Trap:During development stage I had hardcoded most of the env links to the specific file. I never knew that a .env file would be so important. I learned the hardway of missing some urls and taking valuable timing finding this error.(Thsi wont be repeated again :D)
  • Supabase & Connection Errors: Migrating the database from a local PostgreSQL setup to Supabase in the cloud came with a learning curve. I hit connection errors because of IPv6 transaction pooler endpoints and typos in database connection strings on Render.
  • CORS Policies & Environment Variables: When I deployed the frontend to Vercel and the backend to Render, they couldn't talk to each other. I had to learn how CORS headers work to allow requests between the domains, and ensure Vercel was pointing to the production Render URL instead oflocalhost:8000. Me and Gemini spend almost half an hour until i realised the local address alone added to the CORS.
  • OAuth & NextAuth Misconfigurations: Configuring Google OAuth for the first time meant dealing with redirect URI mismatch errors. Getting the authentication flow to correctly query the database and fetch the whitelisted emails took some troubleshooting.

What I Learned

Building VeloWiKi was a great exercise in full-stack development. By setting up a robust, well-structured PostgreSQL database and a fast backend api, I was able to build a secure, responsive dashboard that handles the club's records cleanly. Keeping the focus on the Next.js web application allowed me to polish features and keep the interface simple and easy for everyone to use.