Co-authored-by: Greg Sarjeant <1686767+gsarjeant@users.noreply.github.com> Reviewed-on: https://gitea.subcultureofone.org/greg/tkr/pulls/26
tkr
A lightweight, HTML-only status feed for self-hosted personal websites. Written in PHP. Heavily inspired by status.cafe.
Screenshots
Mobile
Desktop
Features
- HTML and CSS implementation. No Javascript.
- Accessible by default
- RSS
/feed/rss
and Atom/feed/atom
feeds - CSS uploads for custom theming
- Custom emoji to personalize moods (unicode only)
I'm trying to make sure that the HTML is both semantically valid and accessible, but I have a lot to learn about both. If you see something I should fix, please let me know!
Prerequisites
- A web server with PHP support, such as:
- Apache with mod_php
- nginx and php-fpm
- PHP 8.2+ with the PDO and PDO_SQLITE extensions
- The PDO and PDO_SQLITE extensions are usually included by default
- This might work with earlier PHP versions, but I've only tested 8.2
Installation
- Download the latest tkr archive from the packages page
- Copy the
.tgz
file to your server and extract it - Copy the
tkr
directory to the location you want to serve it from- on debian-based systems,
/var/www/tkr
is recommended
- on debian-based systems,
- Make the
storage
directory writable by the web server account.chown www-data:www-data /path/to/tkr/storage chmod 0770 /path/to/tkr/storage
- Add the necessary web server configuration.
- Examples for common scenarios can be found in the examples directory.
- Apache VPS, subdomain (e.g.
https://tkr.your-domain.com
): examples/apache/vps/root - Apache VPS, subfolder (e.g.
https://your-domain.com/tkr
): examples/apache/vps/subfolder - Nginx VPS, subdomain (e.g.
https://tkr.your-domain.com
): examples/nginx/root - Nginx VPS, subfolder (e.g.
https://your-domain.com/tkr
): examples/nginx/subfolder
- Apache VPS, subdomain (e.g.
- Any values that need to be configured for your environment are labeled with
CONFIG
. - The SSL configurations are basic, but should work. For more robust SSL configurations, see https://ssl-config.mozilla.org
- Examples for common scenarios can be found in the examples directory.
From git
If you'd prefer to install from git:
- Clone this directory and copy the
/tkr
directory to your web server.- Required subdirectories are:
config
public
src
storage
templates
- Exclude the other directories
- Required subdirectories are:
- Follow the main installation from step 4.
Initial configuration
- Edit
config/init.php
to set the domain and base path correctly for your configuration.- subdirectory installation (e.g. https://my-domain.com/tkr)
'base_url' => 'https://my-domain.com', 'base_path' => '/tkr/',
- subdomain installation (e.g. https://tkr.my-domain.com)
'base_url' => 'https://tkr.my-domain.com', 'base_path' => '/',
- Browse to your tkr URL. You'll be presented with the setup screen to complete initial configuration.
Server configuration notes
The document root should be /PATH/TO/tkr/public
. This will ensure that only the files that need to be accessible from the internet are served by your web server.
There is an .htaccess
file in the tkr/
root directory. It's designed for the following installation scenario:
- shared hosting
tkr/
is installed totkr/
under your web root. (e.g.public_html/tkr
).tkr/public
is the document root- The other application directories are blocked both by
tkr/.htaccess
and by.htaccess
files in the directories themselves. These are:tkr/config
tkr/examples
(not technically an application directory, but distributed with the .zip archive)tkr/src
tkr/storage
tkr/templates
Docker compose
The docker directory contains docker-compose.yml files and web server configs for some different server configurations. For simplicity, these do not use SSL.
To run tkr locally on your machine, copy the docker-compose file you're interested in to tkr/
and run docker compose up
.
Accessibility Note
The "Strict Accessibility" setting (enabled by default) addes tabindex="0"
to all <a>
tags to force them to get tab focus. This isn't strictly best practice. The <a>
tag should get tab focus by default. But I've learned that some browsers (at least Safari and Vivaldi) disable this in their default configurations, making accessibility an opt-in feature.
If you'd like to revert to the standard behavior, toggle this setting off. But know that people who navigate by keyboard may have to reconfigure their browser settings in order to select hyperlinks.
Storage
Ticks are stored in files on the filesystem under /tkr/storage/ticks
. This directory must be writable by the web server user and so SHOULD NOT be served by the web server. If you set your document root to /tkr/public/
, then you'll be fine.
The file structure is YYYY/MM/DD.txt
. That is, each day's ticks are located in a file whose full path is /tkr/storage/ticks/YEAR/MONTH/DAY.txt
. This is to prevent any single file from getting too large.
Each entry takes the form TIMESTAMP|TICK
, where TIMESTAMP
is the time that the entry was made and TICK
is the text of the entry.
For illustration, here's a sample from the file /tkr/storage/ticks/2025/05/25
on my test system.
# cat /tkr/ticks/2025/05/25.txt
23:27:37|some stuff
23:27:45|some more, stuff
SQLite Database
tkr stores profile information, custom emojis, and uploaded css metadata in a SQLite database located at tkr/storage/db/tkr.sqlite
.
You don't have to do any database setup. The database is automatically created and initialized on first run.
Acknowledgements
It's been a lot of fun to get back to building something. I'm grateful to the people and projects that inspired me to do it:
- armaina - Armaina's a talented artist (check out the site!) who had the original idea for a self-hosted PHP version of status.cafe. That sounded like a fun project so I thought I'd see if I could manage it. This project doesn't exist without Armaina. Thank you!
- status.cafe - The technological inspiration. Unless you really want to self-host, you should use status.cafe instead! I took a lot of inspiration from its design and then I made the CSS way heavier and probably lost some of the soul along the way.
- 32-bit cafe - I started in technology as a hobbyist and idealist. Then I became a professional. The decades since have sucked the joy and the hope out of technology. 32-bit cafe reminded me that they're both still there.
Tentative 0.y.z releases to 1.0
I'd like to alternate beteen architecture and feature releases between here and 1.0. This is my current thinking, but these may change.
0.7.5 (architecture improvements)
- Add linting and tests
- Add artifact build pipeline
0.8.0 (features and enhancements)
- Support microformats
- Support h-feed and JSON
0.8.5 (architecture improvements)
- Add docker build and deployment
0.9.0 (features and enhancements)
- Allow customization of time zone and time display for ticks
0.9.5 (architecture enhancements)
- Improve exception handling
- Add logging, including log viewer screen
1.0.0
- Polish README and other docs
- Set up dedicated webpage