DEV Community

Cover image for I Built a Notebook for Sharing Notes That Doesn't Ask You to Sign Up First

I Built a Notebook for Sharing Notes That Doesn't Ask You to Sign Up First

Varshith V Hegde on August 12, 2026

Someone asked me to share meeting notes in Slack yesterday. I pasted the markdown. Slack ate the table. The code block lost its indentation. The t...
Collapse
 
nazar-boyko profile image
Nazar Boyko

The edit token sitting in the URL path caught my eye. It ends up in browser history, server access logs, and anything that syncs history across devices, which feels risky for a write credential. Was putting it in a fragment ever on the table, or did server side routing make that too awkward?

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Fragment was considered. It stays off the request line, but our edit route is server-rendered (/e/[token] validates on the server), and fragments never reach the server, so you need a client-side bootstrap page and a redirect dance. I prioritized a single copy-pasteable URL over that complexity.

Fair tradeoff question though. If I tighten this, fragment or “exchange token for session cookie on first load” is probably the direction.

Collapse
 
wrobeltomasz profile image
Tomasz

@varshithvhegde Have you run any performance tests on the project?
The biggest risk is the free quotas for Supabase and Postgres, which act as a single point of failure through which all write traffic passes.

Collapse
 
varshithvhegde profile image
Varshith V Hegde

For this project this should work and currently I have some basic rate limiting on place but surely if it gets kuch traction and then yeah it may fail to write

Collapse
 
tom_jones_230c4659491adcd profile image
Tom Jones

The token in the URL is a real tradeoff and you argue it well. You also state the principle that governs it: an edit token is a write credential, so it must not reach a third party.

There is one place it may be reaching one anyway. PostHog attaches $current_url and $pathname to the pageview event automatically, and turning autocapture off leaves that alone, because those properties ride the pageview rather than the autocapture handler. On /e/{token} the URL is the credential. So "no edit tokens in any event payload" can be entirely true of every property you set, and still false because of two the library sets for you.

Cheap to settle. Open an edit link, then find that pageview in the PostHog activity view and read $current_url. If the token is sitting in it, a before_send hook that rewrites $current_url and $pathname on the /e/ route fixes it while you keep the analytics.

The same shape sits one layer further down, and it is the layer people check second. The token is in the path, so it appears in the request line of everything that logs requests: your host's edge, the CDN, any proxy in between. Log retention quietly becomes credential retention, and nobody ever makes that decision on purpose. Reading the token from a fragment or a header instead of the path closes both at once, at the cost of a redirect dance on first load.

None of this makes the design wrong, and your sanitisation section shows you thought harder about it than most side projects do. The narrow point is that moving a credential from a header into a URL hands a copy to every system that records URLs, and those systems were configured by people who had no idea they were storing credentials.

Separate from any of that, the use case I would push on is the blackboard one. Someone with a half formed idea and no account puts it on a page, hands out a single link, and collects help on it. That is a different job from sharing finished notes, and I think it is the stronger framing for what you have actually built. Multi page behind one URL, open editing, comments, and a ten day default expiry are exactly the properties a working scratch space wants, and mostly the opposite of what a document product wants.

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Good catch on PostHog — $current_url on the automatic pageview is exactly the kind of leak I thought I had ruled out. Will verify in activity and add a before_send scrub on /e/ if needed.

The path-in-URL → logs point is fair too. Copy-pasteable edit links were the reason I accepted that tradeoff, but “every system that logs URLs gets a copy” is real and I underplayed it in the post.

And yes on the blackboard use case — that is the one I actually built for. Open editing + comments + expiry is a scratch space, not a doc product. Stronger framing than “share meeting notes.”

Thanks for the careful read.

Collapse
 
tom_jones_230c4659491adcd profile image
Tom Jones

One thing worth doing when you check the activity view: read the stored event, and treat the network request as a separate question. A before_send hook that fires correctly still leaves open what was captured before you shipped it, and the answer to that lives in the events already sitting in the project.

We got caught by the mirror image of this last week. A generated status line of ours printed a figure I then quoted externally. The line had been generated 236 hours earlier. Every word of it was accurate when written, and I was reading a claim about the past tense as though it described the system now. Re-running the emitter took nine seconds and changed one of the numbers.

On the scratch space framing, that is the version I would put at the top of the post. Expiry is what makes open editing defensible, and it reads as a limitation until you say what it is for.

Good luck with it, and thanks for taking the PostHog note in the spirit it was meant.

Collapse
 
nitishkumarpro profile image
Nitish Kumar

The strongest part of this build is the decision to treat the edit token as the ownership boundary instead of introducing a full user system.

That is a good example of designing authentication around the actual threat model and product requirements rather than automatically reaching for accounts, sessions, and password recovery.

I also like the production details: sanitising Markdown because open editing creates an XSS surface, keeping expiry separate from physical deletion to provide a recovery window, and fixing the R2 upload issue by explicitly setting Content-Length.

These are the kinds of details that rarely appear in the product demo but determine whether a small tool remains reliable once real users start abusing the edge cases.

Simple product surface, but thoughtful engineering underneath.

Collapse
 
nitishkumarpro profile image
Nitish Kumar

The part of SharePad I find most interesting isn't the markdown editor. It's the decision to remove accounts entirely.

For a small sharing tool, authentication can easily become more infrastructure than the actual problem requires. Here, the edit token effectively becomes the ownership credential: generate it once, store only its SHA-256 hash, and require it for mutations. That removes signup flows, sessions, password recovery, and a users table without removing the security boundary.

There are also several good production details here that are easy to overlook: sanitising raw HTML because open editing creates an XSS path, explicitly setting Content-Length for larger R2 uploads, keeping expiry and deletion separate for recovery, and rate-limiting uploads at the database level to avoid concurrent requests bypassing the counter.

This is a good example of a broader engineering principle: don't add infrastructure to solve a problem your product doesn't actually have.

Sometimes the more robust architecture is the one with fewer moving parts, provided the security and failure boundaries are explicit.

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thanks

Collapse
 
mattewens profile image
mattewens

The signup-first wall is such a friction killer. I ran a small experiment on my own waitlist recently - dropped the email field to the second interaction instead of the first, and click-to-completion went from about 2% to nearly 5%.

Curious what your read is on abuse - did you hit any spam or crawler noise without the auth gate, or has it been mostly quiet so far?

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thanks for sharing about signup wall .Atleast I hate the signup a most whenever I try to use a service.

Yeah I mean the problem is people using random bot to spam the server 😞. Even if there are rate limits people always find way to abuse the thing. Even my last project even with cloudflare generous free tier on workers my last project was hitting free teir dailyy limit and I am sure it was not a boom it's just someone trying to abuse the server. But again I build not for money but I don't wanna loose too .. I am happy until atleast 1 of the people who visit genuinely love it or use it .

Collapse
 
mattewens profile image
mattewens

Yeah, the abuse thing is the bit nobody warns you about. On my voice-agent
stack (Twilio + Vapi) I hit the same wall: Twilio dev accounts get scraped for outbound spam attempts within 48 hours of your number going live. Learned the hard way after burning $12 in a couple of hours to a botnet pinging my inbound webhook.

The fix that stuck for me was pushing the rate-limit right down to the edge - Cloudflare Workers with a KV-backed sliding window per IP, before the request even hits the origin. Cheap, fast, and it kills 95% of the
noise before the Twilio quota gets touched.

Genuinely curious what your abuse pattern looked like - was it more signup-form-style flood, or people trying to exfiltrate stored notes?

Thread Thread
 
varshithvhegde profile image
Varshith V Hegde

They are just trying to loop in notes or continuously calling a read api those kind of things ...

Thread Thread
 
mattewens profile image
mattewens

Ha, the read-loop pattern is the sneakiest one because it looks statistically like a real reader with a slightly excited scroll wheel.
I ended up doing per-note-id request budgets to catch it - anything more than ~40 reads on the same doc from the same IP inside 10 minutes gets a soft 429 with a friendly message. Kills the scraper, doesn't punish the person who genuinely opened the tab and forgot about it.

Also curious: are you seeing any obvious User-Agent tell, or are they hiding behind normal browser UAs?

Thread Thread
 
varshithvhegde profile image
Varshith V Hegde • Edited

That's a great method .

No nothing in particular that i saw

Thanks for this 🙌🙌

Collapse
 
codearea_shop_1f1def9b532 profile image
Codearea

SharePad is a really interesting approach to sharing notes without the usual signup and account-management overhead.
The token-based ownership model is especially worth paying attention to: instead of creating an account, you receive a secret edit token that acts as your ownership credential. Combined with Markdown support, multi-page notebooks, password protection, expiry dates, and PDF export, it makes a practical alternative to traditional note-sharing tools.

If you're interested in web development, programming projects, and useful developer tools, check out CodeCan.net for more resources.

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thank you

Collapse
 
anik_sikder_313 profile image
Anik Sikder

A lot of products begin with "I want to use Next.js, Supabase, or AI." This began with a simple problem: sharing structured notes shouldn't require accounts, workspaces, invitations, and permissions before anyone can read them.

The token-based ownership model is particularly elegant. It removes an entire category of complexity authentication flows, password resets, session management, and user onboarding while still preserving ownership and control.

That's a good reminder that great architecture isn't always about adding systems. Sometimes it's about finding a way to remove them.

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thanks

Collapse
 
publiflow profile image
PubliFlow

Dealing with markdown rendering in chat platforms is notoriously frustrating because they often strip out or mangle standard formatting. When I was building a similar internal tool, I found that using a standardized AST parser like remark before sending the payload to the client saved a lot of headache with inconsistent rendering. For a frictionless sharing experience, are you handling the markdown parsing entirely on the client side with something like react-markdown, or are you sanitizing and compiling it on the backend? It is a great approach to skip the initial auth wall since it drastically reduces the time-to-value for the end user.

Collapse
 
tatta profile image
tatta

That’s a really great idea.
I’ve actually been feeling the same kind of inconvenience when sharing little bits of Markdown with friends, and I was just thinking about making something quite similar to what you’ve built.

My only concern is whether the service might suddenly disappear someday, along with all the documents I’ve written.
That’s one reason I tend to go with self-hosting after considering various options...

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Truee I agree the main reason was the same I had previously built similiar website but it was v1 and it had too many security risk and at that time I was just learning things but again now we have AI and if we use it properly we can create great products

Collapse
 
hoseinmdev profile image
Hosein Mahmoudi

The edit token approach instead of a full user system is brilliant for a quick sharing tool. Simple, lightweight, and gets out of the way. Great job on this!

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thank You

Collapse
 
aposalik profile image
Abdullah_Salik

Cool man I like it

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Thank You

Collapse
 
daymondhyper profile image
DaymondHyper

Thanks for writing this, useful and practical. The point about keeping it simple is the one that resonates most with me. Have you found a setup that works well for you so far?

Collapse
 
varshithvhegde profile image
Varshith V Hegde

Please support this Project on product hunt

producthunt.com/products/sharepad-...