Ty Clifford 75d38d4eb8 - I made both surfaces friendlier to screen readers.
CMS changes landed in 
[layout.php](/Users/tyemeclifford/Documents/GH/blog/themes/neon/layout.php), 
[style.css](/Users/tyemeclifford/Documents/GH/blog/themes/neon/assets/style.css), 
[app.js](/Users/tyemeclifford/Documents/GH/blog/themes/neon/assets/app.js), 
and 
[lone-embed.php](/Users/tyemeclifford/Documents/GH/blog/lone-embed.php): 
skip link, named search/forms, current page state, live notices/empty 
states, labelled media/embed controls, visible focus states, theme 
control pressed states, and a focus-trapped/lightbox dialog with proper 
ARIA.
Mac app changes landed in 
[main.m](/Users/tyemeclifford/Documents/GH/blog/macclient/AppKitClient/main.m), 
and I rebuilt 
[TCMS](/Users/tyemeclifford/Documents/GH/blog/macclient/TCMS.app/Contents/MacOS/TCMS): 
AppKit controls/tables/fields/previews now get accessibility 
labels/help/value text, workspace sections are named, media/comment 
tables expose useful context, and status messages are announced via 
macOS accessibility notifications.
2026-07-05 23:36:27 -04:00
2026-07-05 16:23:17 -04:00
2026-07-04 20:19:56 -04:00
2026-07-04 20:19:56 -04:00
2026-07-04 21:53:18 -04:00
2026-07-04 19:41:44 -04:00
2026-07-05 16:23:17 -04:00
2026-07-05 16:23:17 -04:00
2026-07-04 19:41:44 -04:00
2026-07-05 21:34:14 -04:00
2026-07-05 16:23:17 -04:00

Ty Clifford's Content Management System

Ty Clifford's Content Management System, or TCMS, is a dark-neon PHP blog CMS built around portable files, clean URLs, and a dedicated native Mac client.

Feature Showcase

  • Bludit-style content folders make copying or importing posts simple: bl-content/pages/<slug>/index.txt.
  • Trusted author rendering parses Markdown while allowing raw HTML, iframes, JavaScript, and executable PHP blocks inside posts/pages.
  • Shortcodes are declared in config/shortcodes.php or config/shortcodes.json, including [youtube=<id>] and [video poster=<poster> file=<file>].
  • Embed support uses lone-embed.php for generated full-frame HTML5 video players, while YouTube shortcodes render privacy-friendly iframe embeds.
  • The AppKit macOS 12+ client, TCMS.app, manages posts, pages, media, comments, autosave, API login, publishing, updates, and deletes.
  • Blog essentials are included: pretty URLs, search, pagination, static pages, tags, categories, social links, moderated comments with captcha/honeypot, SQLite, JSON, and Excel-ready CSV stats.

Details

TCMS uses a Bludit-style content layout:

bl-content/pages/<slug>/index.txt

Posts and static pages are Markdown .txt files with front matter. Comments live in SQLite, site configuration and generated indexes are JSON, and visit stats are CSV for easy Excel import.

Post and page bodies are treated as trusted author content. Markdown is rendered while allowing raw HTML, iframes, JavaScript, and executable PHP blocks inside the .txt files.

Shortcodes are declared in config/shortcodes.php as a PHP array, with optional JSON overrides in config/shortcodes.json.

[youtube=dQw4w9WgXcQ]
[video poster=poster.jpg file=file.mp4]

[video] renders an iframe pointed at lone-embed.php, which serves the full-frame HTML5 video player. Bare filenames resolve from bl-content/uploads.

Requirements

  • PHP 8.1 or newer
  • PDO SQLite enabled
  • Apache with mod_rewrite for .htaccess pretty URLs, or the PHP built-in server for local testing

Local Server

php -S 127.0.0.1:8080 router.php

CLI

php cli/blog.php help
php cli/blog.php list --all
php cli/blog.php create "New Post" --status=published --category=Notes --tags=php,markdown
php cli/blog.php update hello-neon --title="Hello Neon"
php cli/blog.php delete old-slug
php cli/blog.php rebuild

Mac Client and API

The native AppKit macOS 12+ client lives in macclient/.

cd macclient
./build-app.sh
open TCMS.app

Point the client at any TCMS site URL. It will call api.php at that site for posts, pages, media, comments, local autosave, and optional remote draft autosave.

API credentials are stored in the site root .env file:

TCMS_API_ENABLED=true
TCMS_API_USERNAME=admin
TCMS_API_PASSWORD=change-this-password
TCMS_API_PASSWORD_HASH=

The Mac client authenticates with the .env username and password. Use TCMS_API_PASSWORD_HASH with password_hash() output instead of TCMS_API_PASSWORD for production.

Comments

Comments are moderated by default and protected by captcha plus a honeypot field.

php cli/blog.php comments:list --status=pending
php cli/blog.php comments:approve 1
php cli/blog.php comments:spam 2
php cli/blog.php comments:delete 3

Import Bludit

Import from a local directory on the server. The source can be the old Bludit root or the old bl-content folder.

php cli/import-bludit.php /var/www/old-bludit --dry-run
php cli/import-bludit.php /var/www/old-bludit
php cli/import-bludit.php /var/www/old-bludit/bl-content
php cli/import-bludit.php --source=/var/www/old-bludit --overwrite

The importer preserves original publish dates, modified dates, post/static-page type, draft/published state, categories, tags, authors, cover image metadata, allow-comments flags, page order, page-local files, and bl-content/uploads.

It also scans local comment export files under the old bl-content/databases and bl-content/workspaces directories. To point it at a specific local comment export:

php cli/import-bludit.php /var/www/old-bludit --comments=/var/www/old-bludit/comments.json

Stats

Visits are appended to storage/stats/visits.csv with a header row suitable for spreadsheet import.

php cli/blog.php stats:summary

Apache

The included .htaccess enables pretty URLs and blocks direct access to app code, configuration, .env, the Mac client source, SQLite, CSV, JSON databases, and Markdown content files.

For a subdirectory install such as https://example.com/blog, either place the app in that folder and let the CMS auto-detect the path, or set:

{
  "base_url": "https://example.com/blog",
  "base_path": "/blog"
}

base_path controls generated links, assets, forms, RSS, and sitemap paths.

S
Description
Ty's Content Management System.
https://tyclifford.com/blog
Readme 2.9 MiB
Languages
PHP 53.9%
Objective-C 34%
CSS 6.1%
JavaScript 5.7%
Shell 0.3%