Inspiration

I got the inspiration from social media videos where people randomly realize that they have free will, and starts doing random silly things such as eating instant noodles while squatting on top of the table. As our lives get busier, it gets harder to live in the present moment, and we forget that we can control how we live our lives. We're always moving on to the next thing, to the next day, and not really enjoying our days to the fullest, or taking time to ensure our wellbeing. What if we were assigned quests that are made for us to relax and detach from the world for a few moments?

What it does

Wander EarthOnline simulates a retro, cyberpunk world, where you, as an Earthling, make acquaintance with a fallen star Pip, and take on a special mission assigned by The System starting today. The mission: to be happy. Every day, new low-pressure quests are assigned to you by The System that fall under 5 categories: Growth (personal growth), Body (physical health), Bond (relationships with others), Sanctuary (taking care of your living and mental spaces), and Wonder (something whimsical, silly and random). Complete quests to gain EXP and level up. The reward? Happiness! You can also assign quests to yourself, where you choose the category and amount of EXP as you see fit. Assign it for the day or for tomorrow. You can log your thoughts in the Quest Book, which serves as your journal. Use the journaling prompts or freestyle.

How I built it

I used Claude Code to help design the React UI framework, by giving it prompts and keywords, then I added individual components one by one on top of the existing model, testing and refining it as I go. Wander is a client-side single-page application, meaning that all data is locally stored on the user's browser, with no server, database, or backend. The HTML page is rendered once only so everything is instant. I made a pool of side quests to be chosen from randomly, with a few from each category. To help with journaling in the Quest Book, I also made a pool of journaling prompts that displays when the Quest Book is opened, serving as inspirations. At first, simple math couldn't effectively influence the index of the category to make it so that consistent completion of quests ensures an increase in happiness index, so a more complicated statistics model was used to calculate the category index. Each of the five categories holds a value $v_c \in [0, 10]$ (everyone starts at 5), and the happiness index is just their average. Completing a quest calls the function 'boostValue', which increases the index of that quest's category by a fixed amount based on its EXP tier (clamped to 10). $$v_c \leftarrow \min!\big(10,\; v_c + b(\text{exp})\big), \qquad b(20)=0.5,\; b(40)=0.85,\; b(60)=1.25$$ The category index decreases through 'applyNeglectDecay': it sustains for a grace window of $G = 3$ cycles, then loses $0.6$ per cycle after (floored at 0). If a category has been idle for $n$ cycles, the drop in its index is: $$v_c \leftarrow \max!\big(0,\; v_c - 0.6 \cdot \max(0,\, n - G)\big)$$

Challenges I ran into

Since I decided not to use a server, I had to somehow ensure the users across the web receive the same side quest assignment. The only factor that is the same for all users is the date or cycle, so I based the assignment of side quest using a deterministic seeded random number generator seeded by the date. This allows users across the web to receive the same side quests even without a server. The daily summary wouldn't show up if there was a main quest assigned. Completing a cycle is supposed to show a recap before the new quests, but it skipped the recap whenever I inscribed a main quest for the next day. Advancing to the next cycle would flag "there are quests to assign" one render before the recap was ready, so the popup opened too early and locked into the wrong screen. I fixed it by only opening the popup once the recap exists and deriving the screen from the data rather than a one-time initial value. Showing the journal as a calendar was a pain. First, the calendar wouldn't render when the journal was empty (it checked for zero entries before checking the active view), then my first day-cells were so tall they pushed the day's entries off-screen, and I had to bucket entries by local date so notes written near midnight didn't jump to the wrong square. Fixing them meant scoping the "empty" message to the list view, switching the cells to a compact fixed height, and being consistent about local time.

Accomplishments that I'm proud of

Shipped a complete, polished product solo. Built an original and aesthetic look entirely from code. Made the daily quests the same for everyone, with no backend. Gained more experience and knowledge of React + TypeScript.

What I learned

There are more complications than expected when making an application, all sorts of things can go wrong and sometimes the original plan will no longer work. Starting early and having ample time to thoroughly test and refine each feature is critical. Instead of going for more features, starting with less but well-made ones is more important. Quality over quantity. There is more satisfaction of accomplishment from doing something well than doing more things but poorly. Having a clear goal (my priority of everything rendering instantly) helps a lot with refining the prototype.

What's next for Wander EarthOnline

Introduce a collaboration feature where users can complete quests with other users and cheer each other on their wellness journey. This will make the app more complicated by introducing accounts, integrating backend and more animations/UI features that support social features.

Built With

Share this project:

Updates