![]() |
![]() |
![]() |
Have you ever asked yourself how your phone shows you that login page upon connecting to a public wifi? Well, I did.
That question turned into an 8 month project.
The idea was simple, what if strangers could share their artwork, videos, and music with people around them using nothing but a wifi connection? Not having to give their names, emails, not even setting up a password. But they still have an account, so they can delete their media or retrieve it later.
And I wanted to give them a unique experience. Something that looks weird enough but still lovable. So I went with a modern matrix theme, a CRT scanlines effect, and a deterministic profile picture generator that gives each user a uniquely generated avatar tied to their id.
How the captive portal works
Turns out it's pretty simple.
Android phones send a GET request to connectivitycheck.gstatic.com/generate_204 and expect a 204 No Content response. If the wifi has internet, Google responds with 204 and your phone knows it's connected. If it couldn't reach that url at all, you get the "No internet connection" popup.
But what if that page replied with 302 Found instead? Your phone thinks there's some sort of auth mechanism and shows you a popup that says "Sign in to Wi-Fi network". Some phones just open it in webview without you even asking.
Each OS has its own url and expected response:
Android: connectivitycheck.gstatic.com/generate_204
iOS/macOS: captive.apple.com/hotspot-detect.html
Windows: www.msftconnecttest.com/connecttest.txt
So I just made routes for all of them inside FastAPI that always return 302 Found. And since the device running this is the network itself, I used dnsmasq to intercept those OS specific urls and point them to our server ip instead.
That's literally it. That's the whole trick.
The stack
Built with Python, FastAPI, SQLAlchemy, and a fully vanilla HTML/CSS/JS frontend — no frameworks, because I wanted it to run on anything that can open a browser. This was my first time writing HTML, CSS and JS.
Running on a Raspberry Pi Zero 2W. I already included a flashable .img.gz in the releases if you just want to try it out.
Live preview: https://rematrix.remohexa.com
Repo: https://github.com/remohexa/rematrix-gallery



Top comments (0)