Sign in

Riyo Takahashi

@riyo.skyphone.social
60 followers 28 following 195 posts

Solo dev from Japan 🇯🇵 building on atproto. Creator of SkyPhone (12M+ installs).

PostsRepliesMedia
Riyo Takahashi @riyo.skyphone.social · 19/09/2026
Counted the calls my app makes to server functions: 81. Number with a time limit on them: 1. On a good network you never find out. On a train you get a screen that spins forever with no way back. A timeout isn't a feature, it's the difference between slow and stuck.
000
Riyo Takahashi @riyo.skyphone.social · 18/09/2026
Found the worst one by asking a dumb question: which screen does every single user have to pass through? Email confirmation. It's Japanese only. Password reset - the same mechanism, same kind of screen - speaks five languages. The one mandatory step is the one nobody translated.
000
Riyo Takahashi @riyo.skyphone.social · 18/09/2026
Audited my own app from eight angles in one day. 76 findings, each re-checked independently of whoever raised it: 58 survived, 18 did not. My favourite: a moderation flag that eight different queries filter on, and that no code anywhere ever sets. Purely decorative safety.
000
Riyo Takahashi @riyo.skyphone.social · 18/09/2026
18.6% of my 9,470 test assertions match source text rather than behaviour. So I made copies of the code that were semantically broken but textually intact. The guards for message read state and for login both stayed green. A test that reads your code instead of running it defends nothing.
000
Riyo Takahashi @riyo.skyphone.social · 17/09/2026
My shared CI was red three runs in a row and I had stopped looking. The cause was one test with an absolute path from another checkout baked into it. A red build you have learned to ignore is worse than no build at all: it teaches you that the colour means nothing.
000
Riyo Takahashi @riyo.skyphone.social · 17/09/2026
The call that tells the server "I read this" swallowed its own failures and always resolved successfully. So my error handling never ran: on a flaky connection the row looked read forever while the server still counted it unread. It returns true or false now, and false rewinds the cursor to retry.
000
Riyo Takahashi @riyo.skyphone.social · 17/09/2026
I compare those read marks as epoch milliseconds, never as text. An older version compared timestamps as strings, and one value that had lost its microseconds sorted below the real newest message - so that message stayed unread forever. I don't sort time as text anymore. Ever.
000
Riyo Takahashi @riyo.skyphone.social · 16/09/2026
Opening a conversation cleared its unread mark 15-20 seconds later, on the next poll. Now the instant the read registers, I write a local "read up to here" line and the inbox subtracts it right away. Anything that arrives after that line stays unread. It's a floor, not a mute button.
000
Riyo Takahashi @riyo.skyphone.social · 16/09/2026
What made it hard to see: every caller turned a failed fetch into "nothing there". No error on screen, ever. Just a missing button, a follower count of zero, a profile with no posts. Absence and failure look identical unless you go out of your way to keep them apart.
000
Riyo Takahashi @riyo.skyphone.social · 16/09/2026
Of the 288 repositories on my server, 23 still name a hostname I retired months ago in their identity document. The data is all on the current host - same machine, new name. So I rewrite that one dead name where the value enters, and only that one. Anything that merely looks similar is left alone.
000
Riyo Takahashi @riyo.skyphone.social · 15/09/2026
Some profiles on my own server showed zero followers and no posts. My first theory was my browser's connection policy blocking a host, so I allowed it, and nothing changed. That host no longer exists. Gone from DNS entirely: no A, no AAAA, nothing, on two separate resolvers.
000
Riyo Takahashi @riyo.skyphone.social · 15/09/2026
My dev diary is posted by a scheduler: rows in a table, a job every five minutes, one post per tick. It ran 2,023 times this week and did nothing at all, because I stopped filling the table on Aug 8. The machine was healthy the whole time. I was the broken part.
000
Riyo Takahashi @riyo.skyphone.social · 29/08/2026
SkyPhone Social 1.3.3 is out. You can now sign in with your existing Bluesky account. No app password — you approve it on Bluesky's own screen. Self-hosted PDS works too. Android was late: I built it and forgot to push it. A user had to tell me. iOS has had it since Aug 19.
021
Riyo Takahashi @riyo.skyphone.social · 24/08/2026
SetLive 1.0.6 is out on iOS and Android. Cold start: 7.5s → 1.0s. Fixed: when your connection dropped mid-broadcast, the app went audio-only and your own camera froze too. Now only the outgoing stream is throttled — your own view keeps moving. setlive.skyphone.social
000
Riyo Takahashi @riyo.skyphone.social · 12/08/2026
SkyPhone Social 1.3.2 is out. An incoming message used to take 3.3 seconds on average to show up. It now takes 0.35. Your own messages appear the instant you hit send. It changes how a conversation feels. iOS, Android and web.
000
Riyo Takahashi @riyo.skyphone.social · 10/08/2026
SkyPhone GPS 1.3.0 is out. Messages now arrive much faster. What used to take several seconds now lands in about 0.3 seconds. It changes how a conversation feels. Available on iOS and Android.
000
Riyo Takahashi @riyo.skyphone.social · 08/08/2026
Rate-limited my view counter per viewer: 1000 new posts a day. Then realised the viewer comes from the connecting address when nobody is logged in. Change the address, get a fresh allowance. Unlimited became "unlimited per exit node". Added a global daily cap on first-ever rows.
000
Riyo Takahashi @riyo.skyphone.social · 08/08/2026
I blocked cross-site writes to my counting endpoint by rejecting Sec-Fetch-Site: cross-site. Counting stopped completely in production. The endpoint is on a different domain, so my own app is cross-site to it. I had only tested by setting the header by hand, which no real browser does.
010
Riyo Takahashi @riyo.skyphone.social · 08/08/2026
A post with an image is often taller than the screen. If "visible" means "half of the element is on screen", those posts can never qualify — it is structurally impossible. My viewport was 665px, the tallest post 1044px; 15 of 122 could never be counted. Now: half the element, or enough pixels.
000
Riyo Takahashi @riyo.skyphone.social · 08/08/2026
Fixed a bug where post views were never counted. Then my fix reopened it. React calls a ref with null before attaching a new one whenever the callback's identity changes. My feed re-renders on every translation, so the dwell timer was thrown away each time. Zero counts at 300ms, 700ms and 900ms.
000
Riyo Takahashi @riyo.skyphone.social · 08/08/2026
Added view counts to my posts. atproto has no field for this — Bluesky returns likes, reposts, replies, quotes and bookmarks, and nothing else. So the number can only be what my own clients see. Counting it myself meant deciding who "a viewer" is when most of them aren't logged in.
010
Riyo Takahashi @riyo.skyphone.social · 07/08/2026
SkyPhone GPS 1.2.9 is out. - Account deletion now spells out exactly what gets removed before you confirm - The app icon badge clears when nothing is unread - Startup and map fixes Available on iOS and Android. gps.skyphone.social
010
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
SkyPhone Social 1.2.9 is out. - Browse videos in the app: new, popular, search, by author - Suggested people to follow - Shared links now open the app - Follows your device's dark mode - Fixed: video uploads, and posts not opening from notifications Available on iOS and Android.
030
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
Want to share where you are, but not exactly where you are. SkyPhone GPS lets you share your location as an approximate area. Your friends see a point a few hundred meters off, not your real position. You choose who sees what, and you can stop anytime. Available on iOS and Android.
010
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
居場所を教えたいけど、正確な場所までは知られたくない。 SkyPhone GPS には、位置をぼかして共有する機能があります。数百メートルずらした「だいたいの場所」だけが相手に見えます。友達ごとに設定でき、いつでも止められます。 iOS / Android で配信中
000
Riyo Takahashi @riyo.skyphone.social · 03/08/2026
SkyPhone Social 1.2.8 is out — stability improvements and minor bug fixes only. 1.2.9 is on the way.
020
Riyo Takahashi @riyo.skyphone.social · 30/07/2026
Wrote a test that asserted "still sets the badge when the current value can't be read". It passed. It was also checking nothing — the function returned undefined either way. Rewrote it to assert the call actually happened; it failed immediately. A green test you didn't watch fail is not a test.
010
Riyo Takahashi @riyo.skyphone.social · 30/07/2026
Nastiest bug today: on Android, passing 0 to the badge API doesn't zero the badge — the library calls cancelAll() and empties the whole notification shade. My poll runs every 30s, so an empty inbox would have wiped likes and replies twice a minute. Found it in the source before shipping.
020
Riyo Takahashi @riyo.skyphone.social · 29/07/2026
SkyPhone GPS 1.2.6 is out. - New: share your location as an approximate area (shifted by a few hundred meters) - Post pins now follow your location sharing setting - Account deletion removes more of your data, plus other fixes Available on iOS and Android.
000
Riyo Takahashi @riyo.skyphone.social · 29/07/2026
Built an unread count for the app icon, then deliberately didn't ship it. The server sends the number inside push notifications — but the code that clears it wasn't on anyone's phone yet. Ship the increment before the decrement and you hand people a number that never goes away. Still holding.
000
Riyo Takahashi @riyo.skyphone.social · 28/07/2026
kaiki test moji dake
000
Riyo Takahashi @riyo.skyphone.social · 28/07/2026
kensho2 chuudan saikai skyphone.social/video/did:plc:ta347…
skyphone.social
kensho2 chuudan saikai
000
Riyo Takahashi @riyo.skyphone.social · 28/07/2026
kensho1 douga A skyphone.social/video/did:plc:ta347…
skyphone.social
kensho1 douga A
000
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
Sobering realization: my entire federation identity — every account, every post — lived on one VPS with zero backups. Now: daily snapshots, 14 generations, tested restore path, all shipped to a second server. If you self-host a PDS, check your backups today.
3250
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
My current workflow: AI writes the fix, then I spawn 30+ adversarial AI agents to attack it — each finding gets a "refuter" agent trying to disprove it. 3 rounds, 65+ claims, 47 confirmed real. The scariest bugs were in the fixes themselves. Trust nothing, verify everything.
030
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
Bluesky is impressive — a decentralized SNS that's still pretty niche in Japan. People tend to see it as "an X clone," but I think its real core is the tech underneath: the AT Protocol. 🧵1/6
100
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
SkyPhone Social 1.2.7 is out. One month of progress: ・Search: 22s → 3s ・Images, quote posts, and link cards ・Per-type notification settings, and swipe right to go back on any screen ・Fixed random logouts and notifications that never arrived Next up in 1.2.8: video posting in the app.
110
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
Counted lines out of curiosity: 91k in the main repo, 51k of it TypeScript and 26k SQL migrations, 152k across all repos. Written almost entirely by AI, audited adversarially by AI, directed by one human. The bottleneck isn't writing code anymore — it's deciding what's true.
020
Riyo Takahashi @riyo.skyphone.social · 25/07/2026
Our push notifications kept dying "randomly" for weeks. Root cause: expired sessions come back as HTTP 400 with a "token expired" body, not 401 — and our refresh logic only listened for 401. Every user's polling silently died until someone happened to post. One status code. Weeks of ghost bugs.
010
Riyo Takahashi @riyo.skyphone.social · 24/07/2026
長尺テスト(自動生成カラーバー4分) skyphone.social/video/did:plc:ta347…
skyphone.social
長尺テスト(自動生成カラーバー4分)
通し検証用。すぐ削除します。
000
Riyo Takahashi @riyo.skyphone.social · 24/07/2026
長尺テスト(自動生成カラーバー4分) skyphone.social/video/did:plc:ta347…
skyphone.social
長尺テスト(自動生成カラーバー4分)
通し検証用。すぐ削除します。
000
Riyo Takahashi @riyo.skyphone.social · 24/07/2026
長尺テスト(自動生成カラーバー4分) skyphone.social/video/did:plc:ta347…
skyphone.social
長尺テスト(自動生成カラーバー4分)
通し検証用。すぐ削除します。
000
Riyo Takahashi @riyo.skyphone.social · 23/07/2026
テスト
010
Riyo Takahashi @riyo.skyphone.social · 19/07/2026
upside of running my own Bluesky infrastructure: I extended the analysis tool to Bluesky accounts too. unlike the X side, which pays a data provider per pull, reading Bluesky posts costs me nothing. same pipeline, zero marginal cost. small reward for owning your stack.
120
Riyo Takahashi @riyo.skyphone.social · 19/07/2026
analytics honesty, part 2: for low-posting accounts, the free timeline returns all-time top posts, not recent ones. compute "best time to post" from that and you're really just measuring when their viral posts landed. so now I detect it and hide the misleading stats.
010
Riyo Takahashi @riyo.skyphone.social · 19/07/2026
debugging war story: some analyses silently failed to cache. my sanitizer trimmed text to a max length by raw character index, and that cut a string in the middle of an emoji — leaving half a surrogate pair. the database quietly refuses to store that. one dangling half-emoji killed the whole save.
010
Riyo Takahashi @riyo.skyphone.social · 18/07/2026
cost lesson I didn't expect: my paid data provider charges ~315 credits for a good pull and ~915 for a failed one — failures cost 3x. an outage doesn't just break things, it drains the balance faster. added hard caps on failed attempts so a bad day can't empty the account.
010
Riyo Takahashi @riyo.skyphone.social · 18/07/2026
today's gotcha: I had two ways to keep pages out of search on the same pages — a crawler block and a noindex tag — assuming they'd stack. they cancel out. a blocked crawler never loads the page, so it never sees the noindex, and can still list the bare URL. keep one, not both.
110
Riyo Takahashi @riyo.skyphone.social · 18/07/2026
shipped a free tool this week: paste in an X handle and an AI reads the posts, then tells you what your followers actually show up for. didn't expect much. it ran ~450 analyses in a day and a half — most people testing it on Elon, NASA, Google first, which was funny to watch.
010
Riyo Takahashi @riyo.skyphone.social · 16/07/2026
a two-layer cache bug ate three days: x caches link-card images by image url, separately from the page card. we redesigned our card but kept the same image url — so x served the old design forever. lessons: change the url when you change the image, and look at the screenshot before blaming caches.
020