all projects web platform / project 03

Revology — The Ideal Revision Website

During my GCSEs I kept running into the same problem: plenty of great resources existed, but never in one place. Revology is my answer — a Django platform where students can build a shared library of notes and flashcards instead of starting from scratch every exam season.

18
months in development
4
languages used
78
students surveyed
1 in 2
couldn't find resources easily, pre-Revology

Why it exists

One of the main problems as a student was figuring out which platforms to use, what to use them for, and how to keep all my revision together. So Revology became a library of resources, where a student could revise, track progress and access everything else from one hub — flashcards and notes, growing with every user who contributes to it.

Market research

Before writing a line of code, I surveyed 78 students from Years 7–12. 83% didn't feel completely sure how to revise. 65% made their own notes, and a further 18% relied on pre-made ones. 58% said finding pre-made notes for their subjects "requires a bit of digging." That gap — a common platform where resources can be accessed from one place — is exactly what Revology tries to close.

I was careful about the limits of that data too: the sample came from one independent, academically competitive school, so if anything the national picture is probably worse than what I found.

Planning the database

Before any Python was written, every table was mapped out with its primary and foreign keys — Users, Notes, Flashcard Sets, Flashcards, and an Activity table to track usage. Notes and flashcards both have a many-to-one relationship with a user (the author) and with a subject; flashcards also belong to a flashcard set. That structure translated almost directly into the Django models below.

supernova/models.py
from django.db import models
from django.contrib.auth.models import User

class Notes(models.Model):
    notes_content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='authored_notes')
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
    title = models.CharField(max_length=30)
    date_uploaded = models.DateTimeField('date uploaded', auto_now_add=True)
    image = models.ImageField(null=True, blank=True)

    def __str__(self):
        return f'{self.id}: {self.title} ({self.subject})'


class Flashcard(models.Model):
    front_of_card = models.TextField(max_length=2000)
    back_of_card = models.TextField(max_length=2000)
    flashcard_set = models.ForeignKey(Flashcard_set, on_delete=models.CASCADE, related_name='flashcards')

    def get_rag(self, user):
        # returns red/amber/green confidence rating for this user
        try:
            return Flashcard_rating.objects.filter(flashcard=self, user=user)[0].status.colour
        except IndexError:
            return Status.red

Two of the eight models in supernova/models.py — Notes and Flashcard, with the RAG (red/amber/green) confidence rating logic that drives the flashcard filtering feature.

Choices I made on purpose

Two decisions shaped the whole build, and I want to be upfront about why I made them rather than just listing the stack.

decisionoption Aoption B (chosen)why
Web frameworkFlaskDjangoBuilt-in user authentication and admin interface meant more time for Revology's actual features, not boilerplate.
CSS frameworkBootstrapBulmaNo JS dependencies to fight with on a Python-first project, and cleaner documentation.

The two JavaScript features

Almost everything is server-rendered Python and Django templates, but two features needed real client-side JS.

Flipping flashcards. Each card needed to flip on click, replicating a physical flashcard's front/back. The script listens for a click, toggles which side is showing, and updates the background colour as a visual cue:

view_flashcards.html — flipCard()
function flipCard() {
    if (cards.length === 0) return;
    flipped = !flipped;
    const card = cards[current];
    document.getElementById('card-text').textContent = flipped ? card.back : card.front;
    document.getElementById('flip-hint').textContent = flipped ? 'Click to flip back' : 'Click to flip';
    document.getElementById('flashcard').style.background = flipped ? '#f0fdf4' : 'white';
    document.getElementById('rag-section').style.display = flipped ? 'block' : 'none';
}

From supernova/templates/supernova/view_flashcards.html.

Previewing PDFs. Revology's own verified notes carry more weight than user uploads, so I wanted a way to show their first page before the click — using Mozilla's PDF.js library to render page one onto a canvas, since PDFs can't display natively inside a <div>:

homepage.html — PDF.js preview
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
document.querySelectorAll('.pdf-thumb').forEach(canvas => {
    const url = canvas.dataset.url;
    pdfjsLib.getDocument(url).promise.then(pdf => pdf.getPage(1)).then(page => {
        const viewport = page.getViewport({ scale: 1.5 });
        canvas.width = viewport.width;
        canvas.height = viewport.height / 2;
        page.render({ canvasContext: canvas.getContext('2d'), viewport });
    });
});

This exact technique now renders the live preview below — for the actual project write-up.

loading preview…
// full write-up

Revology — The Ideal Revision Website (full document)

Planning, market research, database design, the iterative build, ethics & GDPR considerations, beta feedback and a full bibliography — exactly as submitted for my Gold CREST Award.

Open full PDF ↗

Ethics & GDPR

Because the site collects user data, I had to take data protection seriously from the start. Sign-up only asks for a first/last name, email, username and password — all credential handling is delegated to Django's built-in authentication system, which encrypts passwords and follows established security practice. User-created resources fall under UK GDPR, which requires data to be collected lawfully, stored securely, and used only for its stated purpose.

What beta users said

"It's really useful to divide Revology notes and community notes because I know I can trust what I'm reading."

Another suggested adding past paper questions organised by topic — a strong idea for Version 2, alongside activity streaks and leaderboards, in the spirit of how platforms like Duolingo gamify consistency.

What I'd actually say happened

I learned how to navigate Django properly — from authentication to database administration — across four languages, the most I'd used in a single project, deployed on PythonAnywhere via a Linux Bash console. But the real takeaway wasn't technical. It was the rhythm of the development process itself: write, debug, test, repeat, for months.

anikagupte/revology HTML 60.9% · Python 39.1% · 14 commits
Browse repository ↗
back to →
All projects
View all