lade...

Heyloura.com

Heyloura.com

an avatar

Hey Loura!

🌐 Visit Heyloura.com 🌐 Heyloura.com besuchen

✍️Write rieview ✍️Rezension schreiben 🏷️Get Badge! 🏷️Abzeichen holen! ⚙️Edit entry ⚙️Eintrag bearbeiten 📰News 📰Neuigkeiten

Webfan Website Badge

Tags:

Rieviews

Bewertungen

not yet rated noch nicht bewertet 0%

Be the first one
and write a rieview
about heyloura.com.
Sein Sie der erste
und schreiben Sie eine Rezension
über heyloura.com.

Heyloura.com News

I did set the alarm for 2am, hoping to see the lunar eclipse… but clouds had other plans. The kids were disappointed.

https://heyloura.com/2025/03/14/...

I did set the alarm for 2am, hoping to see the lunar eclipse… but clouds had other plans. The kids were disappointed.

14.3.2025 11:40I did set the alarm for 2am, hoping to see the lunar eclipse… but clouds had other plans. The kids were disappointed.
https://heyloura.com/2025/03/14/...

Today is a sneak off to the office day. I love my kids and homeschooling them but man… their pre-teen attitude(s) is making...

https://heyloura.com/2025/03/13/...

Today is a sneak off to the office day. I love my kids and homeschooling them but man… their pre-teen attitude(s) is making everything 10x harder than it needs to be.

13.3.2025 12:45Today is a sneak off to the office day. I love my kids and homeschooling them but man… their pre-teen attitude(s) is making...
https://heyloura.com/2025/03/13/...

Coding Adventure: Using Deno and Micropub to launch heyloura.com into geminispace!

https://heyloura.com/2025/03/11/...

After last mini-coding adventure where I was exploring a simple command-line browser idea I had there was a comment by @sod that mentioned I might enjoy looking into Gopher or Gemini as alternative protocols to http… and he was 100% correct 😁

Making a blueprint 🗺️

After exploring some gemini sites (called capsules) I decided I wanted one. But… I didn’t want to make extra work for myself by having to publish blog posts in two different places using two different tools. So I thought of two options. One, make a gemini server that could host my capsule and fetch my blog posts or two, I could go the other way. Make a gemini server, write posts in gemini syntax (.gmi) and then have them uploaded to my blog.

I decided to go with the first option.

1.) A scale model 📡

First thing first. I needed to get something running locally. I already had a gemini client installed called Lagrange and I’ve been using Deno quite a bit for hobby projects. Luckily someone else had made a Gemini server middleware that I could use.

First was the command to create the certificates needed

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 3650 -nodes

And then I moved them into a cert subfolder I made in my project folder.

Next up was the main.js file and the handful of lines needed.

import { Application } from 'jsr:@arma/qgeminiserver@2.0.3';

const 
keyPath  = Deno.env.get('KEY_PATH')  || '../cert/key.pem',
certPath = Deno.env.get('CERT_PATH') || '../cert/cert.pem',
key      = await Deno.readTextFile(keyPath),
cert     = await Deno.readTextFile(certPath),
app      = new Application({key, cert});

app.use(ctx => {
  ctx.response.body = '# Hello World!'
});

await app.start();

I ran this file with the deno run --allow-env --allow-read --allow-net main.js command and there, in my Lagrange client after navigating to gemini://localhost/, was “Hello World”…beautiful 🤩

Getting my existing blog posts with Micropub

There are many things I like about using Micro.blog as my blog host. One of the big ones is the API and the Micropub implementation. In case you’re not familiar, Micropub is an open web standard for creating, editing, and deleting posts/pages from a website. So I just need a valid token and the location of my Micropub endpoint and the world is my oyster 🦪… well, at least my blog posts are… 🤣

So, Micro.blog has a spot on its website where I can generate app tokens and the micropub endpoint is in the HTML head of my blog’s index page. I grabbed those two items and stuck them in an .env file. Once there I could access them easily in Deno. var token = Deno.env.get('token') and var micropub = Deno.env.get('micropub'). I also needed the destination I was calling in Micropub, this is needed since I have several different blogs hosted and it needs to know which one I’m talking about. In this case, https://heyloura.com. var destination = Deno.env.get('destination'). I just declared each of these at the top of the file.

I replaced the route that was serving “Hello World” with a fetch request.

...
app.use(ctx => {
  const fetching = await fetch(`https://micro.blog/micropub?q=source&limit=10&mp-destination=${encodeURIComponent(destination)}`, { method: "GET", headers: { "Authorization": "Bearer " + token } } );
  const results = await fetching.json();
  let page = '';
  results.items.filter(p => p.properties["post-status"][0] == 'published').map((item, i) => { 
    page = page + item.properties["content"][0] + '\r\n\r\n';
  });

  ctx.response.body = page
});
...

I needed to filter out my draft posts, which is why there is a filter call with .filter(p => p.properties["post-status"][0] == 'published') and the content of each post is under item.properties["content"][0]. Now for this sample, I simplified the code. In actuality I added extra text, emojis, links to named blog posts (instead of just outputting) the content. You get the idea.

I once again saved and ran the run command and viola! I had a nice list of blog posts. Or at least that’s what I thought would happen… Instead everything was garbled.

Turns out the Gemini protocol doesn’t support markdown, which is what I typically use to write my posts in.

Doh!

From Markdown to Gemtext

Once again leaning on the open source community I found someone had already created a library Dioscuri. Awesome. Here’s what I needed to add at the top of my main.js file where the import statements go

import * as dioscuri from 'https://esm.sh/dioscuri@1'
import {fromMarkdown} from 'https://esm.sh/mdast-util-from-markdown@2'
import {gfm, gfmHtml} from 'https://esm.sh/micromark-extension-gfm@3'
import {gfmFromMarkdown, gfmToMarkdown} from 'https://esm.sh/mdast-util-gfm@3'
import {gfmFootnote, gfmFootnoteHtml} from 'https://esm.sh/micromark-extension-gfm-footnote@2'
import {gfmFootnoteFromMarkdown, gfmFootnoteToMarkdown} from 'https://esm.sh/mdast-util-gfm-footnote@2'

and then around the item.properties["content"][0] I called

dioscuri.toGemtext(
  dioscuri.fromMdast(
	  fromMarkdown(item.properties["content"][0]),
		{
		  tight:true,
			endlinks:true,
			extensions: [gfm(), gfmFootnote({inlineNotes: true})],mdastExtensions: [gfmFromMarkdown(), gfmFootnoteFromMarkdown()]
	 }
  )
)

Now everything is displaying a bit better.

Not perfectly. Links are gathered up at the bottom with a simple bracketed number and if it encounters any formatting it doesn’t understand it drops it.

Yes… which is why I made a little find and replace function. For a url that starts with https://heyloura.com/:year/:month/:day/:id I replaced the https://heyloura.com with a / so it became a relative link. But that means I need a route to capture those…

new Route('/:year/:month/:day/:id', async (ctx) => {
        const id = ctx.pathParams.id;
        const year = ctx.pathParams.year;
        const month = ctx.pathParams.month;
        const day = ctx.pathParams.day;
        let fetching = await fetch(`https://micro.blog/micropub?q=source&properties=content&url=https://heyloura.com/${year}/${month}/${day}/${id}&mp-destination=${encodeURIComponent(destination)}`, { method: "GET", headers: { "Authorization": "Bearer " + token } } );
        let post = await fetching.json();
        let content = dioscuriContent(post.properties["content"][0])
        ctx.response.body = content;
)

Here I grabbed the route parameters and then asked my Micropub endpoint for the contents of that URL. dioscuriContent is a helper function I made for the code in the previous section.

Now links that reference my blog posts up on my blog can be resolved on my little Gemini server.

That’s nice, but what about images?

In the Gemini protocol, images are never included in the page. You can only link to them and then if a user clicks on one can you see it. Luckily I have the url of where the image is and I have a server that can fetch. The tricky part is returning the image as a Unit8Array. No worries. I’ve got you covered.

    new Route('/uploads/:year/:id', async (ctx) => {
        const id = ctx.pathParams.id;
        const year = ctx.pathParams.year;
        let fetching = await fetch(`https://heyloura.com/uploads/${year}/${id}`, { method: "GET" } );
        const file = await fetching.blob();

        try {
            await file.arrayBuffer().then(function(data){
                var response = new ResponseOk(new Body(new Uint8Array(data)), file.type);
                ctx.response = response;
            });
        } catch(e) {
            console.log(e);
            ctx.response = ResponseFailure();
        }
    })

Same thing with the blog links. I checked for and replaced any url that had https://heyloura.com/uploads/:year/:id. Since I’m using a middleware for a gemserver I used it’s helper method for returning a response (to make sure everything is going over the correct port, etc…). So I added import { Application, handleRoutes, Route, ResponseOk, Body, ResponseFailure } from 'jsr:@arma/qgeminiserver@2.0.3'; to my import at the top of the file.

My little proof of concept is complete. I can load up my little server on localhost, click around my links, and even load images I have hosted on my blog. 🤠

Preparing the launch pad

Now this is the point where I’d normally put my little project up on Deno Deploy and the server hosting my code part is done. One big catch though… Deno Deploy doesn’t play nice with port 1965 and the TOFU certificates required by the Gemini protocol.

Sigh. Guess we are going to have to do this the hard way.

Setting up cloud hosting

I spun up Ubuntu 24.04 on a shared VPS. I’m using Hetzner and it’ll come to around $5.60 a month to host this thing (as of current pricing). I actually followed this blog post by David Sadler pretty closely when I was setting everything up.

On step “Install certificates” I did rename key.rsa to key.pem to match what I had in my main.js file and then I had to veer off on my own since I was going install deno and use my code to run the server.

First, deno needed to be installed. But! First first, zip wasn’t installed on the machine… so actually sudo apt install zip was first. Then came the curl -fsSL https://deno.land/install.sh | sh to get Deno installed.

I cd into the directory that was going to hold my little file and then created it with nano main.js and copied the contents over.

I verified everything was there. Ran my master command of deno run --allow-env --allow-read --allow-net main.js and saw the wonderful output that it was up and running on localhost.

The end.

Except… maybe I should check that I can reach my capsule with Lagrange

..er

… huh …

… crap …

I can’t 😭

Loura takes a nap

After running sudo ufw status verbose to make sure I had the firewall configured correctly and running sudo netstat -tnlp | grep :1965 to check it was listening on port 1965 and double checking the main.js file a dozen times. Every time I tried to connect I got connection refused.

So I walked around my neighborhood, appreciated the subtle signs of spring, ate a wonderful lunch, and then took a nap.

When I woke up and checked….

… Darn it, same error.

Sigh… search engine. Don’t fail me now.

Wisdom of the ancients

I did finally find the answer on this AskUbunto thread from 2012.

Installing nmap and then running nmap confirmed nmap -A -T4 capsule.heyloura.com that it was 127.0.1.1 that was the issue. Nmap scan report for capsule.heyloura.com (127.0.1.1)

Now that I knew what to look for… I found a Github issue around it Deno.ListenOptions hostname defaults to 127.0.0.1 instead of 0.0.0.0

And, looking at the code for the middleware I’m using, I was delighted to see that I could pass in the hostname and specify 0.0.0.0 by changing new Application({key, cert}) to new Application({key, cert, hostname: '0.0.0.0'}).

Holding my breath and ran my server again, and did a little joy dance when it finally connected.

Launching 🚀

The last step I needed was to make sure that my server ran even when I wasn’t logged in and that it would load when the server was rebooted and that it would auto-restart if needed. Pup to the rescue. The install was easy with deno run -Ar jsr:@pup/pup setup and then pup init --id "deno-gemini" --autostart --cmd "deno run --allow-env --allow-read --allow-net main.js". I made sure things could keep running if my user isn’t logged in with sudo loginctl enable-linger username (where username was my username) and then to finish it off pup enable-service and pup run

And heyloura.com launched as capsule.heyloura.com 🪐

For those wanting to browse it:

gemini://capsule.heyloura.com/

Otherwise, here is a picture.

Final notes

The code above was simplified for brevity but hopefully I listed enough of the steps that someone else can copy what I did. I’m thrilled that changes I make to my blog are reflected immediately to my Gemini capsule and since it is all driven by Micropub I can use my own little tools for posting and managing content.

I’m enjoying wandering around Geminispace and hope that others are inspired to check it out.

Happy coding everyone, Loura

11.3.2025 20:19Coding Adventure: Using Deno and Micropub to launch heyloura.com into geminispace!
https://heyloura.com/2025/03/11/...

Mini-coding adventure: Explorations with a command line browser

https://heyloura.com/2025/03/03/...

So last weekend I was a bit tired of the internet. Which will probably be another post at some point. But suffice it to say that the invasive tracking browsers are up to just turns my stomach.

Which lead me back to an old desire of mine, building my own web browser. I’ve never gotten very far. Browsers are so very very complex and as soon as I get started I get overwhelmed. So maybe instead of tackling something so gargantuan, I start a bit smaller.

That lead me down a rabbit hole of text-based browsers. The one that struck me the most was Offpunk. I liked how it incorporated feeds, the simple text interface, and the concept of offline first. Which got me thinking…. What could I pull off in a couple of hours?

Deno has some libraries to help with a command line tool. I ended up grabbing deno-cliffy to start. I ran into some issues with getting it to import but eventually figured out that running deno add jsr:@cliffy/command@^1.0.0-rc.7 worked instead of using the import in the main.js file.

Now that was situated I grabbed an rss parser and a feed from a blog I enjoyed. I did a quick fetch to grab the feed and then parsed it using the tool.

Turns of cliffy lets you pass in a list of suggestions with a paging interface. Sweet…

const xml = await response.text();
const feed = await parseFeed(xml);

const postSelection = await Input.prompt({
  message: "Choose a post",
  info: true,
  list: true,
  maxRows: 20,
  suggestions: feed.entries.map(f => f.title.value)
});

As you can see, the list of items in the RSS feed are displayed and you can type/filter down to the one you want to view.

Once selected I fetched the actual post.

But displaying a bunch of HTML on the command line isn’t my idea of a good reading experience.

That where another library came in html-to-text from npm

A little bit of configuration later and I have….

Which is actually pretty nice to read. The big drawback is I don’t have paging and I find scrolling up on the command line to be distracting. Maybe I could pipe it to less or something.

Where to next?

I thought this was a nice and quick proof of concept that building something out like a text-based browser could be in my grasp (assuming I’m sticking to just getting text and not having to support forms)

But that doesn’t solve… I want my cool new browser on my android phone.

And I also want it without using web-view anything. My trust in the browser is waning. That strikes out almost all of the javascript -> cross platform apps tools.

Deno included.

Little Side Quest

There is a SDL2 deno project that I found in my quest to see if Deno could do desktop apps. The documentation is a bit poor and it took some major head scratching to get the dependencies squared away on Windows. But I was able to get a little “Hello World” up and running

Some idle thoughts

I do want to pursue this browser idea a bit further. I recently got the cross platform GUI library python Kivy up and running with a little test project. I may pull out my little idea sketchbook and see what I can come up with. What could a browser be… if we didn’t use the current browser kings as a blueprint?

Could RSS reign supreme? Bookmarks and link graphs?

Dear reader, have you ever thought about it?

3.3.2025 21:19Mini-coding adventure: Explorations with a command line browser
https://heyloura.com/2025/03/03/...

So while I’m at this swim meet my mind is wandering to webgardens, the Spring'83 Protocol and small social networks. I feel like I...

https://heyloura.com/2025/03/02/...

So while I’m at this swim meet my mind is wandering to webgardens, the Spring'83 Protocol and small social networks. I feel like I have an idea brewing but I’m not sure what connection my mind is trying to make. 🤔

3.3.2025 00:02So while I’m at this swim meet my mind is wandering to webgardens, the Spring'83 Protocol and small social networks. I feel like I...
https://heyloura.com/2025/03/02/...

Last big swim meet of the season for my daughter! 🏊‍♀️

https://heyloura.com/2025/03/02/...

Last big swim meet of the season for my daughter! 🏊‍♀️

Board displaying swim meet times

2.3.2025 21:12Last big swim meet of the season for my daughter! 🏊‍♀️
https://heyloura.com/2025/03/02/...

Small work rant. The non-profit I work for has six people working for them (including me) Why on earth do we have 92* projects in Asana? ...

https://heyloura.com/2025/02/26/...

Small work rant.

The non-profit I work for has six people working for them (including me)

Why on earth do we have 92* projects in Asana?

🤯 Why… just why!?! No wonder I can never find things…

*That’s just the number I have permission to see… there are even more I’m sure….

26.2.2025 15:46Small work rant. The non-profit I work for has six people working for them (including me) Why on earth do we have 92* projects in Asana? ...
https://heyloura.com/2025/02/26/...

Made some progress yesterday on my blog/game hybrid. I’m thinking that the blog post will be represented by the broken tablet and...

https://heyloura.com/2025/02/20/...

Made some progress yesterday on my blog/game hybrid. I’m thinking that the blog post will be represented by the broken tablet and you’ll need to find the key to unlock and read it, thus gaining gold and XP. The game change-log has been updated. Onward! 🐉⚔️👩‍💻

A pixelated game interface displays a character navigating through a maze-like environment with inventory options and navigation instructions on the side.

20.2.2025 16:32Made some progress yesterday on my blog/game hybrid. I’m thinking that the blog post will be represented by the broken tablet and...
https://heyloura.com/2025/02/20/...

🐸 Lillihub (an unofficial web/PWA client for Micro.blog) Here’s what’s new: Rename/delete notebooks Move notes to different...

https://heyloura.com/2025/02/14/...

🐸 Lillihub (an unofficial web/PWA client for Micro.blog)

Here’s what’s new:

  1. Rename/delete notebooks
  2. Move notes to different notebooks
  3. Copy notes and export to Markdown/HTML
  4. Optional note auto-save
  5. Auto-save on new posts and editing existing blog posts

14.2.2025 19:12🐸 Lillihub (an unofficial web/PWA client for Micro.blog) Here’s what’s new: Rename/delete notebooks Move notes to different...
https://heyloura.com/2025/02/14/...

Coding Adventure: Micro.blog Private Notes + 7.css Fun

https://heyloura.com/2025/02/11/...

Back in October I posted a bit about using YAML front-matter with Micro.blog private notes to extend it’s functionally. I ended up releasing that to Lillihub users earlier this year.

I’ve moved over to using analog index cards for most of my daily note taking but I still have several collections of notes I’m growing. And I needed a place for them. Why not use Micro.blog? Is what I asked myself. Now that Manton has built out a versioning system that saves note changes for 60 days I feel more confident using the service with a larger volume of notes. But what I’ve built out so far in Lillihub (tagging and having titles) is not quite enough.

A Fetch Quest - Getting my notes

Just like my last coding adventure, first I needed to authenticate. I’m not going to write that up again. But do not fear fellow adventurer. I have a map with the secrets of Micro.blog’s indieauth spelled out.

So now that I have the magical token, I need only ask the API nicely for what I need.

Firstly, my notebooks

const fetching = await fetch(`https://micro.blog/notes/notebooks`, { method: "GET", headers: { "Authorization": "Bearer " + token } } );
const results = await fetching.json();

And then upon choosing a notebook and divining its id, I can get all my lovely notes…

const fetching = await fetch(`https://micro.blog/notes/notebooks/${id}`, { method: "GET", headers: { "Authorization": "Bearer " + token } } );
const eNotes = await fetching.json();

But wait! I cannot read my lovely notes! They are garbled and undecipherable to my eye.

A Wizards Secret - Decrypt and encrypt my notes 🧙‍♀️

Luckily some documentation lights the way.

The end. 🤣

Okay, kidding! I’ll share (some of) my secrets.

Behold!

The first of three spells - creating a key 🔑

The first spell component needed is the private note key from Micro.blog. This I saved in localStorage so I could access when needed.

const imported_key = localStorage.getItem("notes_key") ? await crypto.subtle.importKey(
    'raw',
    hexStringToArrayBuffer(localStorage.getItem("notes_key").substr(4)),
    { name: 'AES-GCM', length: 256 },
    true,
    ['encrypt', 'decrypt']
) : '';

function hexStringToArrayBuffer(hexString) {
    const length = hexString.length / 2;
    const array_buffer = new ArrayBuffer(length);
    const uint8_array = new Uint8Array(array_buffer);

    for (let i = 0; i < length; i++) {
        const byte = parseInt(hexString.substr(i * 2, 2), 16);
        uint8_array[i] = byte;
    }

    return array_buffer;
}

The second of three spells - decrypting 🧩

async function decryptWithKey(encryptedText, imported_key) {
    const encrypted_data = new Uint8Array(atob(encryptedText).split('').map(char => char.charCodeAt(0)));
    const iv = encrypted_data.slice(0, 12);
    const ciphertext = encrypted_data.slice(12);

    const decrypted_buffer = await crypto.subtle.decrypt(
        { name: 'AES-GCM', iv },
        imported_key,
        ciphertext
    );

    const decoder = new TextDecoder();
    const decrypted_text = decoder.decode(decrypted_buffer);
    return decrypted_text;
}

The third of three spells - encrypting 🪄

async function encryptWithKey(text,  imported_key) {
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const encoder = new TextEncoder();
    const plaintext_buffer = encoder.encode(text);

    const ciphertext_buffer = await crypto.subtle.encrypt(
        { name: 'AES-GCM', iv },
        imported_key,
        plaintext_buffer
    );

    const encrypted_data = new Uint8Array([...iv, ...new Uint8Array(ciphertext_buffer)]);
    const base64_encoded = btoa(String.fromCharCode(...encrypted_data));
    return base64_encoded;
}

With these spells in our arsenal we can decrypt any of our notes and then save them again by re-encrypting them.

const markdown = await decryptWithKey(note, imported_key);
const eNote = await encryptWithKey(markdown, imported_key);

With that out of the way, let’s see what we can can do 🫠

I Can Never Make Up My Mind 🫥

I’ll admit it. I change up how I save my data regularly. No structure is safe for more than a couple of months. Maybe I’m strange. I find it soooooo soooothing to rename and reorganize digital files.

Not being able to move notes around in notebooks started to drive me insane.

Nor did the documentation hand me a simple endpoint to get it done either. Oh well. I’m sure I’ll think of something.

What about…. copy and delete? As in copy the note into a new notebook and then delete the original.

So with a little HTML, CSS, and JS I have lovely modal I can use to select a notebook and thus send my note along to it’s new home… Oh yeah, I better put up a warning for other users.

A digital note displays various categorized emoji-labeled lists and options to move a notebook.

The code isn’t that complicated and there is no need to decrypt anything.

let fetching = await fetch(`https://micro.blog/notes/${id}`, { method: "GET", headers: { "Authorization": "Bearer " + accessTokenValue } } );
const eNote = await fetching.json();

const formBody = new URLSearchParams();
formBody.append("notebook_id", notebook);
formBody.append("text", eNote.content_text);

let posting = await fetch('https://micro.blog/notes', {
    method: "POST",
    body: formBody.toString(),
    headers: {
        "Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
        "Authorization": "Bearer " + accessTokenValue
    }
});

if(posting.ok) {
    posting = await fetch(`https://micro.blog/notes/${id}`, {
        method: "DELETE",
        headers: {
            "Authorization": "Bearer " + accessTokenValue
        }
    });
}

Sweet.

I also added in the ability to rename a notebook and delete a notebook. I won’t go into details since those are just endpoint you call and they are in the documentation.

Danger! ☠️ Loura lost 10 HP!

So while writing the first draft of this blog post, I stepped away from my desk and didn’t lock my computer. The cat took advantage of this and decided to step all over my keyboard. I lost the first draft 😢

Okay, that sucked. Maybe I should do something about that…

I know! auto save!

This was pretty easy. The editor I’m using is EasyMDE and it includes it out of the box. Sweet! Just pass it the right configuration autosave:{enabled:true} and….

Uh oh…..

Did you spot it?

Maybe I should let people know I’m saving a copy of the decrypted note in localStorage.

And thus a toggle was born.

A dark themed interface is displayed showing a note-taking application with options for creating and managing various subjects such as Index, Meals & Recipes, Money, and others on the left sidebar.

Side Quest - Storing other one-off project data.

One other fun thing I started doing, was using using private notes to hold other small amounts of data for my growing collection of personal PWA’s. Remeber this project with the iframes? I did end up finishing that (though not the blog posts), turned it into a PWA and hooked it up to a private note. I just serialize the data and store it.

It’s my personal todo list calendar hybrid on my phone.

A Dragon’s Hoard Must Be Shiny! 🪙

Okay, okay. I made a micro post on January 15th when I discovered 7.css.

And I uh….

had a bit too much fun.

🤣😅🤣😅🤣

A colorful, patterned desktop displays multiple open windows, showing a Twitter feed, chatting, and an image of muffins.

What I love about it? opening up all my notes in different windows! I can even drag the windows around and resize them.

Yep… 😅

The End

♥️ Loura

11.2.2025 22:48Coding Adventure: Micro.blog Private Notes + 7.css Fun
https://heyloura.com/2025/02/11/...

This morning I’m practicing some tai chi forms, teaching my son to use an encyclopedia for his research paper, and waiting for fresh...

https://heyloura.com/2025/02/09/...

This morning I’m practicing some tai chi forms, teaching my son to use an encyclopedia for his research paper, and waiting for fresh homemade donuts to finish rising.

Auto-generated description: Two people are sitting at a wooden table, reading books in a room with wooden floors and a staircase in the background.

9.2.2025 16:32This morning I’m practicing some tai chi forms, teaching my son to use an encyclopedia for his research paper, and waiting for fresh...
https://heyloura.com/2025/02/09/...

Today’s exercise is a three ton pick up. Three tons of pellets for the pellet stove need to be moved into storage.

https://heyloura.com/2025/02/06/...

Today’s exercise is a three ton pick up. Three tons of pellets for the pellet stove need to be moved into storage.

Auto-generated description: Pallets covered in shrink wrap are stacked outside a building surrounded by trees.

6.2.2025 14:45Today’s exercise is a three ton pick up. Three tons of pellets for the pellet stove need to be moved into storage.
https://heyloura.com/2025/02/06/...

Yesterday I was out clothes shopping and two hours in I noticed my wedding ring was gone… vanished… poof… So my...

https://heyloura.com/2025/02/03/...

Yesterday I was out clothes shopping and two hours in I noticed my wedding ring was gone… vanished… poof…

So my “cheer myself up” outing from a rotten morning turned into tears, backtracking, and feeling dejected.

Sigh.

But a turn of luck saved me. It had fallen off in my car.

Relief.

3.2.2025 14:55Yesterday I was out clothes shopping and two hours in I noticed my wedding ring was gone… vanished… poof… So my...
https://heyloura.com/2025/02/03/...

🎊🥳🐸 Lillihub Update 🐸🥳🎊 Besides bug fixes, here’s what’s new: Private notes can have titles and tags...

https://heyloura.com/2025/01/31/...

🎊🥳🐸 Lillihub Update 🐸🥳🎊

Besides bug fixes, here’s what’s new:

  1. Private notes can have titles and tags (Lillihub only)
  2. Access private note versioning
  3. The timeline now mimics Micro.blog by default (this can be changed under settings)
  4. Links to notes and bookshelves in the slide out menu

screen shot of lillihub ui showing the private notes edit ui with instructions on how to add titles and tags.

screen shot of lillihub ui showing the private note in the previous image displayed

Enjoy!

31.1.2025 16:27🎊🥳🐸 Lillihub Update 🐸🥳🎊 Besides bug fixes, here’s what’s new: Private notes can have titles and tags...
https://heyloura.com/2025/01/31/...

Android Studio and gradle. Please, I beg you. Give me something useful in the console when you fail to build. -heyloura, day three of trying...

https://heyloura.com/2025/01/24/...

Android Studio and gradle. Please, I beg you. Give me something useful in the console when you fail to build.

-heyloura, day three of trying to get an old Cordova app for work working on a new system.

24.1.2025 19:13Android Studio and gradle. Please, I beg you. Give me something useful in the console when you fail to build. -heyloura, day three of trying...
https://heyloura.com/2025/01/24/...

Phew, finally finished backing up all my photos. One backup on my Linux machine, and one on my Immich server I’m self hosting with...

https://heyloura.com/2025/01/21/...

Phew, finally finished backing up all my photos. One backup on my Linux machine, and one on my Immich server I’m self hosting with Pika Pods. Next step, delete everything off of google, onedrive, and Amazon photos and finally start cancelling accounts.

21.1.2025 22:04Phew, finally finished backing up all my photos. One backup on my Linux machine, and one on my Immich server I’m self hosting with...
https://heyloura.com/2025/01/21/...

I’m having way too much fun with 7.css

https://heyloura.com/2025/01/15/...

I’m having way too much fun with 7.css

15.1.2025 15:25I’m having way too much fun with 7.css
https://heyloura.com/2025/01/15/...

My 2025 Productivity System

https://heyloura.com/2025/01/14/...

I bounce around tools a lot trying to keep my life organized. Everywhere I look, the tasks I need to get done just keep multiplying. I’ve probably tried dozens of apps by now over the years. I really liked Notion, but didn’t like the lack of portability for my data. Logseq was fun but keeping things synced was hard. Obsidian was close to what I wanted, but ultimately the freedom to endlessly tweak the system made it more of a distraction to me.

Then came 2024 and my life getting exponentially more difficult in an emotional way and all these systems I crafted crumbled. When life was going fine, my executive function skills could keep up with multi-step processes or deal with some friction in the system. But just when I needed these systems the most to keep me afloat and make sure the essentials are getting done they failed. Or I failed, depending on your point of view.

What did keep me getting stuff done? The index card in my pocket.

Since then, my paper system has evolved and that’s what I want to take a moment to record in this post. But unlike other options, I can toss aside the extra’s in this system at anytime and go back to what I can depend on… a simple list on an index card.

The index card

I have three varieties of index cards in my system.

  1. The capture card or inbox
  2. Project cards
  3. Reference cards

I keep all of these in a little index card holder in my pocket or purse. This is similar to the Hipster PDA. Here is a peak at my inbox card, where I jot down tasks or notes as I get them, and a reference card which is this month’s calendar so I can see what dates I have appointments scheduled

Auto-generated description: A calendar and a notebook page contain handwritten entries listing events and reminders for January, placed on a wooden surface.

Similar to the Getting Things Done system, GTD, my inbox card captures whatever I come across. Periodically throughout the day I cross off things that take less than two minutes (and do them) and at the end of the day the rest of the items are transferred to projects cards, other reference cards, or put as notes on slips of paper (more on that below).

Project cards are the cornerstone of my system and each active project has its own card that is stored in my holder. I currently have around 20 that I’m carrying around. When a project is done I put it in storage if I think I might need to reference in the future otherwise I recycle it.

When I create a project card I brainstorm the tasks I think I need to do. Then I highlight the “Next Action” I need to take and the color it is highlighted corresponds to the context that task needs. I cross out tasks as I complete them and before I put the card away for the day I make sure I have another action highlighted for the next time I circle around to it.

Auto-generated description: Index cards on a wooden surface display handwritten notes, including task lists and a project named Lillihub - Timeline.

Reference cards I tend to keep on a graph paper index card and contain information I want to reference. Monthly calendars or larger projects that will take more than six weeks are things I’ll normally write up a reference card for. As an example here are my six week homeschooling reference cards for the kids and one I put together for work. So when I’m homeschooling, I have the homeschooling reference cards on hand and when I’m working… the work one.

Auto-generated description: Three handwritten study planners on a wooden surface outline tasks and schedules for various academic subjects and activities.

Now, I tend to view projects as things done at a discrete point in time. For instance, changing my HVAC filters is something that must be done and redone on a schedule. So “change HVAC filters in January” is a project in my system and I’ll make a project card for it. However, the reoccurring reminder to do it is not a project and I needed somewhere to store that and be sure to rediscover that reminder when I needed it.

Keeping organized - a tickler file

Now I’ve been familiar with 43 folders or a tickler file system since I read the post on Analog Office . I just never used one since… one, I was mostly using apps and two, they don’t tend to be portable. If I was going to break free of the apps I needed something portable.

In December 2024 inspiration struck and I crafted my own tickler file. One that was small, portable, and fit in my purse. I took an old Tomoe River A6 planner I wasn’t using and some washi tape I had on hand and went to crafting. I doubled up the pages and taped them together making slightly more than 43 pouches. Tomoe River paper is thin which helps keep this whole thing portable. The A6 size means that my 3x5 index cards fit right inside. Plus it folds open flat and I can use the outside of the pouches to put sticky notes.

A person is holding a stack of decorated and colorful index cards labeled Jan 31st, suggesting they are used for organizing or journaling purposes.A hand is holding open a notebook with grid paper and a pink sticky note on one page.A colorful, tabbed notebook titled PRESENT with various illustrations on its cover is placed on a wooden surface.A black zippered pouch containing a large stack of colorful, organized papers is lying open on a wooden surface.

I have a pouch for each day and monthly ones in the back. My reference cards, slips of papers with notes and reminders, all live in this pouch. At the beginning of the month I distribute all the slips of paper it collected to the dates they need to go. If they repeat, I keep that info on the paper and move it along as needed. This method of rotating out reoccurring cards is a lifesaver for all those home-based tasks that I need to keep in mind. Changing filters in the fish tank, car maintenance, you name it. I make a slip of paper and move them along.

Auto-generated description: A handwritten note on graph paper outlines a monthly digital photo organization process, including steps like deleting blurry photos and selecting favorites.One thing I did discover, is that I need to use thin paper to keep the tickler file from getting too big. I just tore apart an old Hobonichi journal, with Tomoe River paper, I never used and cut the paper to fit instead of using thicker index cards for everything.

Using the system

I wake up, make coffee and grab my tickler file. I open it up to today’s date and pull out whatever slips of paper it contains and glance at the sticky notes. I put aside what I feel like I can handle that day and move the rest to tomorrows folder. Then I pull out my index card holder and look through my projects cards. Anything new I think of I jot down on my inbox card as well as a tentative plan of attack for the day. Then I get to work.

My inbox index card is right there for when an email comes in or I get a Teams message. I have it in my pocket when homeschooling the kids so I can jot down a random supply I need to pick up. I bring it to work meetings. If I need to go somewhere, everything fits in my purse. In fact, my tickler file fits in my A6 planner cover that has card slots and a small mesh holder for my highlighters… so it often is my purse when I’m out and about.

At the end of the day I spend about 15 minutes sorting slips back into the ticker file or creating project cards or updating reference cards.

It’s been a long time since I felt so in control of my tasks across all facets of my life 😊🗃️

14.1.2025 18:40My 2025 Productivity System
https://heyloura.com/2025/01/14/...

Yesterday’s rabbit trails (things that caught my interest that I went off to explore) Non-cryptographic hash functions and more...

https://heyloura.com/2025/01/07/...

Yesterday’s rabbit trails (things that caught my interest that I went off to explore)

7.1.2025 12:40Yesterday’s rabbit trails (things that caught my interest that I went off to explore) Non-cryptographic hash functions and more...
https://heyloura.com/2025/01/07/...

First time in a while that I have friends coming over to play Dungeon Crawl Classics. I hope they enjoy and survive “Perils of the...

https://heyloura.com/2025/01/05/...

First time in a while that I have friends coming over to play Dungeon Crawl Classics. I hope they enjoy and survive “Perils of the Sunken City” ⚔️🐉

5.1.2025 21:33First time in a while that I have friends coming over to play Dungeon Crawl Classics. I hope they enjoy and survive “Perils of the...
https://heyloura.com/2025/01/05/...

So… 1:00 am one of the kids burst into our bedroom with stomach bug symptoms… and that’s how my new year is going 🤣

https://heyloura.com/2025/01/01/...

So… 1:00 am one of the kids burst into our bedroom with stomach bug symptoms… and that’s how my new year is going 🤣

1.1.2025 21:35So… 1:00 am one of the kids burst into our bedroom with stomach bug symptoms… and that’s how my new year is going 🤣
https://heyloura.com/2025/01/01/...

Happy New Year!

https://heyloura.com/2025/01/01/...

Happy New Year!

1.1.2025 06:21Happy New Year!
https://heyloura.com/2025/01/01/...

Homeschooling costs for the 24/25 school year

https://heyloura.com/2024/12/30/...

It’s that time of the year when I close my books on the costs for the current school year. Take a big breath, and then in late February I’ll start planning, putting down deposits and hunting for supplies for the next school year.

The first thing you need to understand, is the homeschool unicorn. 🦄 It’s this mythical curriculum you can get for your child that is:

Now most curriculum for homeschoolers fit one of the three. You can even get two of those bullet points if you look around and do your research. Unfortunately something that is all three does not exist. Even if the marketing on the curriculum promises it.

I work full-time as a software engineer and I’m the primary homeschooling parent for my children. I’m also a secular, eclectic, academic homeschooler which in homeschooling circles is pretty small segment. What that means is, I have to have an easy-to-use curriculum since 40+ hours of my week are for work, I want rigorous curriculum choices customized to my kids and I’m not interested in anything religious or masquerading as secular or that whitewashes history which removes many curriculum choices and communities.

So rigorous and easy-to-use means that I spend $$$. These numbers are what I spend and are not representative of other homeschoolers.

I’m sharing this in part to be more open in general but also because I come across countless posts in homeschooling groups about a homeschooling parent who wants to/must work full-time and is looking for a unicorn. If you work, the biggest hurdle becomes time. I don’t have time to chase deals, or go to the library, or spend hours making a free curriculum work. As my kids get older and their learning requires more time for understanding and cementing concepts… I can’t make that time magically appear in my schedule. What I can do, is pay others for their time.

So here is my real world example:

My son, age 14, 9th Grade (1st year of high school):

Auto-generated description: A person is sitting in a chair reading a book with a cat on their lap.

Whew. So that comes to $10,198.

But, I have two kids!

My daughter, age 12, 7th grade

Auto-generated description: A person is sitting at a desk petting a cat, with a map on the wall and various items on shelves in the background.

So that comes to $4,400 for kid #2.

The grand total? $14,598

And that doesn’t include paper, pens, and other random supplies I need to rush out for and grab for a project. Also not included in the numbers above are the summer camps, music lessons, or sport fees that I spend. I kept these out since many parents who are not homeschoolers also incur these costs. Same with our family trips to museums or to other historical points of interest.

It’s less than a secular private school in my area but much more than public school.

So there you have it. 😎

31.12.2024 16:29Homeschooling costs for the 24/25 school year
https://heyloura.com/2024/12/30/...

Merry Christmas to all who celebrate. For those that don’t, I hope you have a wonderful day. For those who celebrate, and it’s...

https://heyloura.com/2024/12/25/...

Merry Christmas to all who celebrate. For those that don’t, I hope you have a wonderful day. For those who celebrate, and it’s complicated… I’m right there with you and I’m wishing you the best. 🎄

25.12.2024 20:14Merry Christmas to all who celebrate. For those that don’t, I hope you have a wonderful day. For those who celebrate, and it’s...
https://heyloura.com/2024/12/25/...

Everyone is out of the house… It’s time to wrap presents 🎄

https://heyloura.com/2024/12/22/...

Everyone is out of the house… It’s time to wrap presents 🎄

22.12.2024 16:31Everyone is out of the house… It’s time to wrap presents 🎄
https://heyloura.com/2024/12/22/...
Subscribe

🔝

Datenschutzerklärung    Impressum