Jason Leow

Indie hacker, solopreneur | Creating a diverse portfolio of products + services.

Day 61 - Biohacking sleep: Mouth taping, daylight alarms, coffee naps https://golifelog.com/posts/biohacking-sleep-mouth-taping-daylight-alarms-coffee-naps-1614675237201

Been pretty happy with my recent experiments in biohacking sleep:

* taping mouth to prevent mouth breathing, to enable less snoring, better sleep quality
* daylight alarms that use light to wake you instead of sound
* taking coffee right before my post-lunch power naps

Created new Carrd clone template for a simple scroll to top button

https://scrolltotop.carrd.co/

Organic sharing/marketing on Twitter

The more I try this Twitter marketing thing, the more I realise... I just wanna chat with strangers on my hobbies/passions. Not market/sell them things.

😪 OK managed to integrate my @mention autocomplete component into the page itself

Would have loved to keep it separate as a component but I'm not keen to delay launch any further by wrangling with v-model and $emitting events all so to ensure the parent talks properly to the child component. So it'll be messy to manage so much code on a single vue file, but refactoring can come later. It's tech debt, but so be it – maintaining DX and motivation is more important at this stage.

And even as I solved integration, another 2 edge cases/bugs pop up.

* my current regex can't read the white space that gets created when a word wraps to the next line. So if you're typing a long comment, the @mention tooltip will start to inch 'backwards' from where your cursor is. Not great UX, even if users can still use the function.
* if you're typing a particularly long comment and scroll back up to the top of your comment, the 'bottom' of your comment will extend out beyond the footer of the website. Again, still works, but annoying!

Day 60 - Moolah March https://golifelog.com/posts/moolah-march-1614585474763

All those habits I started in Fund Feb were great, and something I will continue with. But they were all but just a start. The tone of this month is meant to be more serious, so it won’t suffice to just “do 1 task” or say positive affirmations to oneself. I’m looking for tangible results, no matter how small. A dollar that I can attribute to all the marketing and monetization efforts, is “tangible”. But a one-off $1 is under-shooting a bit, so to aim slightly higher and feel more challenged, I’m shooting for these goals:

Acquire at least 2 new subscribers for Lifelog
Sell at least 2 copies of a Carrd clone template for Plugins For Carrd
Get at least 2 web design projects for Sweet Jams Sites

Why two? Because I might be lucky one time, but to be lucky twice is harder, and a better gauge that the marketing and monetization efforts are working. If I fail, so be it. But the challenge is to challenge myself seriously.

Onwards to Moolah March!

Day 59 - Fund Feb wrap-up https://golifelog.com/posts/fund-feb-wrap-up-1614518844147

I’m glad to have done this review – I’d actually done a lot it seems, even though it didn’t feel so. I think that’s why it’s important—for me at least—to do this faithfully every month, because I’m my own worst critic. The kind of perpetually grumpy, unreasonably demanding critic that never has anything nice to say, even if warranted. Such reviews help me silence that critic for a while, and gives a more accurate assessment of the reality.

It was a great Fund Feb for sure! But I don’t think I’m done with money yet.

Onward.

😪 Integrating my @mention autocomplete component from Codepen to my Nuxt app is yet another wall! @nuxt

Pareto's a bitch - the last 20% takes up 80% of the time. I thought I was f**king done when I completed my component in Codepen, but nooo. Due to how the component takes measurements from elements, I got to REDO the calculation bit based on the HTML structure of my Nuxt app (which is more complex than just a Codepen), with hidden gotchas like Bulma classes etc.

🤑 Received confirmation for 6 mths banner ad and 6 months boosted ad from Blyss Foods

Day 58 - Asymmetric opportunities https://golifelog.com/posts/asymmetric-opportunities-1614414938869

They were talking about doing or investing in things that have asymmetric risk – huge upside, limited downside. Basically, huge potential of getting a lot on returns of your investment, with a controlled degree of risk of failure that you can easily walk away from without total personal ruin. Who doesn’t like that?

Things that were mentioned, like:

Writing a book, podcast, video
Investing in a startup
Starting a startup
Investing in the stock market, Bitcoin
Creating software
Go on many first dates
Move to a big city
Tweet
Investing in good health
Investing in travel

Just transferred 12 Carrd (accordion dropdown and pricing tables) templates out - they really looove them templates! Sweet Jam Sites

Day 57 - Reinventing yourself beyond recognition https://golifelog.com/posts/reinventing-yourself-beyond-recognition-1614324582492

Poet Diane Ackerman on reinventing yourself, in Cultivating Delight:

“Living things tend to change unrecognizably as they grow. Who would deduce the dragonfly from the larva, the iris from the bud, the lawyer from the infant? Flora or fauna, we are all shapeshifters and magical reinventors. Life is really a plural noun, a caravan of selves.”

😵 F**KING FINALLY. The DIY @mention autocomplete feature is complete. Managed to find a way to track xy coords of caret in textarea, so that the dropdown tooltip will pop up just under the text when user types "@"

That was some crazy Javascript gymnastics. As imperative programming as it can get. Some dev notes on how I did it so that I can remember:

* Create a separate (invisible) element and fill it with textarea content from start to the cursor position. This 'clone' is for making measurements, using Element.getClientRects(). What's important is that it's an inline element, because each line has it's own boundary within a multiline paragraph.
* Textarea and the clone should have matching CSS (font properties, padding/margin/border and width).
* Then stack these elements on top of each other. Make sure the textarea isn't obscured by clone.
* The "xy" div is meant to mirror the cursor, just an indicator for testing. Also where the tooltip is anchored to.

Find code here:
https://codepen.io/jasonleow/pen/jOVaeXd
Jason Leow Author

@FaizMetronome thank you! Perseverance indeed… never took this long with a feature (~2wks)

0 Likes
Jason Leow Author

Thanks @sergio @okitsjoe!

0 Likes

For the @mention autocomplete - found a promising solution for getting the offset position of the caret in a textarea in pixels!!

Source: https://stackoverflow.com/a/16561663

Repro: https://codepen.io/jasonleow/pen/ZEBvRjP

Day 56 - Drink coffee to power up your power naps?! https://golifelog.com/posts/drink-coffee-to-power-up-your-power-naps-1614242101854

Coffee takes time to take effect. So drinking it just before the nap, you won’t feel the caffeine kick in just yet. And when you wake up, the caffeine would be just about starting to seep into your brain, so giving a boost on top of the rest you just had! Apparently sleep also helps flush out a neuro-chemical in your brain called adenosine. Chemically, adenosine is molecularly similar to caffeine, so it competes with caffeine to take effect on your brain. By flushing it out via a nap, the caffeine has all the room to kick start your brain even more.

Who would have known!?

💪 Yes! Managed to disable cursor movement during autocomplete selection - for DIY @mention autocomplete component

Wow this @mention autocomplete feature is really NEEDY! So many edge cases to account for!

This time, had to create a function to disable cursor movement when the tooltip list pops up. The event.keyCode is supposedly deprecated but it still works...? So to cover bases, I added event.key as well:

preventCursor(e) {
var visibleList = document.getElementById("usernamesList").style.visibility
if (e.keyCode >= 37 && e.keyCode <= 40 || e.keyCode == 13) {
e.preventDefault();
} else if (e.key === "Arrow-Left" ||
e.key === "Arrow-Right" ||
e.key === "Arrow-Down" ||
e.key === "ArrowUp" ||
e.key === "Enter"
) {
e.preventDefault();
}
},

And then adding an event listener to the showTooltip function:
document.getElementById("text").addEventListener("keydown", this.preventCursor);

And removing event listener when username is selected, by enter or mouse click, in the onEnter() and serResult() functions respectively:

document.getElementById("text").removeEventListener("keydown", this.preventCursor);

Noooow to the very last bit, moving the tooltip to pop up where the cursor's coordinates are. 🤞

Organic sharing/marketing on twitter

Hashtags discovered:
💰 #writerslift - amazing amazing movement to lift one another among the writer's community

#nanowrimo #indieauthors #writerslife
#shamlessselfpromo #shamlessselfpromosaturday #shamlessselfpromotuesday
#followfriday

Day 55 - Curiosity, the first mover https://golifelog.com/posts/curiosity-the-first-mover-1614149670056

"Success in anything is just a byproduct of learning, and learning is a byproduct of curiosity. Ultimately, if you are curious about something, you will be successful at it, and the more curious you are about it, the more successful you will be at it." ~ @naval

🕺💃 WOOHOO!!! I made it! DIY-ed my own autocomplete @mention component

The autocomplete was pasting the text after the user's text input, not replacing over it. There were a few solutions that involved tracking and finessing cursor position and index positions of strings/substrings, which felt pretty convoluted even though it used all Javascript functions. I found a better one - using regex to track the entire textarea's input, and just replace the @ or @... with the selected username from the dropdown menu tooltip. Heard it might be less performant, but well...I'm not optimizing for that (yet, if ever). Optimizing for speed and DX 🤷‍♂️ Pretty proud of myself to have solved this!

document.getElementById("textarea").value.replace(/@(\w+)$|@$/)

Spaghetti code here (sorry no time to refactor yet)👇🏻
https://codepen.io/jasonleow/pen/jOVaeXd

[Update:] Also had to deconflict the input coming from mouse click vs arrow+enter key. This has got to be one of the most complex UI interactions I had to create and test for. Everyday I'm finding edge cases to debug! Not even launched yet, so can't imagine if users will find more when it's out in the wild! 😵

Whoohoo indeed go Jason! 🎉. Many props for figuring out the @mention feature.

0 Likes
Jason Leow Author

@Mostdefkima3ff sharing the Codepen code with you in case you want it!

0 Likes

Organic sharing/marketing on Twitter

Learned to save searches, and the significant difference between same search key words in words vs hashtags

💪 YAASS the wonky autocomplete for @mentions is now working!

I'm so deep in the code, that I failed to see one tiny line of code that was causing the error, mutating the original usernames array and thus causing it to only display the result even when I backspace away the characters. Classic case of not seeing the forest for the trees! 😵

Thanks @keenencharles @yuyu for the help on all fronts!

And like nested russian dolls, I just realised I got to work on another problem before I can launch this - making sure the selected username replaces the characters that the user typed, not added on after it! 😭

Day 54 - Sleep MOARE https://golifelog.com/posts/sleep-moare-1614065209549

There’s no sleep biohack better than just more sleep. In fact, your life depends on it.

https://www.quantamagazine.org/why-sleep-deprivation-kills-20200604/