tkr
A lightweight, HTML-only status feed for self-hosted personal websites. Written in PHP. Heavily inspired by status.cafe.
Features
- HTML and CSS implementation. No Javascript.
- RSS /feed/rssand Atom/feed/atomfeeds
- CSS uploads for custom theming
- Custom emoji to personalize moods (unicode only)
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 https://subcultureofone.org/files/tkr/tkr.0.6.0.zip
- Copy the .zip file to your server and extract it
- Copy the tkrdirectory to the location you want to serve it from- on debian-based systems, /var/www/tkris recommended
 
- on debian-based systems, 
- Make the storagedirectory writable by the web server account.- For example, on nginx on debian-based distributions:
 chown www-data:www-data /path/to/tkr/storage
- Add the necessary web server configuration
- Examples for common deployment scenarios, including documentation, are in the examples directory.
 
From git
If you'd prefer to install from git:
- Clone this directoryand copy the /tkrdirectory 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 2.
Initial configuration
- Edit config/init.phpto 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 deployed installed to- tkr/under your web root. (e.g.- public_html/tkr).
- tkr/publicis the document root
- The other application directories are blocked both by tkr/.htaccessand by.htaccessfiles 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
 
There are example configurations for other common scenarios 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
Docker compose
The example directories contain docker-compose.yml files for the different configurations. To run tkr locally on your machine, copy the docker-compose file you're interested in to tkr/ and run docker compose up.
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.
You don't have to do any database setup. The database is automatically created and initialized on first run.
TODO
- Validate HTML semantics on all pages
- Validate accessibility on all pages
- Add logging, including log viewer screen
- Improve exception handling
- Support microformats
- Support h-feed and JSON
- Allow customization of time zone and time display for ticks
- Probably a bunch of other stuff I'm not thinking of
