The PROcrastinator
Inspiration
We wanted to make a productivity app, but with a twist. Since everyone procrastinates, we thought it would be funny to make an app that actually encourages it.
What it does
The PROcrastinator is a productivity app that does everything except make you productive. It distracts users, gives terrible advice, and makes getting work done harder than it needs to be.
How we built it
We built the website using coding tools and GitHub to work together. We focused on making it look like a real productivity app while adding funny and intentionally useless features.
Challenges we ran into
Our biggest challenge was making the app annoying and unhelpful while still keeping it fun to use. We also had some trouble getting all our features to work together.
Accomplishments that we're proud of
We're proud that we turned a stupid idea into an actual working website. We also managed to make something that fits the hackathon theme really well.
What we learned
We learned more about web development, using GitHub, and working together as a team. We also learned that making something intentionally useless is harder than it sounds.
What's next for The PROcrastinator
We want to add more ridiculous features, like:
- An AI assistant that convinces you not to work
- A to-do list that creates more tasks instead of completing them
You need to install the extension under developer mode, and then load as unpacked in microsoft edge
THE PROcrastinator: ARCHITECTURE
A Chrome extension (Manifest V3) written in vanilla JavaScript. No framework, no npm, no build step, no backend.
OVERVIEW
+----------------------------------------------------+
| School page: Canvas / bCourses / Gradescope / |
| Pensive / Google Docs |
| |
| CONTENT SCRIPTS (injected into the page) |
| +----------------------------------------------+ |
| | main.js = core engine ("the brain") | |
| | timer, escalation, heads-up banner, | |
| | overlay, dodging close button, grace clicks| |
| | | |
| | mounts exactly ONE module per popup, | |
| | picked at random: | |
| | +---------------+ +------------------+ | |
| | | reels.js | | snake.js | | |
| | | Shorts feed + | | Brainrot Snake | | |
| | | Clicker game | | (HTML5 canvas) | | |
| | +---------------+ +------------------+ | |
| | after the close: chatbot.js (Procrastibot) | |
| +----------------------------------------------+ |
| overlay.css = styling |
+---------------------+------------------------------+
| chrome.runtime messages
| chrome.storage.local
+---------------------v------------------------------+
| background.js (service worker) |
| opens a popup window (fallback), seeds defaults |
+----------------------------------------------------+
+----------------------------------------------------+
| popup/ (toolbar popup): live stats + on/off switch|
+----------------------------------------------------+
HOW A POPUP HAPPENS (FLOW)
- Page loads -> main.js starts and reads saved stats.
- A timer is set: delay = max(8s, 45s * 0.7^dismissals) Keywords in the tab title or URL (assignment, exam, quiz, due...) halve the first delay.
- If the user was just freed, a grace period applies: the popup waits until the page has had 10 clicks.
- A heads-up banner shows: "Productivity detected. Procrastination incoming."
- The full-screen overlay opens with one random module (video feed + clicker OR snake). If that module crashes, the other one is tried.
- The close button runs away from the cursor twice, then closes.
- Stats are saved, Procrastibot appears in the corner, and the cycle restarts, faster each time.
MODULE CONTRACT (how the pieces plug together)
Every distraction registers itself on one shared global:
window.PROC.modules. = { name, placement: "fullscreen" | "corner", mount(root, api) { ...; return unmountFn; } }
api gives modules: dismiss(), assetUrl(path), openPopupWindow(url). Adding a new distraction = one new file plus one line in the manifest.
DATA (chrome.storage.local, the only database; nothing leaves the browser)
enabled, triggers, dismissals, minutesPrevented, conversations, lastTrigger
- main.js writes triggers / dismissals / minutesPrevented
- chatbot.js writes conversations
- popup writes enabled
- popup and content scripts update live via storage.onChanged
FILES
manifest.json MV3 config, permissions, site list background.js service worker content/main.js core engine content/overlay.css overlay and chatbot styling content/modules/ reels.js YouTube Shorts feed + brainrot clicker chatbot.js Procrastibot (scripted, keyword-based) snake.js Brainrot Snake popup/ toolbar popup (html, css, js) assets/ icons, clicker images test.html + dev/ local test page with a fake chrome.* API
DESIGN CHOICES
- Vanilla JS: loads unpacked in seconds, easy to demo and to debug.
- Modules are isolated: one crashing module can't take the page down.
- YouTube Shorts load in an iframe, one video at a time (an IntersectionObserver loads only the visible one).
- Fully local: no server, no accounts, no data collection.
- Demo mode: press Shift+P three times for an instant popup.
Log in or sign up for Devpost to join the conversation.