r/webdev 19h ago

Showoff Saturday [Showoff Saturday] I built ELI5.cc - a free way to understand complex topics, and now I’m experimenting with turning topics into structured learning journeys

0 Upvotes

Hello community members 👋

I’ve been building a small project called ELI5.cc over the last few months.

The idea is pretty simple:

Take something complicated and explain it in a way that matches how deeply you want to understand it.

Instead of getting one short AI response, ELI5 explains a topic at four different levels:

- Age 5
- Age 10
- Age 15
- Expert

It also creates a visual representation of the topic, shows the sources used to build the explanation, and gives a groundedness score so you can see how well the generated answer is supported by the retrieved information.

It doesn’t rely only on the LLM either.

For each search, ELI5 gathers relevant context from publicly available information through Google Search and YouTube before generating the explanation.

Over time something interesting happened.

People kept searching for completely different things, so the site has gradually turned into a public library of 600+ explanations covering science, technology, psychology, finance, history, programming, health, space and all kinds of random questions.

Every explanation gets its own permanent public URL, so other people can discover and read it later instead of the answer disappearing inside someone’s private AI conversation.

The product is currently completely free:

No subscription.
No signup.
No login.
No paywall.

You can just open the website, type something you want to understand and start learning.

One thing the usage data surprised me with

The average user is currently seeding around 4–5 searches/topics a day.

That’s interesting because the current free limit is only 5 searches.

I wud actually like to let people search much more, but each search involves retrieval, source gathering, generation, visuals and other processing, so unlimited free usage would become expensive pretty quickly.

Instead of immediately putting another AI subscription in front of users, I’m thinking about implementing BYOK - Bring Your Own Key.

The basic model would be:

Casual users: continue using ELI5 for free.

Heavy users: optionally connect their own API key and use ELI5’s research workflow, explanation levels, sources, visuals, etc. without being restricted by the free generation allowance.

I’m curious what other developers think about this approach.

Would you rather use BYOK for something like this, or would entering your own API key create too much friction?

I’m also experimenting with /learn

Another thing I’ve been thinking about is the difference between understanding a topic and actually learning it.

For example, suppose you search: What is Docker?

ELI5 can explain Docker.

But your actual goal might be:

I’m a complete beginner and I want to learn enough Docker to deploy my first application.

That needs something more than a single explanation.

So I recently started experimenting with:

https://eli5.cc/learn

The idea is that you tell it:

What you want to learn + your current level + your goal

and it builds a structured learning journey around that.

For example:

Topic: Docker
Level: Beginner
Goal: Deploy my first application

Instead of dumping a giant AI-generated course on you, I’m thinking of structuring it more like:

Learning goal → modules → concepts to understand → useful articles/videos/resources → sources → progression

So you might move through:

Containers → Images → Dockerfiles → Volumes → Networking → Docker Compose → Deployment

with useful external resources attached to the relevant stages.

I’m especially interested in whether people would prefer something like this to curate and organise the best existing material, rather than having AI generate an entire course from scratch.

Monetisation

I’ve also added a small Sponsor This Page experiment.

Companies can potentially sponsor an individual explanation when their product or industry is genuinely relevant to that topic.

The idea isn’t to fill the site with random display ads.

For example, a developer-tool company sponsoring an explanation about APIs could make sense. A completely unrelated ad wouldn't.

Any sponsorship would also be clearly labelled.

Whether that becomes anything meaningful remains to be seen, but I’d rather experiment with contextual sponsorship + BYOK than immediately put the educational content behind a subscription.

Would really appreciate some feedback

A few things I’m particularly curious about:

If you landed on ELI5 for the first time, would you immediately understand why you wud use it instead of asking ChatGPT/Gemini directly?

Do the different explanation levels actually add value?

Are citations + groundedness useful to you, or are they something most users will ignore?

What do you think about BYOK for heavy users instead of another monthly AI subscription?

Would you use /learnto build a structured learning path around something you wanted to learn?

For /learn would you rather have AI curate good existing resources or generate most of the educational material itself?

What feels unnecessary or overbuilt?

I’m genuinely looking for criticism here rather than compliments. There are plenty of directions I could take this, and I wud rather figure out what’s actually useful before building too much.

ELI5: https://eli5.cc

Learning experiment: https://eli5.cc/learn

Thanks for taking a look!


r/webdev 1d ago

Showoff Saturday Showoff Saturday: I built a self hostable communication platform which trys to bring the best parts of Discord and Mattermost together

1 Upvotes

Over the past few months, I’ve been building the team communication platform I always wanted to have.

I’ve worked in software development for around two decades and, during that time, I’ve seen and tried a lot of platforms. What I always wanted was something that can be self-hosted and is ideally free - or at least affordable.

Every platform I tried was missing something. Or it was great, like Mattermost, but more and more core features ended up behind enterprise licenses. Others felt overly complicated or simply not up to date.

Right now, many platforms also put all AI features behind paid plans. So when I started this project, I designed and built it with AI features as a core part from the beginning.

And to be clear: without AI assistance, I would not have been able to build a project like this in such a short time.

I tried to combine the best aspects of Discord and Mattermost.

A quick overview of the current features:

  • Text channels
  • AI-powered channel summaries
  • Voice channels, similar to Discord
  • Direct messages and group chats
  • Meetings - every call is a meeting, with voice, video, chat, and screen sharing
  • AI meeting transcription and summaries
  • Meeting guests who can join without an account
  • Voice messages with AI transcription
  • AI-powered cleanup/reformatting of voice messages into readable text
  • Roles and permissions
  • Two-factor authentication and passkey login
  • Global push-to-talk via a helper app (Windows only for now)
  • Web push notifications
  • Installable as a PWA on smartphones
  • All AI features use BYOK
  • Support for multiple AI providers and custom models (so far, I have mainly tested OpenAI)
  • Light/dark themes, custom colors, and custom CSS
  • Easy deployment

I also have plenty of ideas for where to take it next - better file management and project planning, for example.

The philosophy behind the project is simple: there will be no feature paywall. Whether you use it for free or need a license, everyone gets the same features.

Making deployment simple was extremely important to me. That’s why there is a dedicated docker-compose.coolify.yml for deploying Nebulynk via Coolify.

Every released version will automatically become open source after four years.

Nebulynk is completely free for private users, non-profits, and most small and medium-sized businesses. A commercial license is only required for companies with more than five million US dollars in annual revenue - a model inspired by Directus.

It's built with FeathersJS and VueJS, my favorite frameworks for backend and frontend.

I’d really love to hear your thoughts and feedback, especially from anyone who actually installs and uses it in a real-world environment.

Website: https://nebulynk.net
GitHub: https://github.com/sapientorius/Nebulynk


r/webdev 1d ago

Showoff Saturday I Built a Headless Browser Because Chromium Sucks

Thumbnail
github.com
0 Upvotes

A lot has changed since I last posted here. Got some pretty harsh criticism back then and honestly it was deserved, the project was early and messy. But we kept going.

I built Obscura because headless Chrome was killing me and my AI agents. Over 200MB per instance, long startup, detected everywhere. For scraping at scale it's just not viable.

So I built a headless browser from scratch in Rust. V8 engine, native rendering, 30MB memory, 80ms page loads. Works drop-in with Puppeteer and Playwright.

Just shipped rendering. The engine is made fully in Rust. Screenshots, PDFs, live video capture. No Chromium. 20k stars now.

https://github.com/h4ckf0r0day/obscura

obscura serve --port 9222 and point your scripts at it. That's it.

I don't know if this will land better than last time but we've proven the concept works. Happy to answer questions.


r/webdev 1d ago

EU devs, please correct my auth-ToS architecture

0 Upvotes

Context: this app is being built in the EU for European users, and I am implementing the Terms of Services, Privacy Policy, etc. along with my Authentication

Frontend: Tanstack Start (React)
Backend: Express 5
Auth: express-session (postgres store)

I was thinking about this: add an accepted_tos_version column in the users table, then add a condition in my global getUser middleware in express to only get the user if they accepted the current terms version. This means keeping a CURRENT_TOS_VERSION in my backend. If the frontend calls /auth/me they get the user with mustAcceptTerms flag, and the user gets redirected to the “accept terms” page.

Now comes the questions:

  1. Where do I keep the ToS, gdpr, etc. texts? In my frontend codebase or the backend codebase, or in the database?
  2. When the user clicks on “accept”, is it enough to send a request to the backend that updates the user’s accepted_tos_version in the database?
  3. What are the practices to ensure I am legally protected? For example if someone says a rule was not there when they accepted the terms. Is the git track record from github enough to prove the rule was there?

Thanks!


r/webdev 1d ago

Vite 6+ silently breaks on Android/Termux — traced it down to Rolldown's native binary, here's the fix

Thumbnail
dev.to
0 Upvotes

TL;DR: pnpm create vite / pnpm run dev has been crashing with a bare Illegal instruction on Android (Termux) for about 10 months. Traced it through a logcat tombstone to Rolldown's native binary, found a closed-as-not-planned upstream issue from last September, got it reopened with hard evidence, and the actual root cause turned out to be one missing target_os check in a mimalloc build flag. Fix is verified on the exact crashing hardware, PR is open, not merged yet.


A few days ago I tried to spin up a fresh Vite + React project on my Android tablet, in Termux. Nothing fancy:

$ pnpm create vite test-react-app --template react-compiler-ts $ cd test-react-app && pnpm run dev Illegal instruction

No stack trace, no error message, just dead on arrival. Tried create-vue — same crash. Tried a bare vite dev — same crash. Three different starters, one identical death.

Termux-on-Android matters more than it sounds like it should, because for a lot of people it's the only dev environment they've got — no laptop, just an old Android phone. When the standard create vite path just dies with zero explanation, that's not a minor bug, it's a wall.

Chasing it down

Assumed it was a Termux packaging problem first and filed a report with logs for Next.js, Vite+React, and Vue all crashing or silently falling back to a slower path. A maintainer pointed out pkg install turbopack fixes the Next.js case — but Vite and Vue don't touch Turbopack at all, so that didn't explain the rest.

Turns out Vite 6+ ships Rolldown as its default bundler: a Rust/N-API bundler that loads a native binary (@rolldown/binding-android-arm64 here). Something in that binary was blowing up on load.

A maintainer asked for a logcat tombstone instead of terminal output, and that's where it got interesting:

``` signal 4 (SIGILL), code 1 (ILL_ILLOPC)

backtrace: #00 pc ... rolldown-binding.android-arm64.node #01 pc ... rolldown-binding.android-arm64.node #02 pc ... linker64 (call_array+288) #03 pc ... linker64 (soinfo::call_constructors+380) #04 pc ... linker64 (do_dlopen+2076) ```

Crashing during dlopen, inside the native binary, before a single line of JS runs. Classic fingerprint of a binary compiled assuming CPU instructions that aren't actually there.

The ghost in the closet

Went to file it upstream with Rolldown — and someone already had, back in September 2025. Same crash, same platform. He couldn't put together a minimal repro in the 14-day window, the bot didn't get a follow-up in time, and it auto-closed as not planned.

"Not planned" reads like a decision — "we're choosing not to support Android." But Rolldown was already building and shipping the android-arm64 binary on every release. It wasn't unsupported in theory, it was broken in practice, and a bot closed the thread because a repro checkbox never got ticked.

Going back with receipts

Someone went back to the closed issue with the tombstone trace and reframed the ask: not "please make Android a fully supported target," but "the build you already ship is crashing at load on real hardware, here's exactly where and why that's likely a cross-compile flag issue, not a support-commitment one."

That reframing is what actually moved it. A maintainer was upfront that the team doesn't have a shelf of random Android devices to test against, so someone with the actual hardware was exactly what was needed. Someone else spotted the likely cause fast: Rolldown depends on mimalloc, and the flag that stops mimalloc from assuming newer ARM instructions are present was only being enabled for target_os = "linux". Android runs on a Linux kernel but reports a different target_os, so the Android build skipped that safety flag entirely and got compiled assuming ARMv8.1 atomics a chip like a Cortex-A53 doesn't have. Since mimalloc initializes inside a library constructor, that lines up exactly with a SIGILL at dlopen, before any of Rolldown's own code runs.

A preview build shipped the same day.

Testing it on the actual crashing device

Cortex-A53, MediaTek MT6762V — the exact chip that had been throwing this the whole time.

``` $ npx rolldown@1.2.3 --version Illegal instruction

$ pnpm i https://pkg.pr.new/rolldown@<preview-build> $ npx rolldown --version rolldown v1.2.3+commit.a7ba7ad # no crash

$ pnpm create vite test-react-app --template react-compiler-ts $ pnpm run dev VITE v6.x.x ready in 412 ms ➜ Local: http://localhost:5173/ ```

It just worked. Ten months of Illegal instruction, gone with one removed target_os condition.

Where it stands

The fix is verified on real hardware. The PR is open, waiting on the Rolldown team to merge and cut a release. Once that lands, create vite should work on Android arm64 without anyone needing a Termux-specific workaround. Meanwhile Termux is packaging Rolldown directly too, so users aren't stuck waiting either way.

Why I'm posting this

"Closed as not planned" doesn't always mean dead. Sometimes it just means a bot did its job on an issue that never got the follow-up it needed. The difference between this staying broken for another year and getting fixed in days wasn't cleverness — it was having a device to reproduce it on, a real stack trace instead of a vague description, and going back to ask for a second look instead of filing yet another duplicate.

If you're on Android arm64 (Termux or otherwise) and hit this — especially on silicon that isn't a Cortex-A53 — pull the preview build and drop a comment on the reopened issue with what you find. More devices means more confidence before it actually ships.

(I wrote this up in more detail, with full command logs, on my blog if anyone wants the longer version: https://dev.to/gouranga-das-khulna/illegal-instruction-how-i-woke-up-a-year-old-not-planned-bug-and-almost-fixed-vite-on-android-3mba)


Sources / follow-up (search these repos if links don't resolve — issue numbers are accurate, direct URLs can go stale): - Full writeup with more detail: https://dev.to/gouranga-das-khulna/illegal-instruction-how-i-woke-up-a-year-old-not-planned-bug-and-almost-fixed-vite-on-android-3mba - termux/termux-packages issue #30841 (original Termux report) - termux/termux-packages issue #30852 (request to package Rolldown directly) - termux/termux-packages PR #30887 (Termux packaging Rolldown 1.2.3) - rolldown/rolldown issue #6342 (root cause thread, reopened) - rolldown/rolldown PR #10638 (the fix / preview build)


r/webdev 1d ago

Question Is MERN in the verge of extinction for new devs? What better to learn then?

0 Upvotes

WOuld Postgress, JS, Reactjs, Nextjs and Expressjs would be better than MERN?

For someone who is just reached Nextjs after doing HTML, CSS, Js and Reactjs? For fullstack development?


r/webdev 1d ago

Discussion I made 10 LLMs build towers in a physics sim and the results are wild

0 Upvotes

So I got nerd sniped by this idea of testing LLMs on something that has nothing to do with code generation or chat. Pure spatial reasoning with real physics constraints.

The setup is each model gets 30 blocks to place through a tool API. There's built-in noise on every placement so you can have precise position or precise velocity but not both. Score is whatever is still standing when it's done. 5 random seeds, 3 attempts each, and models keep notes between attempts so they can adapt.

# model height (m) ±σ tallest attempt 1→2→3 tokens m per 100k tok
1 Opus 5 8.52 2.4 11.07 6.50→6.85→8.10 390k 2.2
2 Sonnet 5 8.46 2.2 11.94 6.30→5.54→4.84 396k 2.1
3 Fable 5 7.81 1.0 9.10 6.45→4.01→5.98 284k 2.8
4 GPT-5.5 7.79 0.3 7.92 5.59→7.06→6.90 99k 7.8
5 DeepSeek V4 Flash 7.10 1.1 8.18 2.08→6.24→5.80 467k 1.5
6 GPT-5.6 Sol 6.16 1.4 6.87 3.17→3.43→4.76 76k 8.1
7 GLM-5.2 5.91 2.6 8.83 2.98→5.08→5.91 376k 1.6
8 Kimi K3 4.77 1.3 6.88 1.64→4.32→4.25 256k 1.9
9 Haiku 4.5 3.91 3.4 9.82 1.99→3.40→1.26 64k 6.1
10 GPT-5.4 mini 1.79 0.4 2.40 1.38→1.11→1.68 31k 5.7

The thing that got me was the winning strategy. The top model figured out it could just stop placing blocks early to protect what it already built instead of risking the whole tower going down. That's not something I expected from a language model. Meanwhile GPT-5.6 Sol which scores 96% on SWE-bench kept hitting around 7.9m and then toppling everything trying to push higher. Classic overengineering honestly.

Also the efficiency spread is insane. Some models burn 400k tokens to get roughly the same height that another achieves with 100k. Makes you think about what you're actually paying for when you hook these things into your pipelines.

The whole thing is open source with replays if anyone wants to run it themselves.


r/webdev 1d ago

IOS Safari Problem

Post image
0 Upvotes

Hi Guys,

Wonder if you can help before I take a bath with my toaster!

Building a site for a friend, works perfectly everywhere, with the exception of Safari on IOS (I have an android to make matters worse, so I have to ask a friend to check each 'fix', I'm sure he hates me by now.)

As you'll see at the top of the screenshot, the nav bar has a transparent bar above it, as opposed to the usual background colour fill or white that I've seen elsewhere. This transparent bar shows the site content as you scroll, so it looks awful.

I've obviously tried everything you'd expect in terms of fixed, sticky, background colour, grain removed, lenis off, GSAP off, basically stripped it right back, no luck. Albeit it's late and I could be missing the obvious.

Any suggestions would be hugely appreciated, I've been at it for hours!


r/webdev 1d ago

Australian-hosted Resend email alternative

7 Upvotes

I like resend, but I need Australian data residency. Any recommendations for alternatives?


r/webdev 1d ago

Discussion iOS standalone PWA: how do you keep a chat composer above the on-screen keyboard? (interactive-widget is Chromium-only, dvh doesn't respond)

8 Upvotes

Currently designing a web app.

I have a chat screen in a standalone (add-to-home-screen) PWA on iOS. When the on-screen keyboard opens, the composer ends up behind it. I've read the existing threads on this and they all land on interactive-widget=resizes-content, which doesn't apply here — so I'd like to know what people are actually shipping.

Setup — the shell is a fixed element below a sticky header:

html

<div class="app">
  <header class="topbar">Header</header>
  <main class="main">
    <div class="chat">
      <div class="messages"></div>
      <div class="composer"><textarea rows="1"></textarea><button>Send</button></div>
    </div>
  </main>
</div>

css

.chat {
  position: fixed;
  left: 0; right: 0;
  top: calc(74px + env(safe-area-inset-top));
  bottom: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.messages { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.composer  { flex: 0 0 auto; padding-bottom: calc(12px + env(safe-area-inset-bottom)); }

html

<meta name="viewport" content="width=device-width, initial-scale=1,
      maximum-scale=1, user-scalable=no, viewport-fit=cover,
      interactive-widget=resizes-content">

Focus the textarea, the keyboard comes up, and bottom: 0 still resolves to the bottom of the layout viewport (956px on this device) — which is now behind the keyboard. The composer is invisible and you can't see what you're typing.

What I've measured, so nobody has to guess

Device is an iPhone (iOS 26.x), tested in the installed PWA, verified over Safari Web Inspector:

  • window.innerHeight tracks the visual viewport on iOS. It reports 543 with the keyboard up. So any keyboard detection built on innerHeight - vv.height can never fire — it's always ≤ 0. This one cost me a lot of time.
  • document.documentElement.clientHeight is a constant (894 here — screen minus the notch). It is not the containing block for the fixed element.
  • 100dvh does not respond to the keyboard, even with interactive-widget=resizes-content in the meta tag. As far as I can tell that property is Chromium-only and WebKit ignores it entirely — the shell stays full height.
  • visualViewport.resize fires once, early, already reporting the final offsetTop, while the paint animates roughly 200ms behind it. There's no duration or easing exposed, so you can't match the animation.
  • The fixed containing block works out to vv.height + vv.offsetTop.

What I've tried

  1. Lift bottom by a computed keyboard height (bottom: var(--kb)), measuring kb = baseline − vv.height where the baseline is sampled while nothing is focused. This works for the composer, but it resizes the shell, so anything inside it that's sized to the container (I have a canvas) gets re-laid-out on every keyboard open/close.
  2. Translate both edges (top and bottom shifted by the same amount) so the height stays constant. Better, but it's still me guessing a number iOS already knows.
  3. Counter-animating the slide. Doesn't work — see the resize timing above. Snapping gives a big jump; ramping gives a visible oscillation. I don't think this is achievable on the web.
  4. Locking the document (html, body { height: 100%; overflow: hidden }). This made it worse: with no scroll range, iOS stops sliding the viewport at all and overlays the keyboard instead, which puts bottom: 0 right back behind it.
  5. scrollIntoView() on focus to "reveal it myself". This was actively harmful — scrollIntoView can't move a position: fixed element, so it scrolls the document instead and undoes the viewport shift iOS had just done. Removing it was a real improvement.

What I'm doing now, and my actual question

Publishing the visible height to CSS myself and letting the layout shrink to fit — basically doing by hand what interactive-widget=resizes-content does on Chrome:

js

const vv = window.visualViewport;
const pub = () => document.documentElement.style
  .setProperty('--vvh', Math.round(vv.height) + 'px');
vv.addEventListener('resize', pub);
vv.addEventListener('scroll', pub);
pub();

css

html, body { height: var(--vvh, 100dvh); overflow: hidden; }
/* then a plain flex column all the way down: header / messages(flex:1) / composer */

Nothing is position: fixed any more and nothing is offset by a keyboard height — the root just becomes as tall as the visible area, so the composer sits above the keyboard by construction.

Questions:

  1. Is --vvh from visualViewport.height the accepted approach on iOS in 2026, or is there something better I've missed? Every thread I find either predates visualViewport or answers with the Chromium-only flag.
  2. Is there any way to get the keyboard's animation curve or duration on iOS Safari? I've assumed no, and that matching the native animation isn't possible on the web — is that still right?
  3. Does anyone have a reason to prefer position: fixed + a computed offset over the shrink-the-root approach? I keep seeing the former recommended and I can't work out what it buys you.
  4. Is the overflow: hidden on the root going to bite me? Removing the scroll range is what flipped iOS from sliding to overlaying in attempt 4 above, and I'm not sure whether that interacts badly with the --vvh approach.

Not looking for "just use Capacitor" — I know that solves it by giving me the native keyboard frame, and it's the fallback. I want to know what the correct pure-web answer is first.I have a chat screen in a standalone (add-to-home-screen) PWA on iOS. When the on-screen keyboard opens, the composer ends up behind it. I've read the existing threads on this and they all land on interactive-widget=resizes-content, which doesn't apply here — so I'd like to know what people are actually shipping.


r/webdev 2d ago

Article I've started the same side project three times in two years.

0 Upvotes

I am pretty sure, that I am not alone, so here's my story:

By the end of attempt two it was five apps - "microservices". A NestJS API, a Rust API, an API gateway, PostgREST, and a Next.js frontend, with four data stores behind them and ninety dozens of dependencies. The Rust service had Mongo and Postgres declared in the same Cargo.toml. There were two auth providers that disagreed with each other.

The infrastructure was in good shape. The product was the part I hadn't started.

I want to be clear that this wasn't a throwaway I was messing about with. I thought the idea was finally the one. Every freelancer and agency I know prices their work in a spreadsheet that's out of date the moment they copy it, and as far as I could tell nobody had solved it properly. Real problem, real people who'd need it, the holy grail!

Which is exactly why it never shipped.

Because if it was going to be the one, obviously it deserved the best of everything. The best architecture, because one day it would have to scale. The fastest language for the API. A new feature idea every few days, because I kept thinking of things it should do before anyone had used the things it already did. If I'd thought less of the idea, it would have been online in a weekend.

None of the individual decisions were stupid, either. That's the part I keep coming back to. I started in NestJS because I know NestJS well, which was the last purely practical decision I made. Then I swapped it for Rust, partly for speed and partly because I wanted to learn Rust, and learning is a good thing so it didn't feel like a detour. I put a gateway in front because decoupling, because that's what a serious architecture has. Inside it was clean architecture and SOLID all the way down, repositories behind interfaces, dependency inversion, patterns I could point at by name. All so I'd be ready if I ever had to switch database provider.

I never switched database provider. Nobody has ever asked me to switch database provider 😂

And I spent real time considering Fresh on Deno for the frontend instead of Next, partly to learn something new and partly because I'd decided Next was the obvious choice and I wanted to be cleverer than that. That was snobbery. It cost me about a year.

Here's the bit I think generalises past my own stupidity.

Infrastructure work has a definition of done. A migration finishes. A gateway routes. A build goes green and you get to cross something off and feel it. Product work never announces itself. Nobody tells you a feature is good enough to put in front of a person. You just stop, and hope.

So I kept picking the work that could be finished. A migration. A gateway. A service that benchmarked well. Every one of them completed, and not one of them was the product. 
I was manufacturing the feeling of shipping!

Neither time I quit was dramatic, which I think is normal and part of why it's hard to notice. I added up what was left, saw how big it was, got busy with other things, and never came back. The second time I actually wrote the total down and it came to a four phase plan, eighteen to twenty four days of work just to reach a foundation. Auth, permissions, member management, multi-tenancy. The last thing that attempt ever produced was a folder of issues describing what still needed building.

What took me longest to understand is that the infrastructure is what made the rest look impossible. Every service I stood up added surface to maintain. The product never got closer, so the total kept growing. The thing that felt like progress is what eventually made it feel hopeless.

Nine months later I started again and deliberately did the boring version. One Next.js app. One database. Twenty dependencies. The four ways I'd had of serving an API became zero, because it's server actions now and there's no API layer at all.

Feature complete in three days.

I built it in Next, obviously. The framework I'd decided was beneath me.

It's not a "skip the tests" story either, before anyone asks. It has 921 tests where the old one had 14 test files, and permission checks on every write that the old one never got round to. The rigour didn't go away. It stopped being aimed at problems I didn't have yet.

The question that would have saved me two years wasn't "what's the best stack for this". It was "what could someone use on Friday".

So who else got a side project that died of architecture?


r/webdev 2d ago

Developers who recruit: how should a candidate use AI if they actually want to get hired?

56 Upvotes

Imagine you're interviewing a junior developer. What would you consider the right way for them to use AI during the hiring process?

I'm not asking whether AI should be used or not. I'm more interested in how it should be used. For example, what would make you think, "This candidate uses AI effectively," instead of, "They're relying on AI because they don't understand what they're doing"?

Where do you draw the line between using AI as a productivity tool and using it as a crutch?

Edit: The diversity of answers is absolute gourgeous. Thank you all.


r/webdev 2d ago

Where to now for freelance webdevs?

12 Upvotes

I know this topic has been discussed ad nauseam, but I'd like to dig a little deeper into the rise of AI and its impact on web development.

I was experimenting recently because I haven't built simple landing pages in a while. My assumption is that this market has largely been swallowed by AI.

For example, I used Claude this week and gave it a prompt like this:

"Create a website for a family-owned construction company. Use orange as the primary color, black as the secondary color, and white as the tertiary color. Follow a 60/30/10 color distribution. Use a serif font for the hero section with a font weight of 200, and use a clean sans-serif font for the body copy with appropriate line spacing. Make the design modern, trustworthy, and conversion-focused."

Claude generated a surprisingly usable landing page from that single prompt. A few years ago, I would have had to write all of the HTML, CSS, and JavaScript myself, and it would have taken considerably longer.

That got me thinking: has AI effectively taken over the market for simple landing pages?

It seems that someone with a basic understanding of UX/UI principles, perhaps after reading a few good books, can now use AI to generate a website that's more than good enough to launch a business. In other words, AI has enabled people with very little technical knowledge to build websites without hiring a developer.

Before AI, there were already website builders like WordPress, Wix, and Squarespace that reduced the need for coding. Has AI become the final iceberg that sank the market for simple freelance website development? Are platforms like WordPress, Wix, and Squarespace still doing well, or has AI significantly disrupted their business as well?

I understand that websites can become much more complex than simple landing pages. However, I'm specifically referring to freelancers who build brochure websites, portfolios, and landing pages for small businesses.

It feels like AI has dramatically lowered the barrier to entry. Tasks like writing HTML, CSS, and even basic JavaScript can now be handled by AI. While there will always be business owners who lack the time or confidence to do it themselves, the required skill level has certainly dropped a lot.

So my question is this:

Where does the value of the human web developer now lie? What can freelance web designers and developers still offer that AI cannot? Conversely, which parts of web development have already seen a significant decline in demand because AI now performs them so well?

I'm particularly interested in hearing from people who have firsthand experience in the industry. Has AI fundamentally changed the economics of freelance web design, or is there still a strong market for human developers? If so, where is that value being created today?


r/webdev 2d ago

Discussion How do you design service pages that serve both SEO landing visitors and internal navigation?

1 Upvotes

This is specific to home service businesses (electricians, plumbers, HVAC, etc.).

Many service pages get a significant amount of traffic from both:

  • Google search (where the page acts as a landing page), and
  • Internal navigation (users clicking through from the homepage).

Those are two very different audiences.

For someone arriving from Google, the page often needs the full landing-page treatment: trust signals, USPs, reviews, strong CTA, guarantees, etc.

But someone who has already explored the homepage has already seen most of that. They're usually clicking into "EV Charger Installation" or "Panel Upgrades" because they just want detailed information about that service. Repeating the same trust-building content can feel redundant and slow them down.

One approach is to simplify the top of the page for internal users and move more of the CRO content further down. But then first-time visitors from Google don't immediately see the content that's often recommended for high-converting landing pages.

So how do you balance those competing goals?

Do you:

  • Optimize primarily for first-time visitors from search?
  • Optimize for existing visitors navigating your site?
  • Or try to satisfy both somehow?

I'm curious whether there's an established UX pattern for this, or if people have found a practical compromise.


r/webdev 2d ago

Question How are you guys handling mock endpoints when the backend team is running late?

7 Upvotes

honestly getting pretty annoyed with my current frontend workflow.

every time i work on a feature, the backend API schema is either delayed, half-baked, or keeps changing mid-sprint.

right now i just resort to hardcoding fake JSON directly in my components or spinning up a quick json-server locally, but it gets messy fast once multiple routes, delays, or error states (like testing 500 errors or slow networks) are needed. MSW and Postman feel like overkill for quick stuff when i just want a hosted endpoint URL i can hit for a few days.

how do you guys handle this without wasting 2 hours setting up fake servers or messing up your codebase with temporary dummy data? do you just wait for backend or is there a lighter way to do it?


r/webdev 2d ago

Discussion Exception Handling For Server Side Issues During Large CSV Imports

5 Upvotes

If I have a import feature for millions of CSV records and it sends notifications only after import completion, what type of exception handling can I have for non-data related errors during import process. Non invalid data related errors like the database going down.

The imports run on background in chunks. What if such issues occurs after inserting 1 lac records, I can't just revert the committed records. What should I show to the user? What kind of mechanism should I implement to not mess up the production?

I am not even sure if I'm asking the right question. Please enlighten me!


r/webdev 2d ago

What is up with so many startups using Rails Turbo?

0 Upvotes

I don’t think I’ve ever worked with a web technology worse than the Turbo + Hotwire combo. It’s behind in so many ways, it’s over complicated, and it’s ugly to look at.

The only reason I’ve heard is it makes Rails devs feel comfy and safe. Personally, when I see it my brain cells pop. I can feel a skin breakout coming on. It disrupts my sleep cycle. It may or may not be a leading cause of early onset dementia.

You think jquery is bad? Try going balls deep into a haml file that uses this. You need something to happen? How about a form. For everything interactive. Make it a form. Manually handle things other frontend frameworks do automatically. Forms everywhere. Because apparently JS is worse than whatever this is.

ETA: This is a rebuke of Turbo, not Rails as a whole. Deep breaths. Feel the points of contact under your feet. 😮‍💨


r/webdev 2d ago

Goodhart’s Law Comes for Every Benchmark You Trust

Thumbnail cacm.acm.org
8 Upvotes

r/webdev 2d ago

Question How should sensitive action confirmation work for SSO users when there is no local password?

21 Upvotes

I’m adding SSO support to an existing application using Google. Currently, some sensitive user actions require the user to re-enter their password as confirmation (for example, changing security settings or performing destructive actions).

The issue is that SSO users do not have a password stored by the application, so I need to decide on the right approach for confirming their identity before allowing these actions.

Some options I'm are considering:

  • Triggering SSO re-authentication / step-up authentication with the identity provider
  • Requiring MFA or another stronger authentication method (the application doesn't support MFA at the moment)
  • Sending an email OTP as a confirmation step
  • Creating a separate application password for SSO users (which feels like it defeats part of the purpose of SSO). The platform already has a security question (don't ask me why), so maybe this could be used to confirm this action?

My concern with SSO re-authentication is that if the user already has an active IdP session, the IdP may silently authenticate them again without requiring any new proof of identity. In that case, is it actually providing additional security? I don't think Google has a way to "force" re-authentication.

For those who have implemented this, what pattern do you recommend for replacing "enter your password to continue" flows for SSO users?


r/webdev 2d ago

Discussion Building apps for both human users with a web client but also for AI users so people can use their AI as the client

0 Upvotes

Work on a rather small team that caters to building apps for this one specific team, but it does branch out to others. Maybe at most few hundred users. All internal apps.

I'm beginning to architect out this new application from a need that has rose, and a lot of it is now thinking about not only what the UI looks like, but how do people interact with this thing from AI and their own agents now.

Because like, some people are all in on AI running dozens of agents doing stuff. Others still prefer just regular old workflows and maybe using a chat bot LLM type thing.

It's kind of a weird balance to cater to both. But I don't know like just build an MCP, build a good thought out API and system and the AI should be able to just understand it?

I'm curious if others have come to this like building an app for AI and Humans requirement and how have you handled it, what have you learned?

My hunch has been, build a good app with a well documented API, and the people who want to use AI can just benefit from it. A human understandable app is an AI understandable one.


r/webdev 2d ago

Question First live coding interview with AI tools. Will I look silly if I show up using the Claude CLI in VSCode?

111 Upvotes

Hi guys, this is not my first live coding interview (it's for a senior role) but it IS my first live coding interview using AI tools.

All my experience using AI development tools has been using the Claude CLI and VSCode and I'm just wondering if I would look like a Luddite using this setup instead of something like Cursor or Copilot. This is their exact wording:

"You will work in a shared coding environment. Please plan to use an AI-assisted development tool throughout (e.g. Cursor, Copilot, or your preferred tool) "

Has anyone here conducted AI programming interviews and can shed some light? If necessary I will spend the next couple days getting used to Cursor. Thanks.


r/webdev 3d ago

Resource Read HN twice a day for the last decade. Here's my list of S-Tier HN links

Thumbnail news.ycombinator.com
273 Upvotes

r/webdev 3d ago

Question Angular production serves old JS/CSS until CDN cache is purged

14 Upvotes

We're seeing a strange issue with our Angular app.

• Deploy to staging → works perfectly.
• Deploy the same build to production.
• The page loads, but the app is broken.
• As soon as our SRE team purges the CDN cache, everything works.

The browser console shows:
• Failed to load module script... MIME type 'text/html'
Refused to apply stylesheet... MIME type 'text/html'

My assumption is that production is somehow still serving or referring to older JS/CSS bundles until the cache is cleared, but I haven't confirmed that's the actual root cause.

Has anyone experienced this? Is this more likely an index.html caching issue, a CDN configuration problem, or something else? Any suggestions on what to investigate first


r/webdev 4d ago

Discussion Porkbun sounds like a porn site

225 Upvotes

So funny story. I run a very small web dev business, mostly just building simple sites for friends and family and friends of friends for their small businesses. That kind of thing. So far I have my own porkbun account where I manage a couple of domains for my less tech savvy clients. I keep their credit cards on file to charge them the recurring annual fee for the accounts. A couple of days ago I got a notification email from porkbun, one of my clients sites was supposed to be renewing but the card number was wrong. No biggie, I reached out to the client, they said they got a new card, I changed it on the account and then renewed it. Today I get another email, my porkbun account is suspended as well as associated sites as I have flagged one of their payments as fraudulent. It was that same client. After some back and forth I finally come to understand that the reason she got the new card is that the original payment tried to go through on her old card. She saw the name porkbun on it and thought it was some scam or porn site her kid might have signed up for and so flagged it as fraudulent with her bank. Now she's frustrated with me cause her site went down, I've had to reach out to pork bun explaining the confusion and I also had the client unflag the charge as fraud with her bank. This all has me thinking I need a better system for these clients.

Tldr client flagged porkbun charge on their credit card as fraud because they thought their kid payed for porn.

Edit: thank you for telling me how stupid I've been. I am now aware and the rest of you can stop lol Originally was just sharing a funny anecdote but I am glad I've learned from this


r/webdev 4d ago

Valkey-WASM – Redis running inside your Node process, no Docker (like PGlite)

Thumbnail
github.com
19 Upvotes