~aleteoryx/webjrnl

ref: 97ce6ab3135a0339a3bc42ff882091a398e8b22d webjrnl/README.md -rw-r--r-- 5.3 KiB
97ce6ab3Aleteoryx compat 22 days ago

#webjrnl

minimal HTML4 journalling program, written in golang

features:

  • filesystem database
  • javascript-free
  • you can probably use this on anything with a TCP stack
  • versioning system

I wrote this so I could edit my journal (a text file) from multiple computers. it is basically a system for versioning and editing sections of a specially-formatted text file

#installing

$ git clone https://git.amehut.dev/~aleteoryx/webjrnl
$ cd webjrnl
$ go build -ldflags '-w -s'
$ mkdir db
$ echo -n 'changeme' | sha1sum
fa9beb99e4029ad5a6615399e7bbae21356086b3 -
$ echo '[{"id": "marmalade", "passhash": "fa9beb99e4029ad5a6615399e7bbae21356086b3"}]' >db/users.json
$ ./jrnl :8080 db
initialized!

this is untested in go versions < 1.24.5. if you successfuly compile it in an earlier version, let me know and I will update go.mod. it has been tested on linux, but should have no problems running on other unixes, plan 9, or even windows.

webjrnl is a single executable, jrnl. it takes 2 arguments: the address on which to listen, and the database location. if the second argument is omitted, it is assumed to be .

if you plan to run webjrnl behind a reverse proxy, pass it the -proxied flag. this will tell it to read the X-Forwarded-For header when writing logs.

the database has the following layout:

db/
	users.json - the list of users
	{userid}/{year}/{month}/{day}/ - the entry for a given date
		latest - contains the ID of the latest edit, in base 10
		{id} - the full text of edit id

users.json contains an array, each element of which corresponds to a jrnl. it must contain id and passhash. the former is the jrnl username, the latter is the SHA-1 hash of the user's password. it may also contain a timezone field, the value of which should be an IANA time zone name, like "UTC" or "America/New_York". this timezone is used when displaying dates in the UI.

users.json is read once, at startup. if you modify it, you will need to restart the service.

no caching of the database is performed. for a performant experience, make sure your kernel is configured to cache the database directory in RAM.

webjrnl is written in such a way that multiple instances can be pointed to the same database, and access it concurrently without risk of corruption.

for convenience, an openrc script is included at /openrc. edit it to your needs.

#usage

jrnl text is mostly free-form ASCII text, delimited by lines of the form > YYYY-MM-DD. in any text box accepting jrnl text, you may insert such a line anywhere to start a new entry. webjrnl will sort it into reverse chronological order, once it is submitted.

webjrnl does not delete anything. when an entry is edited, the new text is saved as the latest revision. it is not possible to delete an entry or revision, without hand-editing the database.

a typical jrnl excerpt looks something like:

> 2026-04-26

= 1725, cafe =

got webjrnl mostly together, just need to write the docs.

...


> 2026-04-25

= 1020, desk =

I'm SO EXCITED for today!!!

...

the homepage, /dash, has links to a list of entries, an import tool, a backup tool, and each year's page. if there is no entry for today or yesterday, buttons to create them are also presented.

the import tool accepts jrnl text, and populates the database with it. the backup tool exports the entire database as jrnl text, including all revisions. it can be accessed programatically at /save?download

year pages are populated with the jrnl text for a given year, and have a menu to navigate to an entry's page. this is intended as the primary editing frontend.

entry pages allow you to change an entry's text, and contain a list of previous revisions. this is not jrnl text, and does not parse date headings. if you include one, it may lead to unexpected results the next time the entry is parsed as part of jrnl text

#security

some. in particular, POST requests from a different Referer or Origin are blocked, as are all javascript requests from different sites, assuming the browser supports the Sec-Fetch-* set of headers

HTTP basic authentication is very much so insecure over an unencrypted connection.

the contents of the database are stored in plaintext.

#compatibility

needs testing:

  • netscape (the real one, not the chrome reskin)
  • netpositive
  • kaios
  • wii browser channel
  • ds browser
  • WorldWideWeb
  • hotjava
  • original ms edge
  • konqueror
  • older internet explorer versions
  • original opera
  • early mozilla
  • early chrome
  • seamonkey
  • others

works, no notes:

  • any modern web browser probably. works in librewolf
  • lynx
  • w3m
  • microsoft internet explorer 6
  • k-meleon
  • eww (thanks d6!)
  • epiphany
  • DSi browser

works with caveats:

  • links2: textareas start scrolled to the bottom, so the year pages are a bit annoying.
  • netsurf: textareas with a lot of data in them are laggy to edit, so the year pages are annoying to work with
  • plan 9 mothra: textareas are buggy, which makes any editing besides entry creation a chore
  • wine internet explorer: 401s aren't handled; you need to manually add the user:pass@ to the URL. navigating with the back button breaks this
  • dillo: some weird caching behavior that requires manual reloads at times, ignores content-disposition on /save
  • NCSA mosaic 2.7 (thanks chloe!): working but for redirects. relative Location: is not supported :(

doesn't work:

  • offpunk: no <form> support