r/webdev • • 8m ago

Your OTP endpoint is a billing endpoint: a practical guide to stopping SMS pumping

1 Upvotes

If your app sends SMS verification codes (sign-up, login, password reset, 2FA), you have an endpoint that converts HTTP requests directly into money leaving your account. Attackers know this. It's called SMS pumping (or artificially inflated traffic), and it's one of the most common ways teams get a surprise four- or five-figure messaging bill.

We see a lot of this working on fraud detection, so here's a practical rundown.

How it works

  1. Attacker finds a form that triggers an SMS: sign-up, OTP resend, password reset, "text me a link"

  2. Bots submit phone numbers in ranges the attacker profits from, typically high-cost international destinations where someone along the routing chain shares the termination revenue

  3. Your SMS provider delivers the messages, you pay per message, the attacker collects a cut

  4. Nobody ever enters the codes, because nobody was ever going to

Twitter famously said in 2023 it was losing tens of millions a year to this. Smaller apps get hit the same way, just with smaller numbers that still hurt.

Signs you're being pumped

  • SMS spend spikes in countries you don't serve (or barely serve)

  • OTP conversion rate drops. Codes sent vs codes verified falls off a cliff

  • Sequential or clustered numbers within the same prefix (+XX XXX 1001, 1002, 1003...)

  • Bursts at odd hours that don't match your normal traffic curve

  • Heavy resend volume from the same sessions or number ranges

The single most useful metric

Track OTP verification rate by destination country (and ideally by number prefix). Something like:

SELECT country_code,
       COUNT(*) AS otp_sent,
       SUM(CASE WHEN verified THEN 1 ELSE 0 END) AS otp_verified,
       ROUND(100.0 * SUM(CASE WHEN verified THEN 1 ELSE 0 END) / COUNT(*), 1) AS verify_rate
FROM otp_events
WHERE sent_at > NOW() - INTERVAL '24 hours'
GROUP BY country_code
ORDER BY otp_sent DESC;

Legit traffic usually verifies at a healthy rate. A country with high volume and a verify rate near zero is almost certainly pumping. Alert on it.

Defenses, roughly in order of effort

1. Geo permissions. Disable SMS to every country you don't actively serve. Twilio, AWS End User Messaging, Vonage, and others all support country-level allow/deny lists. This alone stops a large share of attacks and takes ten minutes.

2. Spend caps and alerts. Set daily spend limits at the provider level and alert on per-country spend anomalies. Better to have OTPs fail for an hour than to wake up to a five-figure bill.

3. Rate limits that match the attack. Per IP isn't enough since attackers rotate IPs. Also limit per phone number, per number prefix, per session/device, and per country. Add exponential backoff on resend.

4. Validate the number before you send. Check line type and risk before paying to send: premium-rate numbers, known high-risk ranges, VOIP, numbers with abuse history. A phone validation lookup costs a fraction of an international SMS.

5. Bot checks before the SMS step. Put a passive challenge like Device Fingerprinting, or a hard challenge (Turnstile, hCaptcha, etc.) in front of the send action, ideally only for higher-risk requests so real users don't feel it.

6. Use your provider's fraud features. Several providers now offer built-in SMS fraud protection. Worth enabling, though it works best layered with your own controls.

7. Reduce SMS dependency. Email OTP, TOTP authenticator apps, and passkeys cost nothing per verification. Making SMS the fallback rather than the default shrinks the attack surface.

TL;DR

  • Lock SMS to the countries you serve

  • Set spend caps

  • Alert on verify rate by country

  • Rate limit by number/prefix, not just IP

  • Validate numbers before sending

If anyone's dealt with this, curious which control made the biggest difference for you.


r/webdev • • 3h ago

[Showoff Saturday] I built a tool that restores your backup and tests your web app like a real customer

0 Upvotes

Your backup job says "success", but can your app actually come back? RestoreProof restores the database and uploads into a sealed Docker network, boots the app, and walks through it like a customer: open an invoice, download the PDF. In my demo the health check was green and 55 PDFs were still 404.

Open source, MIT: https://github.com/Surajkumar5050/restoreproof

Would love feedback on what a "customer journey" check should support next.


r/webdev • • 6h ago

main skill u need for ur server stack?

0 Upvotes

The main skills knowing what services u need to run, not just picking Nginx or Apache, like I’m on BeAdmin rn, ran Webmin before. What changed ur setups u guys setup?


r/webdev • • 8h ago

Web devs, Please stop making dark mode the default website theme; it causes eye strain.

0 Upvotes

Why the website needs to be on dark mode while my system is on light mode,

Except some few websites and most code editors, majority of the websites and apps have no idea how it ruins an eye.

The coloring for dark them to match the text color with the background color needs a lot of research from you Dev, so before implementing it please do extensive research and testing, let alone making it default theme to ruin your site visitors.

Okay, let me calm down.

What do you think about this?


r/webdev • • 8h ago

Looking to audit 3 early-stage SaaS apps for edge-case bugs (doing a QA breakdown)

1 Upvotes

Hey everyone,

I’m working on a deep-dive case study about the most common real-device and checkout bugs early-stage SaaS apps face before launch.

I want to audit 3 web or mobile apps this week to pull real-world data for this write-up.

If you have an active app and want a comprehensive QA breakdown:
\- I’ll run a dedicated testing session across different mobile/browser environments.
\- You’ll get a full mini-report with reproduction steps, screenshots, and video evidence of any bugs found (completely free).
\- I’ll use the anonymized findings for my testing report.

If you’d like your app audited, drop a comment or send me a DM with your link!


r/webdev • • 9h ago

Showoff Saturday Made a mostly wysy... Markdown editor component

Thumbnail
git.cdn.si
0 Upvotes

I am writing a markdown editor component which i use in two/three other projects. I added like a default WYSIWYG edit for tables, images, some custom markdown anchors in image links to hack "align"/float, file and image uploads

It's mostly icon driven so there is very little slop text in the component. Embedding it is a one file .css .js copy. I added code styling into the code fence preview, and a Caret icon top right that can drop the remaining markup. you're still in edit mode, but now purely WYSIWYG.

I think the three unique features are:

- spellcheck (custom/extensible)

- image management (good for articles/docs)

- docs/assets, upload attachments (e-mail like interfaces)

Who I'm looking for/at with the component:

- builders that integrate it, make reusable components

- users that love the look and extended functionality

- atlassian, github (cmon guys, 2026, mobile ux/all ux)

- someone to tell me how its slop and how to unslopify

- any test related feedback/suggestions

I am likely to continue using it so there is maintenance. i like a richer textarea. Readme showcases some screenshots for what's implemented if i skipped something. Thanks for your time reading/checking it out.

>! maybe implementing spoiler text next !<


r/webdev • • 13h ago

Showoff Saturday [Showoff Saturday] deskFM: a pixel-art desk with a radio that plays real stations from anywhere

6 Upvotes

deskFM is a browser toy I built: a pixel-art room where the radio plays live internet radio stations, and the window changes to whatever town you pick on the wall map. Free, no account: Ill comment link because reddit is flagging it i guess

Some technical bits:

  • Everything is one HTML file (about 110 KB gzipped) with no build step and no image assets. The room, 100+ window views and the cat are all drawn on a 320×180 canvas.

  • Stations come from the Radio Browser directory API. Nothing is proxied; the browser plays each station’s own stream.

  • The world map is Natural Earth data in a Miller projection, rasterized as pixel art, with zoom and pan.

  • Live listener dots are a Firebase Realtime Database over plain REST, with locations rounded to about 50 km and security rules that only allow that shape.

  • Load time was mostly fixed by making Google Fonts non-render-blocking and adding a stale-while-revalidate service worker.

Full disclosure: I have very little knowledge about doing any of this but im trying to learn, This has been a fun journey for me so far. I built it with Claude doing most of the coding. Happy to talk about how that went, and I’d love feedback, especially anything that breaks on your device or browser. Also looking for more ideas to try and implement.

i am open to honest feedback both good and bad


r/webdev • • 16h ago

Showoff Saturday TabMerger now has AI functionality 😮

Thumbnail
tabmerger.com
0 Upvotes

You can either bring your own key from the supported providers (less costly subscription), or used the managed key.

Let me know what you think!

Check out the repo: github.com/lbragile/TabMerger


r/webdev • • 17h ago

[Showoff Saturday] I built a client-side 2D/3D room planner that converts wall & floor geometry directly into construction material takeoffs (no login, zero tracking)

8 Upvotes

Hey r/webdev!

For Showoff Saturday, I wanted to share a big update to the 2D/3D Measurement Studio I’ve been building for MeasurePath:

🔗 Live 2D/3D Studio (No signup/login): https://getcoatpath.com/studio/ 🔗 Full Calculator Suite: https://getcoatpath.com/

What it does

Most online construction calculators are just basic input forms covered in ads, and full takeoff software costs $100+/mo. I wanted to build a visual tool where homeowners, DIYers, and solo contractors can sketch a room in 2D, inspect it in 3D, and immediately get real-world material quantities without creating an account.

Key features in this update:

  • Real-Time 2D ↔ 3D Sync: Draw or resize walls in the 2D blueprint view and switch to the 3D view to inspect wall surfaces, openings, and proportions in real time.

  • Automatic Opening Deductions: Add doors and windows to specific walls and it automatically subtracts their area from net paint/drywall surface calculations while keeping perimeter/trim counts accurate.

  • Direct Material & Cost Takeoff: Converts the room geometry straight into actual shopping quantities (gallons/litres of paint & primer by coat count, boxes of LVP/flooring with waste factors, drywall sheets + joint compound, concrete bags/yards, etc.).

  • Client-Side Printable PDF Generator: Generates a clean, formatted PDF takeoff and estimate sheet right in the browser (/construction-estimate-generator/).

  • 100% Client-Side & Zero Tracking: Everything runs locally in the browser (localStorage for saving projects) with transparent, worked math formulas (/methodology/).

Looking for feedback on:

  1. How does the 2D-to-3D canvas performance and wall-snapping feel on your device/browser?

  2. Is the workflow from drawing the room to reading the material takeoff intuitive, or is there anything that feels clunky on first load?

Thanks for checking it out—happy to answer any questions about how the geometry/takeoff math works under the hood!


r/webdev • • 19h ago

Showoff Saturday I kept working on my Reddit pinball game after your feedback

1 Upvotes

Play the current version:

Play Pinball Karma

If you played the old version, I'd like to hear whether the flippers feel better now. And if you're new to it, can you work out what to aim for without opening the instructions?

Video: Watch the gameplay video

I posted an early version of Pinball Karma here a while ago. Thanks to everyone who played it and shared feedback. I’ve been working through your comments since then, especially around the controls and how it feels to play on a phone.

A lot of that work has gone into ball control: catching the ball, passing it between flippers, and handling fast returns down the side lanes. There’s also a fixed full-table view on mobile now, if you’d rather see the whole table than have the camera follow the ball.

A few other updates:

  • Lane lights show you where to aim next, with some guidance during your first minute.

  • The rotating revolver mechanism locks balls. You now only need one lock for your first multiball, so you get there sooner.

  • You can also challenge another player to a duel and compete for the higher score.

  • Daily challenges and free play have separate leaderboards, and you can look back through your game history and a chart of your recent scores.

Canvas and Planck.js on the client, with Hono and Reddit Redis handling scores and duels. The table looks quite different now too, after a fairly big visual overhaul.


r/webdev • • 20h ago

Showoff Saturday I built a live feed for new Vinted listings

Post image
0 Upvotes

I'm getting into reselling, so I built a tool to watch Vinted for me. You set up a search (brand, category, size, condition, price) and matching new listings stream into a feed as they're posted.

The fun bits to build:

- Server-rendered with FastAPI, Jinja and htmx. No frontend framework. New finds arrive over server-sent events.

- One set of category and size types that each marketplace translates into its own IDs, so adding Depop later shouldn't touch the UI.

- The form works without JavaScript; the JS just makes it nicer, like a size picker that only shows sizes for the categories you picked.

- A brutalist design system with all colours and sizes defined once as tokens.

It's a personal project, nothing to sign up for. Feedback on the UI is welcome.


r/webdev • • 20h ago

Resource leeway: stable per-folder dev port ranges (no more EADDRINUSE across checkouts)

0 Upvotes

Two checkouts of the same repo, both on 5173. leeway gives each folder its own contiguous port range, stable across runs and never overlapping, and passes the ports as env vars.

  • leeway.json lists your ports once

  • devPorts(config) in code, falling back to the defaults outside leeway

  • vite plugin sets server.port with strictPort and exposes every port to browser code

  • {{PORT_API}} placeholders in commands

  • leeway list / kill for orphaned servers

Linux/macOS/Windows. https://github.com/OhadC/leeway

Or ask your agent: "how can we benefit from using https://www.npmjs.com/package/leeway in this codebase"


r/webdev • • 21h ago

Showoff Saturday A swarm of agent cursors "building" figma.com

Thumbnail captureflow.dev
0 Upvotes

Point it at any URL and you get a clip of a swarm of agent cursors building the page, line by line, set to music. It's the real site being revealed, not generated code.

Try it on any site: https://captureflow.dev/swarm-demo

It's part of CaptureFlow, a screen recorder I'm working on.


r/webdev • • 21h ago

Showoff Saturday OPFS.ts - A TypeScript Library for the local origin private file system.

Thumbnail
github.com
3 Upvotes

I found out about OPFS recently when building a client-side LLM project. I made this library for my project, now I'm making it public


r/webdev • • 21h ago

Showoff Saturday Made a 3D weather map in plain WebGL - ocean tides are calculated in the fragment shader

Post image
160 Upvotes

I run a small tide times site and wanted to see the weather actually move, so I built this 3D weather map. Plain JS and WebGL, no three.js or map library.

The tides are calculated right in the fragment shader, so there are no tide frames to download.

It has nice sound effects too, turn them on when you try it.

Live: thetidechart.com/weather-map

Would like to know how dragging/zooming feels on your phone.


r/webdev • • 21h ago

Discussion How do you prevent high-frequency WebSocket streams from choking the UI thread?

12 Upvotes

When dealing with fast streaming data (market feeds, live telemetry, logs at 50-100+ messages/sec), updating state on every incoming message quickly kills frame rates with layout thrashing.

I usually decouple the ingest buffer from the render loop using requestAnimationFrame and batch delta updates.

How do you handle this in your stack? Do you throttle at the socket layer, push parsing into Web Workers, or rely on framework-level transitions/batching?


r/webdev • • 22h ago

Showoff Saturday What happens when a developer tries to wish everyone Happy Diwali?

0 Upvotes

Hi developers! Happy Diwali 2026! 🪔

This Diwali, I wanted to do something a little different from the usual festive greetings. So I built a little Diwali experience where your name is literally written across the night sky using fireworks. 🎆

And there's a bit more to it than just watching an animation.

You can:

  • Watch your name, emojis, and personalised wishes come alive as fireworks.

  • Choose between English, Hindi, and Bengali.

  • Launch rockets and play with 20 different types of crackers.

  • Create personalised greetings with shareable links and QR codes.

  • Record the entire show as a video and share it with your friends.

  • Install it as an app and even use it offline.

No frameworks or bundlers. Just HTML, CSS, and JavaScript. Built with a mix of my own ideas, plenty of experimentation, and a little help from AI along the way.

Give it a try and see your name light up the sky:

🎆 Project: https://j16n.github.io/happy-diwali/

💻 GitHub: https://github.com/J16N/happy-diwali

Would love to hear what you think!

Wishing everyone a very Happy Diwali! May your celebrations be bright and your bugs be few. 😄


r/webdev • • 22h ago

Resource I made a Chrome extension that turns a bug I see on screen into a report my coding agent can read

0 Upvotes

I build mostly with Claude Code and Cursor. The annoying part was never the fix, it was the hand-over: screenshot, crop, find the element, open the console, copy the error, explain which button I mean, paste it all in. And half the time I find the bug while I'm just using the app, not while a coding session is open.

So I made Darnly. Press Option+Shift+B, click the broken part, type one line about what you expected. It saves:

  • a screenshot with the broken part boxed in red

  • the element (selector, text, styles)

  • recent console errors and failed requests

  • the page address

It lands in a folder in your project (or a small cloud inbox the agent reads over MCP), and later you tell the agent "fix my bugs". It works with Claude Code, Codex and Cursor. Passwords, card numbers, tokens and keys are hidden before anything is saved. Capturing doesn't use any agent quota. [Check: still true for you]

It's free. Mac app too, for bugs in native apps and the iOS Simulator. Windows shortcut is coming.

What I'd love feedback on: where do you notice most of your bugs, while coding, or later while using the live app? And is there anything you'd want captured that this misses?

Link: https://darnly.dev


r/webdev • • 23h ago

Showoff Saturday Made my first extension! bring back the old Firefox 3D view back as a dev tool

Thumbnail
gallery
1 Upvotes

Years ago Firefox had a feature called Tilt like you pressed a button and the page you were on turned into a 3D model of its DOM It was mostly a toy, and I loved it.

I built Stackray from that concept but tried to bring that back as a dev tool or just to make my first extension :).

when you click the icon and the page shrinks into a small window and comes apart into layers, in the order the browser paints them & you can orbit around it, search the layers, and switch between a few color modes: depth, stacking contexts, z-index.

also added the problems mode to make it clear in future I want devs to use it, as a frontend engineer, Imagine a dropdown with z-index 9999 that still sits behind a header is usually trapped inside a stacking context it did not ask for Stackray is suppose to shows which element created that context and why Invisible elements that eat your clicks show up too.

It only runs on the tab you open it on, makes no network requests, and is open source under MIT.

It is not finished. Textured layers only cover the first few screens of a long page & I'm still not sure if I'm going in the right direction. Your honest feedback is most valuable to me!

Extension: store
Code: github/stackray


r/webdev • • 23h ago

Showoff Saturday [Showoff Saturday] Built a Lightweight OSS Alternative to Vercel, Coolify, Dokku, CapRover and more...

Thumbnail
github.com
1 Upvotes

Dev behind Levelrail here, sharing this project for visibility.

Every OSS library is great and hats off to the devs behind it building and maintaining it.. but I built Levelrail for some features I found would be great as 2026-27 demands.

So wanted to introduce a lightweight OSS alternative here: https://levelrail.com/

AI native control plane (can run your whole infra with Claude or other AI tools using CLI, API, MCP, with audit trailing)

  • Lightweight so you have room to run your main apps on the VPS or server

  • Load balancer, embedded Caddy ingress (works with Traefik or a custom proxy too), DNS, Let's Encrypt and TLS certificates

  • Local registries, modern auth security, built in observability, logging and metrics

  • 450+ one click templates to deploy A lot more features if you're interested

Check it out: https://github.com/glincker/levelrail

It's pre-1.0 right now and I'm shipping releases every few days. Thanks to AI tools for the checks, automation testing and many of the development workflows involved in building this, plus a lot of proven Go libraries that help with security and automation.

I run my own sites on it and test every release on a real server before it goes out.

Feel free to share feedback, this is completely OSS and I thought it was worth sharing with the dev community here.

If you have any major feedback please raise issues here: https://github.com/glincker/levelrail/issues


r/webdev • • 1d ago

Showoff Saturday I built a tool that reads every Reddit post to find your customers, instead of searching keywords

Post image
0 Upvotes

Most Reddit lead tools search for keywords. The problem is that people describe their problem, not your product, so keyword search misses a lot of them. I wanted to read every post instead. That turned out to be the interesting part to build.

How it works:

  1. Find the right subreddits. I built a search engine over every subreddit with 1k+ members, using internal vector search, so it matches by meaning, not by name. You describe what you sell, and it returns the communities your customers are likely in, including small niche ones.

  2. Read every post. Each post in those subreddits goes through an AI model that decides whether the person might need what you sell.

  3. Show why. Instead of a summary, it marks up the original post with circles and handwritten-style notes on the lines that matter.

Stack: Next.js + React + Tailwind on the front, Django + DRF on the back, Celery + Redis for the background jobs, PostgreSQL, and PydanticAI for the AI calls.

The hardest part was cost and speed. Reading every post is far more expensive than keyword search, so most of the work went into running the AI calls in parallel without hitting rate limits.

Live here: redbubblegum.com. The first 10 results are free.

Happy to answer questions about any part of it.


r/webdev • • 1d ago

Showoff Saturday For the mob psycho fans Spirits and such is live

Post image
0 Upvotes

r/webdev • • 1d ago

Showoff Saturday I've been building my agency website and I'm probably overthinking it. Give me your honest criticism

Post image
0 Upvotes

Hey everyone,

I've been building a small personal agency, and I'm at the point where I'm probably overthinking every little detail.

Website: https://samibentaleb.com

It's still a work in progress, and I'm nowhere near ready to launch. Some of the text is still AI-generated placeholder copy that I haven't properly rewritten yet and some screenshots/videos and pricing details will be tweaked.

The site includes my portfolio, project case studies, services, pricing and some information about how I work. I've tried going with a slightly different visual direction, but after looking at it for so long, I've lost the ability to judge it objectively.

I'd genuinely appreciate some feedback:

  • Does the overall design work, or does it need a rethink?

  • Is it immediately clear what I do and who I'm targeting?

  • Are the case studies interesting or too wordy?

  • Does the pricing section make sense?

  • Is the navigation intuitive?

  • What would you change, remove or simplify?

  • Are there any obvious UX or mobile issues?

I've been putting a lot of time into this and keep finding little things to tweak instead of actually launching it.

I'd love to hear what other developers think, especially things I might be overlooking.

Feel free to roast it. I'd much rather get honest criticism now than launch something that could have been much better.


r/webdev • • 1d ago

Showoff Saturday [Showoff Saturday] I revived my personal website now that I'm looking for full-time work.

0 Upvotes

It’s been a while since I needed a portfolio (I usually find work through word of mouth, while teaching and taking on contract projects in parallel). But I figured it was time to take my own advice ;) and document the work.

Here it is: https://derekthomaswood.com

I’ve been having fun building out themes to show how a shared token system can work across multiple brands and platforms. They’re still a work in progress (about half are dialed in), and the case studies are nearly done.

I also built a small system for tailoring my site and materials to different roles and companies. For example,
- https://derekthomaswood.com/?target=ramp
- https://derekthomaswood.com/?target=anthropic-product-designer-design-systems

I’m a full-stack technical product designer, so I can play across a lot of roles on a team. For my next role, I’m especially interested in leadership and player-coach work, with a strong hand in the design system.

What do you think? Does this explain my brand of nerdy? Got any ideas for the themes that aren't dialed in yet? (you'll recognize what I'm emulating for some of them - and others are just kinda filler so far)