1. i pushed out two patch releases, which basically just

    1. updated every dependency to its latest release, which was important since some things (the old django i had for example) had security issues
    2. fixed my usage of tippy.js to work again, since tippy.js 3 works differently to tippy.js 2


  2. i forgot to push the “native microformats2 in the database” branch to my git server before wiping my old laptop :/ oops

    lemoncurry microformats2
  3. lemoncurry 1.10.0: what's new and what's next?

    lots of stuff is new, since i haven't posted a changelog since 1.9.4! let's focus on the important things i guess?

    • all my html templates are jinja2 now instead of vanilla django - jinja2 is faster and also much more capable, since it supports pretty much arbitrary python expressions rather than a very strict specialised syntax
    • lemoncurry now natively serves avatars through the libravatar protocol, which is basically like an open distributed version of gravatar? sadly, the main libravatar server later announced that it's shutting down in october :( my implementation will still work at least, since it's distributed, but i expect fewer services will actually support libravatar after the main server's gone :( :(
    • micropub support is way better now - i have a micropub media endpoint, which lets you upload images and stuff for your post before you publish it, posts can be deleted over micropub, and additional properties work now too. neato
    • i use messagepack now for caching stuff in redis, since it's faster as well as more space-efficient than the other serialisation formats available
    • amp is no longer supported, because i decided amp sucks. you're welcome?
    • changed the layout of entries so they now have way less vertical overhead. i did this to encourage me to use notes more, since they're meant to be little status updates like toots and making them Big discouraged me from Doing That

    next, i think i might be planning to break backwards compatibility. yep :o

    specifically, i store entries internally using fairly typical relational database modeling: fields for single-valued stuff like name and content, many-to-many associations for stuff like cats and syndications, etc. etc.? and i'm running into a mismatch between that structure and what i need the site to handle

    specifically, while i can easily produce microformats2 html from that structure, micropub works by sending microformats2 items into the site, which means i need to convert back and forth between mf2 and my internal format. this ends up being a big hassle in some cases! what micropub really wants is for microformats2 to be the site's native format, since that eliminates the need for translation

    so basically: i'm planning to change lemoncurry's internal entry format from traditional entity-relationship modeling to native microformats2 json, just like the json i send to its micropub endpoint right now. then i can natively exchange microformats2 items with my site, without the translation mismatch

    that's a gigantic change, and i haven't even decided exactly how i wanna implement it. so i'm planning to make it a major version. that's right, lemoncurry 2.0 is on the roadmap!! :o

    lemoncurry facebook.com twitter.com vulpine.club
  4. got the new design looking pretty nice on my phone now c: woo! i think the next thing to figure out at this point is probably automatic syndication? i’ll look into doing it with mastodon first, and then maybe silos as well. maybe

  5. just added something i’ve been meaning to include!! yay! here it is, since you can’t actually see it unless you’re logged in as me 😉

    a screenshot of an admin panel in my site, which displays micropub tokens and allows me to revoke access

    yay! it can load the clients’ display names and logos as well, although quill is the only client i have in here that has those things

    another screenshot, showing that quill.p3k.io has its nice name and logo displayed. lovely

    so that’s cool!! yay

    lemoncurry micropub
  6. tbh what i really need to do next is get syndication going! with my entries automatically pushed to masto and maaaaaaybe the birdsite, posting here’ll be a way more reasonable choice

    lemoncurry roadmap
  7. yo i just signed into lemoncurry on my phone!! hopefully this will reduce posting friction and get me actually using my own site for stuff lmao

    also it’s been updated a lot since i last posted? lots of general polish, performance tweaks, type checking and such. delicious

    not really many new features honestly, just a lot of cleanup and paying off technical debt

    anyway yeah i’m feeling pretty good about it! yay 💖

  8. a tale of two releases

    hey friends! i haven’t released a lemoncurry update in about a month, but i have been working on it! since last time, i’ve made versions 1.9.3 and 1.9.4 (whoa!! i know, right?) so here’s what happened in both of them :o

    first up, lemoncurry 1.9.3!

    • bootstrap 4 came out of beta, so i switched from the beta to the final release!! woo
    • i set up continuous integration with gitlab ci! what that means is that the unit tests are automatically run every time i push a new commit, and a cute little checkmark is displayed on the commit when i view it on gitlab? unless the tests failed, in which case i get an unpleasant little cross instead? so at a glance i know if a commit Broke The Tests, which is handy info!
    • font awesome put out a few more releases, so now i’m on v5.0.8 instead! neat
    • lots of refactoring: i previously defined separate named routes in django for each kind of post, like entries:notes_index and entries:articles_index, but that makes figuring out whether a particular url points to an entry or something else way more of a hassle, since there are lots of different route names to match? and it turns out you need to know whether a given url on your site points at an entry to receive webmentions (!!!!!!!) for that entry, so i changed all that stuff around :o now there’s just a route called entries:index that takes a parameter for the entry kind, which is much easier to process c:
    • the permalink pages, like /notes/3 and such, weren’t checking whether the entry with id 3 actually existed. which meant it crashed and gave you a 500 server error. now, it checks upfront and returns the correct error if you ask for a nonexistent entry - 404, not found!

    and now, lemoncurry 1.9.4!!

    • i started writing code to receive webmentions!!!!!!!! it’s nowhere near finished yet, and i haven’t made it discoverable so other people’s sites won’t know to use it, but it can receive mentions, figure out which entry was being mentioned, and save that information to the database?? next, i need to use the job queue to test whether the webmention is valid (i.e., whether the source page really mentions the target page) and then if it’s valid to actually display it someplace :o really good start so far tho!
    • i decided to install the lovely highlight.js, for pretty code colours every time i post a code block :3
    • previously, the nya.as short urls were being generated by a third-party plugin called django-shorturls, but that plugin hasn’t been updated since 2016! since it doesn’t really do much anyway, i decided to spend a few hours reimplementing its functionality myself. easy peasy
    • the big advantage of dropping django-shorturls is that it wasn’t compatible with django 2 - since i’m not using it any more, i upgraded django to 2.0.3!! yay!! it seems pretty much the same as before but still!! yay!!

    so that’s what’s up! here’s a pretty little python code block to celebrate :o

    def is_cutie(person):
      Test whether the person provided is an absolute cutie pie.
      if person.is_reading_this:
        return True
      return True # yes, even people not reading this are cuties
    font awesome lemoncurry facebook.com octodon.social twitter.com
  9. yo i just published lemoncurry 1.9.2! there’s nothing new that you can actually see lol

    there are two new things behind the scenes though??

    1. i started writing automated tests?? i’m generally pretty bad at writing tests for my projects so this is kinda notable, i think?? currently the only things covered by my tests are a few utility functions and a couple of the /.well-known views, but it’s a good start and i’m proud ✨

      i’m using the lovely pytest?? the main reason i chose it is that it’s got super-smart assertion introspection: if you write tests using the standard python unittest module, then you have to write ugly things like self.assertEqual(result, 5) into your tests, whereas if you’re using pytest all you need to write is assert result == 5 and you still get the same information when the assertion fails! yay! 🐱

    2. i was hashing passwords with django’s default algorithm, pdkbf2, which is quite good! but it’s not the best password hasher out there, so i’ve now switched to the newer and stronger algorithm argon2 instead! 💖


    lemoncurry testing facebook.com octodon.social twitter.com
  10. whoa, it’s lemoncurry 1.9! yep!

    i bumped the minor version instead of the patch version, ‘cause lots of stuff happened!

    • i added rudimentary support for producing accelerated mobile pages versions of each entry!
      • it doesn’t always produce valid amp html, because i haven’t figured out how to convert the html i get out of my markdown parser into amp html?
      • but for simple entries, mostly entries that don’t have images in them, it works perfectly c:
    • lots of performance improvements
      • i cut down on the number of sql queries that lemoncurry needs to make to achieve various things?
      • most importantly, rendering an entry requires access to its author, its cats, its syndications, and so on. fetching all this took a lot of queries, but it turns out it could just make a few simpler queries up-front instead!
    • i bumped font awesome again!
      • it’s 5.0.6 now: i skipped 5.0.5 because 5.0.6 was actually released on the very same day?
      • i guess they made a mistake in 5.0.5 that needed urgent fixing or something like that :o
    • micropub is better again! specifically, i added support for GET /micropub, which lets micropub clients ask the server for information
      • there’s q=syndicate-to, which tells the client what syndication targets the server supports (currently none)
      • and q=config, which tells the client where the micropub media endpoint is (currently nowhere) and what the syndication targets are (still none)
      • and q=source, which tells the client the normalised microformats2 json for a particular entry! clients use this to retrieve entries in an editable format, as part of updating an existing entry. this part works perfectly so far, but because updating isn’t implemented it’s not too useful yet 😉
    • additionally, micropub
      • does scope checking now! your token must contain the ‘create’ scope if you want to create a new entry! there aren’t any other operations you can perform yet that require a scope, but you’ll need the ‘update’ scope when i implement updating existing entries
      • returns better error responses, when you do things like pass a token that’s missing the scope you need? it turns out the micropub spec actually describes the format the errors should be in, which i wasn’t following, oops :3 now i am!
    • i turned off google analytics!
      • i don’t care about getting that kind of information
      • i didn’t like subjecting visitors to google’s tracking
    • this isn’t actually part of the app itself, just the way i’ve set up my deployment, but: i realised i had gunicorn running just one lemoncurry worker, which meant i could only handle exactly one request at a time??
      • this causes problems if for example your micropub source query works simply by directly requesting the page you asked for, and then parsing it with mf2py! (yes, that’s what lemoncurry’s implementation does 😉 )
      • it also causes problems if you expect any decent amount of traffic to your site, since you can only handle one http request from anyone at a time?
      • so i fixed that, gunicorn has a couple of workers now c:

    you may be wondering why the version is already 1.9.1? the reason is that 1.9.0, while containing all of the above exciting features, was unfortunately broken! while optimising the system’s performance, i accidentally broke the django authentication :o i didn’t notice because i was focused on micropub, which always uses its own tokens rather than the usual session-based authentication? anyway 1.9.1 fixed that

    oh, by the way, it won’t roll over to 2.0 with the next minor release? unless i do something massive next, you can expect 1.10 to be the next minor version!

    lemoncurry micropub to quote william shakespeare: words words words facebook.com octodon.social twitter.com