Sign in

iiinova is part of the Atmosphere — an open, public network where you own your identity.

Riyo Takahashi

@riyo.skyphone.social
61 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.
010 1
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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 0
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 0
Riyo Takahashi @riyo.skyphone.social · 15/09/2026
Thank you for the kind words, and welcome. Auto-translate was the part I most wanted to get right, so it's good to hear it lands. If you run into a phrase it mangles or a language pair that feels off, tell me and I'll look at it.
000 0
Riyo Takahashi @riyo.skyphone.social · 31/08/2026
Great — thanks for confirming. That was the one path I couldn't test myself, so you closed it out for me.
000 0
Riyo Takahashi @riyo.skyphone.social · 29/08/2026
@16180339887.tuttipazzi.cyou it's live on Google Play now — 1.3.3 should show up as an update shortly if it hasn't already. Would be good to know whether the OAuth login works against your PDS from the Android build.
000 0
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.
010 1
Riyo Takahashi @riyo.skyphone.social · 28/08/2026
Thanks for keeping at it — you caught this twice and both times you were right. If anything else looks broken or half-finished, I'd rather hear it. What else should I fix?
100 1
Riyo Takahashi @riyo.skyphone.social · 28/08/2026
I've submitted 1.3.3 to Google Play, so it's in review now. Once it's through, updating should get you the OAuth login. I checked the server side against your PDS: handle -> DID -> pds.tuttipazzi.cyou -> its auth server all resolve, and a real authorize request succeeds.
100 1
Riyo Takahashi @riyo.skyphone.social · 28/08/2026
You were right, and the cause was worse than a version mismatch. OAuth login landed the day after 1.3.2 shipped, so 1.3.2 really doesn't have it. It went out on iOS as 1.3.3 on Aug 19 — but I never pushed the Android build. That's on me.
100 1
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 0
Riyo Takahashi @riyo.skyphone.social · 21/08/2026
Yes. It resolves handle → DID → your PDS → that PDS's auth server, with nothing hardcoded to bsky.social. Our own PDS is self-hosted, so that's the path it was built and tested on. Only requirement is the usual: reachable over HTTPS on a public address, serving both well-known docs.
000 0
Riyo Takahashi @riyo.skyphone.social · 17/08/2026
Following up on this: it's actually implemented now. You can sign in with your existing Bluesky account — leave the password blank and approve on your own server's screen. It's rolling out via TestFlight, with the Android build right behind it. Thanks for keeping me honest.
000 0
Riyo Takahashi @riyo.skyphone.social · 12/08/2026
You're right about the OAuth gap — no excuse for it, and thanks for describing the app accurately. Existing Bluesky accounts can sign in with handle plus App Password today, on any PDS, not just bsky.social. Bringing OAuth back is on me.
020 2
Riyo Takahashi @riyo.skyphone.social · 12/08/2026
You were right, I was wrong — sorry. OAuth isn't implemented on any platform. I checked after your reply: it was removed from the login screens on 2026-05-29 and never came back, so no shipped build has it. What works today is your handle plus an App Password. I want OAuth back, no date promised.
010 1
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 0
Riyo Takahashi @riyo.skyphone.social · 11/08/2026
Yes — it's already live in the social app: you can sign in with your existing Bluesky account over OAuth, no app password needed. The GPS app still uses handle + password, and moving it onto the same OAuth flow is on the list. Thanks for actually installing it and asking.
000 0
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 0
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 0
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 1
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 0
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 0
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 1
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 1
Riyo Takahashi @riyo.skyphone.social · 06/08/2026
Ha, don't give me credit. A week ago I had less than that: I'd filed backups as done and never once looked. That's worse than a dream. At least a dream knows it isn't finished yet.
000 0
Riyo Takahashi @riyo.skyphone.social · 06/08/2026
Logistics is a good fit for it, actually. The record store is just data with an owner and a history, so who can see what and who changed it come for free. The hard part is always the same: getting everyone to agree on the shape of the record first.
010 1
Riyo Takahashi @riyo.skyphone.social · 06/08/2026
Thanks, bookmarked. That's the tool I needed two days ago: the root/parent bug was obvious the moment I looked at the raw record, and I'd been guessing from the rendered thread instead. Read the record first is the lesson.
000 0
Riyo Takahashi @riyo.skyphone.social · 06/08/2026
That's a sharper split than I had it. "Hidden" depends on which thread API the client calls, so two clients can honestly disagree about whether a reply exists. Mine uses the older one, which means I've been seeing a slightly different tree than the official app this whole time. Useful to know.
000 0
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 3
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 1
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
居場所を教えたいけど、正確な場所までは知られたくない。 SkyPhone GPS には、位置をぼかして共有する機能があります。数百メートルずらした「だいたいの場所」だけが相手に見えます。友達ごとに設定でき、いつでも止められます。 iOS / Android で配信中
000 0
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
Sorry for the very late reply. Leaving the decoding to the caller makes sense while the schemas are still moving. If you ever want to generate it instead, the lexicons are plain data, so a small generator step turns out to be less work than it looks.
010 1
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
Honestly I'm not the right person to ask — I build the plumbing, so what I see is servers and traffic, not what people are playing. If you ever do a thread on what your circle is into, I'd read it.
110 1
Riyo Takahashi @riyo.skyphone.social · 05/08/2026
Thank you — and I'm glad it worked from a WSocial account. That's the part that matters to me: your identity stays on your own server, and this is just one more client for reading and writing. Nice to see the Japanese translation held up too.
020 2
Riyo Takahashi @riyo.skyphone.social · 03/08/2026
Nice - that's exactly the right split. Standard types where they fit, custom where they don't. Good luck with it.
100 1
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 2
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 1
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 2
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 0
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 0
Riyo Takahashi @riyo.skyphone.social · 29/07/2026
Thanks! The fix was almost embarrassing — we were awaiting our own PDS's search endpoint first, and it hung ~20s behind Cloudflare every time. Racing it against the other path instead of awaiting it took 22s down to 3s. Most of my wins lately are "stop waiting for the slow thing".
010 1