iTranslated by AI
I Lost My Shoes, So I'm Building an App Vol. 1: What Does It Mean to Lose Shoes?
I Lost My Shoes
Today, I lost my shoes. I wonder how many people have someone close to them who has lost their shoes. More than the fact that my shoes are gone, I'm disappointed in the fact that I lost them. I've been abroad three times, and I've lost my passport every single time. I also lost a necklace my wife gave me for our anniversary. When I lost that necklace, I took off my wedding ring and gave it to my wife to keep. Because I knew I would definitely lose it. During a business trip to Tokyo last week, my wife wanted me to wear the ring when I went far away, so I wore it. On the Shinkansen back, it felt a bit tight, so I put it in my bag. Remembering that now, I am deeply relieved that the ring isn't missing.
That’s how bad my forgetfulness is. Lately, many people call themselves ADHD, and I often think, "don't say that so lightly," but I might actually be one. By the way, I even booked a hospital appointment to get an ADHD diagnosis once, but I forgot about it and skipped it. I don't think of myself as having ADHD, but it's a fact that my forgetfulness is severe.
And I'm going to Bali in November. Alone. The last time I went to Thailand, I lost my wallet and my passport. In other words, there's a very high possibility I'll lose something this time too. Or rather, I will lose something. Definitely.
So, I Decided to Make an App
What I want is an app that periodically sends notifications from my smartphone to check if I've lost anything. Just notifications is enough. That alone makes a big difference. In my experience, the more time passes after losing something, the harder it becomes to find. I can't even remember the path I walked. This app isn't to prevent losing things, but to increase the chances of finding them when I do.
By the way, when I lost my wallet in Thailand, more than half a day had passed since I lost it, so it was impossible to search everywhere I had moved. Miraculously, it was found, though...
I also thought about ways to prevent losing things, but it's quite tough. It would basically require me to do some kind of brain training to improve my forgetfulness. Software can't do much about that. Similarly, I could attach AirTags to everything, but that's tedious and gets expensive.
Why Write an Article?
The most important thing to avoid in personal development is quitting halfway through. It's a waste since I'm using my precious private time. I've written an article summarizing that in the past.
I don't know if anyone will see this, but by making my progress public, I want to lower the probability of giving up, even if only slightly. The reason I'm writing on Zenn is that I'll also be writing about technical stuff. Also, writing itself is a hassle, so I wanted to use the power of GitHub Copilot to some extent, which is why I'm writing this from VSCode right now. This might turn into an article that feels like a stream of scraps, but please bear with me.
After all, I quite like seeing the process. I'm more intrigued by articles saying "I'm making this~" rather than "I made this app!".
I hope it finishes in about 5 installments.
Today's Goal: Technical Investigation of Scheduled Push Notifications
The part that needs investigation is how to let users decide the interval for scheduled execution. I have no issues with the methods for push notifications or building native apps, as I've implemented them in the past.
Normally, you can just use cron for scheduled tasks. However, I want to allow users to set the interval for these scheduled executions themselves. For important items, every hour; for less important ones, every three hours, and so on. Also, I want to avoid sending notifications at night. The idea is that during a trip, at intervals set by the user, a notification like "Hey [Name], have you lost your wallet?" will arrive. Of course, I only want this to be active during the trip.
For this session, I will investigate the method of sending push notifications using cron.
This Time's Tech Stack
Before diving into the investigation, here is the tech stack I'm currently considering:
- FE:
ReactNative+Expo - BE:
Denois the leading candidate - DB: TBD (Something that pairs well with Deno)
For notifications, Expo provides an API, so I'll use that. For the backend, anything works, and I actually wanted to use Rust, but deployment is a hassle. I've deployed to Vercel before, but their cron service isn't very useful on the free plan—logs only last an hour, and it can only run once a day. Cloud Run + Cloud Scheduler could be used almost for free, but it's a pain to set up. I want something easier to configure. So, I'm going to try using Deno. If that doesn't work, I'll rely on Google Cloud.
By the way, I'm the author of the Rust crate expo-push-notification-client-rust, so feel free to contribute! (A sudden plug)
Investigating How to Use Cron in Deno
I'll proceed while looking at the official documentation.
OMG, I thought I'd start by setting up a web server, deploying it, and then sending requests to that endpoint with cron jobs, but apparently, that's not necessary.
On Deno Deploy, our multi-tenant distributed serverless JavaScript platform, Deno.cron() is automatically detected and managed so you don’t need to worry about anything.
You can run cron jobs without a web server or even consistent incoming requests to keep your isolate alive. That’s because whenever your project is deployed, Deno Deploy automatically detects your cron jobs and evaluates them. When its time for your handler to run, Deno Deploy automatically spins up an isolate on-demand to run them.
I thought this when I made a package on JSR too, but isn't Deno amazing? The end of Node might be near.
Deno.cron("Log a message", "* * * * *", () => {
console.log("This will print once a minute.");
});
I deployed this, and it just worked. I don't know if this counts as an "investigation," but I've confirmed that I can use cron with Deno.
Since things are going too smoothly, I'll try sending a push notification with Deno's cron.
Investigating How to Send Push Notifications with Deno
Well, even though I call it an investigation, it's really just about calling an API. Since I haven't built the client side yet, I don't have a token, but I'll test it using an app I previously made for my wife.
Deno.cron("Push notification", "* * * * *", async () => {
console.log("This will push a message to your device every minute.");
const pushMessage = {
to: "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
title: "hello",
body: "world",
};
try {
const response = await fetch("https://exp.host/--/api/v2/push/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(pushMessage),
});
if (!response.ok) {
console.error(
"Failed to send push notification:",
response.statusText,
);
} else {
console.log("Push notification sent successfully!");
}
} catch (error) {
console.error("Error sending push notification:", error);
}
});
It worked without any issues. This is sufficient, but since there is an Expo Server SDK, I'll try using the npm package from Deno.
import { Expo } from "expo-server-sdk";
const expo = new Expo();
Deno.cron("Push notification", "* * * * *", async () => {
const pushToken = "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]";
if (!Expo.isExpoPushToken(pushToken)) {
return;
}
const messages = [{
to: pushToken,
title: "hello",
body: "world",
}];
try {
const chunks = expo.chunkPushNotifications(messages);
for (const chunk of chunks) {
await expo.sendPushNotificationsAsync(chunk);
}
} catch (error) {
console.error(error);
}
});
Everything is going far too smoothly. I feel like I'm already about half-finished. Next time, I'll investigate the database or ways to send notifications at user-defined intervals.
See you later :)
References
Discussion