DEV Community

Aditya Sorathiya
Aditya Sorathiya

Posted on Edited on

How I Built PasteDB in 3 Months — From a Blank Repo to a Real Product

Comments add crucial web security tips

How I Built PasteDB in 3 Months — From a Blank Repo to a Real Product

A developer recently asked me:

«“How do you manage all of this so effectively?”»

It made me think about how PasteDB actually started.

Not with a big team.

Not with expensive infrastructure.

Just a blank GitHub repository, an idea, and a lot of questions.

May 2, 2026 — The beginning

I wanted to build a project that could give me real-world experience and, hopefully, real users.

At first I thought about building something much bigger, like a social media platform.

Then I started thinking about something simpler: code and information sharing.

I noticed that many paste-sharing platforms had trade-offs.

If something was simple, it wasn't always secure.

If it focused heavily on security, the experience wasn't always great.

And if it tried to include everything, the interface could become complicated.

So I decided to build my own.

I created the PasteDB repository on May 2.

The first commit was basically just the initial README.

And I remember thinking:

Will I actually be able to build this?

Will anyone use it?

What happens if nobody does?

Building the MVP

The first version was extremely simple.

The project started with:

  • HTML/CSS/JavaScript
  • FastAPI
  • MongoDB Atlas

I created the initial frontend and backend and slowly started turning the idea into an actual product.

Within a couple of days, the tiny "create.html" file had grown from almost nothing to 100+ of lines.
And now 4000+ lines

Then came authentication.

I decided to keep registration simple with Google authentication.

Getting that working wasn't exactly painless, but eventually I had a functional dashboard and a working authentication flow.

At that point, I thought:

Maybe I actually have an MVP.

Then I stopped.

On May 18, I stopped working on PasteDB.

I started working on other projects and even stopped maintaining the backend server.

For a while, I genuinely thought:

PasteDB failed.

I didn't think there was much more I could do with it.

June 10 — Starting again

Then I wanted to participate in a hackathon.

I came back to PasteDB.

And that changed everything.

I started improving the project again.

I worked on SEO.

I submitted pages for indexing.

I started trying different communities.

I didn't have money for a custom domain, so I kept using:

https://pastedb.netlify.app

I wasn't trying to make it look like a huge startup.

I just wanted the product to work.

I tried Reddit.

Some posts were removed by moderators.

So I tried DEV.

And DEV was different.

People started following me.

People started asking about PasteDB.

People actually started noticing the project.

Then I stopped focusing only on code.

This was probably one of the biggest lessons.

Building features is important.

But nobody can use a product they don't know exists.

So I started spending more time on:

  • SEO
  • developer communities
  • documentation
  • demos
  • feedback
  • talking to developers
  • finding ways for PasteDB to integrate with other tools

I also added Google Analytics so I could actually understand whether people were using the product.

Then something happened that made all the work feel real.

July 22 — 6:30 PM

I opened Analytics.

98 active users.

98 new users.

Only two users away from 100.

And there were returning users too.

People were actually finding something I had built.

Users were coming from different parts of the world, with a large portion coming from the US.

That was a completely different feeling from looking at an empty project.

But there was another challenge: resources.

I didn't have a powerful development machine.

The PasteDB web interface and SDK were largely developed on a Samsung Galaxy M21(Whose screen is bleeding).

The VS Code extension was developed on an old Dell Inspiron N5010 with an i3 processor and a hard drive.

So yes, a significant part of PasteDB was built from a phone.

Today PasteDB has grown beyond the original MVP.

It now includes:

  • Web interface
  • Python and Node.js SDK
  • VS Code extension
  • API key management
  • Public and private pastes
  • Custom URLs
  • Image support
  • Analytics and view tracking
  • Google Authentication
  • Syntax highlighting
  • Version Control
  • QR sharing
  • Transfer tools
  • End-to-end encryption features
  • And more

There are still things I want to improve.

But at some point, you have to stop saying:

“It's not finished yet.”

and start saying:

“This is good enough to put in front of people.”

And that's what I learned.

PasteDB wasn't built in one continuous sprint.

It was:

Idea → Build → Stop → Restart → Improve → Ship → Get feedback → Market → Repeat.

I didn't have a perfect plan.

I didn't know if anyone would use it.

I didn't have expensive hardware.

I didn't have a team.

I just kept trying different things.

And one of the most important lessons I've learned is that marketing isn't only posting advertisements.

Sometimes marketing is:

  • using another developer's product,
  • finding a bug,
  • reporting it,
  • giving useful feedback,
  • starting a genuine conversation,
  • and showing what you've built.

That can lead to opportunities you never planned for.

That's actually how some of my recent developer conversations started — including conversations that eventually led to PasteDB integrations.

So when someone asks me:

“How do you manage all of this?”

My answer is probably:

I don't manage everything perfectly.

I just keep moving.

Build something.

Put it in front of people.

Listen.

Improve it.

And repeat.

That's how PasteDB went from a blank repository on May 2 to a real product being used, discussed, and integrated with other developer tools.

And I'm still building.


PasteDB: Share code, notes, snippets and images instantly.

I documented the full development journey, including the milestones, setbacks, technical decisions and lessons learned, on the PasteDB About page.

Top comments (40)

Collapse
 
mansio profile image
Mikhail

Quick question on versioning: does your SDK expose a version ID or last-modified timestamp in API responses?

I work on AI agent tooling, and a common failure mode is an agent reasoning about a version it fetched earlier while the underlying content has already moved on. A paste.version field could let clients detect staleness before using or overwriting content.

Curious if you've considered this.

Collapse
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

You can just get the current version of paste if you know
You can get

{'title': '',
'burn_after_read': False,
'content':' ',
"images":['https.....,...'],
'encrypted_pek': None,
'e2ee': False,
'syntax': 'plaintext',
'created_at': 1784628221.392158, 'expiration': 'never',
'expire_at': None,
'visibility': 'public',
'custom_id': 'cde',
'password': False,
'current_version': 2}

Collapse
 
mansio profile image
Mikhail

Thanks — I dug a bit deeper into the versioning implementation, and I think there’s an interesting gap here specifically for AI/long-running clients.

current_version is already useful for detecting that the paste changed, but the update operation seems to be missing the other half: binding the write to the version the client actually reasoned about.

For example:

GET → version 2
→ agent reasons for 30 seconds
→ someone updates the paste → version 3
→ agent sends an update based on version 2

If the PUT is still last-write-wins, the operation can succeed while silently overwriting newer state.

That makes current_version more than just history metadata — it can become a concurrency boundary.

Something as simple as:

expected_version: 2

with a 409 Conflict when the server is already at version 3 would let the client decide what to do next: retry, merge, or abort.

I find this particularly interesting for AI agents because the dangerous part isn't that the model failed to make an API call. The call can be perfectly valid. The problem is that the model may be acting on a state that is no longer current.

That seems like a useful distinction for versioned systems in general: provenance tells you what state the agent saw; optimistic locking tells you whether that state is still safe to write against.

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

Are you building a ai agent which takes data from PasteDB?
If yes , that's great

Thread Thread
 
mansio profile image
Comment deleted
Thread Thread
 
mansio profile image
Comment deleted
Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

Are you Samsung user?

Thread Thread
 
mansio profile image
Comment deleted
Thread Thread
 
mansio profile image
Mikhail

Yes

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

Samsung users, want to use AirDrop? Here it is

 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

But of you are logged in then you make a paste then you can view version(max10)
No one will stop you
The browser will fetch the version of the given paste_id
And show then on the version viewer

Collapse
 
publiflow profile image
PubliFlow

Building a data-centric product in just three months is a massive undertaking, especially when you have to balance feature development with schema design. I found that locking in the core database relationships early on saved us from massive refactoring later, even if it meant delaying some UI work. It is always tempting to use a flexible JSON column for quick iterations, but that usually comes back to haunt you during query optimization. Did you run into any bottlenecks with your data modeling when you had to pivot or add new paste formats halfway through the build?

Collapse
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

Thanks for the detailed suggestions! I really like the restore approach—creating a new version instead of replacing the current one would make recovery much safer. A diff view is also something I’d like to add, especially for code pastes. The timestamp is already stored with each version, so exposing that in the UI should be straightforward. The optimistic version check is especially interesting now that PasteDB supports collaborative editing, since it could help detect stale content before a save overwrites newer changes.

Do you have any feature request for guest pastes?

Collapse
 
publiflow profile image
PubliFlow

Implementing the restore approach as a new version will definitely save users from accidental overwrites. For the diff view, leveraging a library like Monaco or CodeMirror could save you significant time since they handle syntax highlighting out of the box. The optimistic version check will prevent those frustrating lost update scenarios when multiple tabs are open. Have you considered how you will handle conflict resolution if two users attempt to update the same paste simultaneously?

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

But how can 2 users edit one
If the request falls first to the server then first is resolved and
It's not compulsory to save a version all time
I have a check btn
[ ] Save Previous Version

If it's checked then a new version is created
See here : pastedb.netlify.app/create

Thread Thread
 
publiflow profile image
PubliFlow

Making versioning opt-in via that checkbox is a smart way to prevent history bloat while keeping the UI clean. Regarding two users editing simultaneously, relying purely on sequential server resolution usually results in a last-write-wins scenario where someone loses their changes. Have you considered adding a simple locking mechanism or optimistic UI updates to handle those concurrent edits more gracefully?

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

No

Thread Thread
 
publiflow profile image
PubliFlow

I would be curious to hear your reasoning, as I assumed default-on versioning would quickly bloat storage for high-volume text pastes. Do you feel the safety net of automatic history outweighs the infrastructure costs, or is there a different middle ground you prefer? Balancing data retention with performance is always a tough trade-off when scaling these kinds of tools.

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

That's exactly why I chose not to make versioning default-on. In PasteDB, the user can explicitly choose “Save Previous Version” when saving changes. I also plan to keep the history limited rather than storing unlimited versions. This gives users the safety net when they actually need it without creating unnecessary storage costs for every edit.
That said, I’m experimenting with a slightly different approach to versioning that might make this trade-off even more interesting. I’ll share more about that once I’ve tested it properly. 👀

Thread Thread
 
publiflow profile image
PubliFlow

Making versioning opt-in is a smart trade-off for keeping storage costs predictable, especially since most quick paste edits don't actually need a rollback. I noticed your message got cut off at the end where you mentioned experimenting with a slightly different approach. What alternative versioning strategy are you testing out to balance user safety and infrastructure costs?

Thread Thread
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

I was using Chrome on Android on my phone, with Desktop Site disabled. I didn't change the browser's zoom level manually — I just used the normal two-finger pinch-to-zoom gesture, and the layout broke when I zoomed out. My screen resolution is 1080×2400. I've already attached the screenshot showing what happened.

My guess is that some element may be overflowing the viewport, but I'm not sure.

Thread Thread
 
publiflow profile image
PubliFlow

That viewport overflow on pinch-to-zoom is a classic mobile CSS headache, especially on tall displays like your 1080x2400 screen. It typically happens when a child element inside a flex or grid container has an unhandled min-width or fixed padding that forces the parent to exceed the viewport bounds. Have you tried inspecting the layout with Chrome DevTools remote debugging to see if adding overflow-x: hidden to the main wrapper stops the horizontal shift?

Collapse
 
codemaster_121482 profile image
Seif Ahmed

That's brilliant.

I almost do all this, but I never thought about Google Analytics or tracking if users actually use my platform or just enter and leave. Thanks for idea, my friend.

Collapse
 
amitfeldman profile image
Amit Feldman

Glad it helped! And nice — an AirDrop-style flow for Samsung users is a real gap.

Quick re-scan note since I'm here: HSTS is still holding strong (max-age=31536000, preload). The CSP is still the open one from the original list — on Netlify it's a few lines in netlify.toml or a _headers file, no code changes. Ping me when it lands and I'll verify the full set.

Collapse
 
amitfeldman profile image
Amit Feldman

Congrats on the launch — the 3-month blank-repo-to-product story is a great read, and the Netlify deploy side is already in decent shape: HSTS preloaded, TLS solid, title/meta/canonical/robots/sitemap all clean.

Since PasteDB renders user-pasted content, I ran a quick check on pastedb.netlify.app and found one thing worth fixing before traffic picks up:

No Content-Security-Policy. For a paste site this is the highest-risk gap — anyone can paste a snippet containing a <script> tag (or an HTML paste), and without a CSP the browser will execute it in your origin if it ever gets rendered unsanitized. Even with sanitization, a CSP is the cheap second line of defense.

Also missing: X-Frame-Options (clickjacking — someone can iframe your paste pages), X-Content-Type-Options: nosniff, Referrer-Policy, and Permissions-Policy.

On Netlify all five are one _headers file in your publish dir:

/*
  Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Referrer-Policy: strict-origin-when-cross-origin
  Permissions-Policy: camera=(), microphone=(), geolocation=()
Enter fullscreen mode Exit fullscreen mode

Tighten script-src/style-src to match whatever your frontend actually needs — start with the above and watch the console for violations.

Happy to run a full free scan of the site (security headers, TLS, SEO, perf) and send you the complete report if you want — just say the word. Good luck with the launch!

Collapse
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya

Thanks for taking the time to check PasteDB and for pointing these out. I’ll review the security headers, especially CSP, and make sure the policy matches the external resources the frontend actually uses. I’ll also verify that pasted content is never treated as trusted HTML. Appreciate the security-focused feedback!

Collapse
 
amitfeldman profile image
Amit Feldman

Quick verification update — just re-ran the scan on the live site: HSTS is now live, and it's the preload-grade version (max-age=31536000; includeSubDomains; preload). Clean fix, exactly as recommended.

Score moved from where we started to 11 pass / 4 warn / 1 fail. The one remaining FAIL is Content-Security-Policy — and this is where your DOMPurify work pairs nicely: sanitizer at render + CSP as the browser-enforced second layer. Even a starter policy like default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' would catch anything that slips past sanitization.

The 4 warnings (X-Frame-Options, nosniff, Referrer-Policy, Permissions-Policy) are all one-liners in the same netlify.toml headers block where HSTS went in — five minutes of work total.

Happy to re-run the full verification once CSP lands so you have the before/after on record.

Collapse
 
amitfeldman profile image
Amit Feldman

That's the right layer to solve it at — sanitizing at render with DOMPurify covers the main XSS path for pasted content.

The reason CSP is still worth the one file: DOMPurify has had bypasses before (it's an arms race like any sanitizer), and CSP is the backstop that catches the day a bypass lands — the browser refuses to execute the injected script even if it makes it into the DOM. Sanitizer + CSP = two independent failures needed instead of one. For a site whose whole job is rendering stranger's text, that pairing is the standard defense-in-depth setup.

Once the _headers file deploys, ping me here and I'll re-run the full scan free so you can see the before/after.

Collapse
 
officialmailkr profile image
오피셜메일

빈 저장소에서 시작해 중단했다가 다시 돌아온 흐름이 특히 현실적으로 느껴졌습니다. 기능만 만들던 단계에서 SEO·문서·커뮤니티로 시선을 옮긴 전환점이 PasteDB 성장의 핵심처럼 보입니다. 작은 기기로 SDK와 확장까지 만든 과정도 인상 깊네요.

Collapse
 
amitfeldman profile image
Amit Feldman

That's a healthy pivot — docs, demo and distribution are usually where launches actually succeed or fail, not the feature list. And agreed on the marketing definition: the version that works for dev tools is showing up with something specific and useful, which is all I try to do with these scans.

The offer stands, by the way — once the CSP and the four warning headers land, ping me and I'll run the full verification re-scan so you have the before/after on record. Good luck with the hackathon relaunch.

Collapse
 
amitfeldman profile image
Amit Feldman

Sounds like exactly the right approach. Two pitfalls worth knowing from doing these on paste/text apps:

  1. Sanitization and CSP complement each other — DOMPurify (or whatever you're using) handles the "never treat pasted content as trusted HTML" side, and the CSP is the backstop for the day a sanitizer bypass shows up. Keep script-src to 'self' (no 'unsafe-inline') if you can; that's the line that actually stops injected scripts.
  2. Watch that your CSP matches the resources the frontend really loads before you ship it — a too-strict policy breaks the page silently, so test in a preview deploy first. If Netlify functions or external fonts/CDNs are in play, whitelist just those origins explicitly.

Happy to run a free verification re-scan once you've deployed the headers — takes me a minute and confirms the policy is live and parseable in the wild. Good luck with the launch!

Collapse
 
aditya_sorathiya_069252f4 profile image
Aditya Sorathiya • Edited

I m using Dom purify while viewing pastes

Some comments may only be visible to logged-in visitors. Sign in to view all comments.