Harshit Sharma
All work

Web AppQ3 2022Lead

Heckfree

Users get a public profile that showcases all of their links in one place.

A live Heckfree profile — avatar and the handle meharshit above seven stacked link rows, on a peach-to-purple gradient.

The build

One link that carries every platform you're on. Mine is at /meharshit.

Problem

Every platform wants a link and only gives you one field. The result is a bio that points at whichever profile you thought mattered most that month, and an audience that never finds the rest.

The product is small and the problem is real: a single stable URL that resolves to everything else, owned by the person rather than by a platform.

Constraints

  • Public pages must be fast and boring. A profile is opened from a phone, on a slow connection, from someone else's bio. It renders or it's useless.
  • Editing must be trivial. If reordering a link takes more than a drag and a save, people stop maintaining the page and it rots.
  • No team, on free hosting. Same as everything else here — no budget, and no one on call but me.

Approach

Server-rendered EJS pages served at each user's handle, with the edit surface behind Passport-backed accounts.

js
// The public route — one lookup, no session, no join.
app.get("/:handle", async (req, res) => {
  const profile = await Profile
    .findOne({ handle: req.params.handle })
    .lean();

  if (!profile) return res.status(404).render("404");
  res.render("profile", { profile });
});

Link ordering is stored on the profile document as an array, so the order the owner drags into is the order the page renders — no sort key to keep consistent, no second collection.

Tradeoffs

  • Server rendering over a client app. The public page is the whole product, so it renders on the server and ships almost no JavaScript. The editor is worse for it — every save is a round trip.
  • Ordering as an array on the document. Reordering rewrites the array, which is fine at a dozen links and wrong at a thousand. It was the right call for the size of the thing.
  • Handles as the primary key of the public URL. Clean URLs, at the cost of handle changes breaking every link already shared. There's no redirect table; there should be.

Outcome

It works and it's still up. My own profile runs on it, which is the only endorsement a link-in-bio tool can honestly give — I use the one I built instead of the one everybody else uses.

Decisions

  • Building it at all, against using Linktree. Chosen because the interesting part was the modelling, not the product — public pages, ownership, and ordering are a compact study in all three. Against it: the commercial version is free and better maintained.
  • Passport accounts over magic links. Chosen for consistency with everything else I'd built, so there was one auth pattern in my head rather than two. Against it: another OAuth app to register per deployment.
  • No custom domains. Chosen to keep hosting simple. Against it: the feature that would make it genuinely useful to somebody else is precisely the one missing.

Stack

  • Node.js
  • Express.js
  • MongoDB
  • Passport.js
  • EJS
  • JavaScript
  • The Lecture Lense workspace — a lecture playing above a chaptered time rail, the corrected transcript on the left, and a chat answer on the right with a timestamp citation.

    Lecture Lense

    Turns any recording into searchable, timestamp-cited notes.

  • Chitter's landing page — headline, a Join Chitter Now button, and a phone mockup of the feed.

    Chitter

    A mini social app that lets users sign up, log in and post whatever is on their mind.

  • The Coscholars landing page — "Learn From The Best Tutors Worldwide" above a course search field.

    Coscholars

    An Ed-Tech platform built end to end during my internship at Coscholars.

esc

Pages

Home/
Work/work
Blog/blog
About/about
Uses/uses
Contact/contact
Bucket list/bucket-list
Guestbook/guestbook
Résumé/resume
Privacy/privacy
Terms/terms

Projects

Lecture LenseQ3 2026
ChitterQ1 2023
HeckfreeQ3 2022
CoscholarsQ3 2022
JsswireQ2 2022
JssconnectQ1 2022
QuizTownQ4 2021
IplheatQ2 2021
TechkartQ4 2020

Posts

Passport.js auth patterns I keep reaching for7 min read
How To Create A README For GitHub Profile3 min read
↑↓ navigate↵ openesc close