CS50W project

Mail

A single-page email client built with Django and JavaScript, where inboxes, messages, replies, and archives update dynamically without full-page reloads.

  • Python
  • Django
  • JavaScript
  • HTML
  • CSS
  • Fetch API

no reload - just render

THE IDEA

One page. One app. No reloads.

Mail is a single-page email client built as part of CS50's Web Programming with Python and JavaScript (CS50W). It recreates the core loop of an email service like Gmail - send, receive, read, archive, reply - but every switch, open, and action happens inside one page.

The backend API was provided by the project, so the build was never about inventing mail infrastructure. The real work was the front end: JavaScript that fetches from that API, then updates the interface on the other side of each response.

THE CHALLENGE

Reloads were the enemy.

A conventional multi-page flow could reload the browser every time someone opened a mailbox, read an email, archived something, or replied. Mail instead had to respond dynamically - no reload, just an updated page.

TRADITIONAL FLOW
  1. CLICK
  2. REQUEST
  3. PAGE RELOAD
  4. NEW PAGE
MAIL SPA FLOW
  1. CLICK
  2. FETCH API REQUEST
  3. UPDATE STATE
  4. UPDATE DOM
  5. NO FULL RELOAD

MAILBOX EXPERIENCE

One client. Multiple mailboxes.

Users move between their mailboxes inside the same single-page interface - no new page, no full reload.

INBOX

Received emails, listed and ready to open.

SENT

Everything the user has sent, in one place.

ARCHIVE

Filed-away emails, retrievable at any time.

WHAT I BUILT

The email client, feature by feature.

Eight focused features - nothing claimed that wasn't built.

01

Authentication

  • Register a new user account
  • Log in and log out
  • Your own mailbox, always on file
02

Inbox

  • Received emails, listed in the inbox
  • Open any message from the same screen
  • Read state updates as you view
03

Sent

  • All sent messages, in one list
  • The full outbox, revisit anytime
04

Archive

  • Archive received emails away
  • Unarchive them straight back to the inbox
05

Compose

  • Write and send new messages
  • Recipients, subject, and body
06

Read

  • Open individual emails
  • Mark emails as read when opened
07

Reply

  • Reply to emails with the key fields pre-filled
  • Send the reply straight from the view

THE EMAIL LIFECYCLE

Three journeys, one page.

Compose, read, and file away - each flows through the same single-page interface.

SEND
  1. COMPOSE
  2. SEND
  3. SENT
READ
  1. INBOX
  2. OPEN EMAIL
  3. MARK AS READ
  4. REPLY
FILE AWAY
  1. INBOX
  2. ARCHIVE
  3. ARCHIVE MAILBOX

FETCH, THEN RENDER

Ask the API, paint the screen.

The JavaScript client talks to the provided backend API through the browser's Fetch API. Every user action becomes a request, and the returned data is what the interface renders - no full-page reloads for the core email actions.

USER ACTIONFETCH REQUESTBACKEND APIRESPONSEJAVASCRIPTDOM UPDATE
← fetch, render, repeat

DYNAMIC DOM

The page is the state.

Switching mailboxesOpening messagesDisplaying email contentUpdating read stateArchiving and unarchivingRendering sent mailComposing email viewsRendering reply forms

JavaScript decides what the user sees at any moment by changing the DOM in place - mailboxes, messages, compose views, and reply forms all live in the same page.

AUTHENTICATION

Account flow.

A classic, documented loop: new users register, existing users log in, and everyone can log out. The email interface sits behind this authenticated experience.

REGISTERLOGINLOGOUT

ARCHIVE SYSTEM

Archive without deleting.

Received emails can be archived and later unarchived - filed away, never lost, and always one click from the inbox again.

INBOXARCHIVEARCHIVE MAILBOXUNARCHIVEINBOX
archive now, unarchive anytime

REPLY EXPERIENCE

Reply, pre-filled.

Replying to an email carries the original message along - the reply form is pre-filled from the email being answered, so a reply is almost a one-click send.

OPEN EMAILREPLYPRE-FILLED FIELDSSEND
reply, edit lightly, send

UNDER THE HOOD

Two layers, one app.

Django structures the app and serves the API; JavaScript is the client-side layer that requests data and updates the interface.

Backend
PythonDjango
Client
JavaScriptHTMLCSS
Data moves
Fetch API
DJANGO
  • BACKEND API
  • VIEWS
  • TEMPLATES
  • APPLICATION STRUCTURE
JAVASCRIPT
  • FETCH REQUESTS
  • DOM MANIPULATION
  • UI STATE
  • EMAIL INTERACTIONS
STYLE
  • CSS

PROJECT STRUCTURE

A tidy Django layout.

The documented project layout - with the SPA's heart up front.

mail/Main application - views, templates, static files, and API logic.
project3/Django project configuration.
templates/mail/HTML templates for the email client.
static/mail/styles.cssStyling for the email client.
manage.pyDjango management utility.

JAVASCRIPT AS THE CORE

JavaScript did the heavy lifting.

Every email action - loading a mailbox, reading a message, archiving, replying, composing - is handled in JavaScript. The browser asks the API, and the page updates itself in response.

  • Asynchronous fetch requests
  • User interaction handling
  • DOM manipulation
  • Changing mailbox views
  • Rendering email content
  • Managing the client-side flow

WHAT THIS PROJECT TAUGHT ME

The front end is the app.

A single page, a backend API, and JavaScript that holds the whole experience together.

Building single-page applicationsEvery email experience - inbox, read, compose, reply, archive - happens on one page with no navigation between files.
Async API calls with JavaScriptThe Fetch API drives it all: each user action becomes a request, and the interface waits for nothing.
Rendering through DOM manipulationThe visible interface is built and rebuilt by JavaScript - mailboxes list emails, and views render messages.
Managing multiple UI viewsInbox, sent, archive, compose, and a single email view coexist as states within one page.
Client-side business logicReading, archiving, unarchiving, and replying are decided and executed in the browser.
Front-end JavaScript meets a Django backendDjango serves the API and the data; JavaScript is the layer that asks for it and paints the result.

TECHNICAL PIPELINE

From click to screen.

This is the project's key story: a user action, a JavaScript event, a fetch, backend data, and a DOM update - the complete round trip that keeps the page feeling alive.

  1. USER ACTION
  2. JAVASCRIPT EVENT
  3. FETCH REQUEST
  4. BACKEND API
  5. RESPONSE DATA
  6. DOM MANIPULATION
  7. UPDATED UI

0 full-page reloads. 1 page. 7 steps.

← click → request → response → render

BUILT WITH CS50W

A course project, focused on the front end.

Mail was created as part of CS50's Web Programming with Python and JavaScript (CS50W). The spotlight fell on JavaScript - APIs, asynchronous requests, DOM manipulation, and single-page behaviour - with Django serving the backend.

CS50W project

PROJECT DETAILS

The essentials.

ProjectMail
CategoryCS50W project
Built withPython, Django, JavaScript, HTML, CSS, Fetch API
Repositorygithub.com/ujjwaluzu/cs50w-mail
ScreencastYouTube

Want to see the code?

The whole single-page client lives on GitHub - and the screencast walks through it.