esoTalk forum software
esoTalk was a lightweight forum software package written in the PHP scripting language, created by Simon and Toby Zerner. A free software made available under version 2 of the GNU General Public License, esoTalk is the project on which my esoBB forum software is based. On its own, however, the esoTalk project carries with it a rich legacy that deserves to be heard about, and so it goes…
From a strictly personal perspective, esoTalk has played a large role in shaping the course and trajectory of my teenage years, from re-discovering the software while early into high school and through a decade-long venture in web development which has since led me back to the point we are currently at: the release of esoBB 1.0.0d3, which represents the single largest update to both the esoBB and pre-gamma esoTalk codebases, to-date.
Knowing that the original esoTalk project has gone unmaintained for what now amounts to an upwards of 10 years, the vast majority of its information resources have since been reduced to dead links, thus prompting me to take the liberty of documenting as much as I can on this very page. Express credit is given to Alfred Don, a member of the Tormater developer community, for obtaining a number of pre-beta archives from Toby that have since been uploaded to the Internet Archive. Additional credit goes to Video (archivist, GitHub) for co-developing an interest in the software side of things whilst early on.
Introduction
esoTalk was originally concieved in early 2008 by the Australian brothers Simon and Toby Zerner as a pet project for them to create a uniquely ‘modern’ forum software all the while improving upon their coding abilities. The project was in the alpha stage until December 2009, at which point it entered its first beta release. Marketed as “forum software reinvented,” esoTalk beta only contains major functions for discussion if used out of the box. Unlike other Internet forums of the time, an esoTalk forum only included one board and no category, and the only board is also the main page. It was designed to be extensible, and so additional features require plugins, with tags serving as the primary method for categorizing discussions according to their subject (e.g. tag:introduction) and gambits for tangible qualities, such as locked/private/draft status.
The pre-beta codebase (2008-2011)
1.0.0b (beta) represents the beta branch of the codebase, of which there are three releases: beta 1, beta 2 and the unfinished beta 3 (1.0.0b3) from which the esoBB codebase was originally derived. The stack is PHP 5.x with the classic MySQL extension, MyISAM tables by default, UTF-8 throughout and php-gd used for avatar (and potentially Captcha) processing. Friendly URLs can be enabled using mod_rewrite but the software runs fine without it.
Post-beta gamma (2011 onward)
Any timeline of the software’s development is undeniably best characterized by delineating on the basis of the 2011 ‘gamma’ rewrite (1.0.0g1) which, in addition to rewriting the vast majority of the code base, also made drastic changes to the underlying functionality of the software. It was this post-beta “gamma” iteration of the software which would become more widely known, entering into service for something within the range of a couple thousand individual forums.
Due to the elevated importance of the pre-beta codebase in regards to the esoBB project, most of the following technical information will pertain to esoTalk versions 1.0.0b3 and prior, rather than the successive releases. In the future, this page may be further extended to provide more information regarding the post-beta gamma releases.
Design philosophy
esoTalk 1.0.0 beta was built to be lean and modern, with an almost spartan philosophy: a single tag-driven board instead of sprawling categories, with gambit-style search and just enough core to make conversation fast. It relies on a tiny, hookable core (Hookable/Controller/Plugin) so that may features live in plugins, while skins and language packs own the presentation. The emphasis is on speed, simplicity, and extensibility over bloat, thereby leaving admins with time to assemble only what they need.
Database schema
Tables are few and direct: conversations and posts for the core thread model; status for per-user conversation state (allowed, starred, lastRead, draft); members for accounts, roles, avatars, and preferences; tags for topic labeling; searches for rate tracking. Indexes favor recency and participation (start time, last post time, posts count). The installer seeds a welcome set of conversations and tags and provisions the root admin.
Requests and page rendering
Every request enters through index.php (or ajax.php when AJAX_REQUEST is defined). The bootstrap in lib/init.php merges configuration, checks versions, loads the language pack, pulls in the skin, and then discovers any enabled plugins. Routing is simple: the first URL segment (q1) selects a controller (conversation, search, join, settings, plugins, skins, profile, feed, etc.), with numeric q1 mapped automatically to the conversation controller for convenience. The controller’s init() prepares data; its render() hands off to the skin-resolved view inside the global wrapper (views/wrapper.php), which handles the page chrome, messages, and hook slots like pageStart, footer, and pageEnd.
Formatter
User text is formatted by a lexer-backed Formatter (lib/formatter.php) that offers modes for inline styling, blocks, lists, quotes, links, images, and code-like fixed text. Plugins can add their own formatters—Emoticons ships as an example—by registering a formatter class and mapping lexer patterns. For feeds, plugins can revert formatting (Emoticons turns images back into text) by hooking formatPost.
Tags and gambits
Users live in a tag-forward world: a single conversation list filtered by tags and “gambits” (search phrases like unread, private, locked, draft, or author:me). Conversations can be private, starred, or saved as drafts. Avatars are stored in avatars/ and can be uploaded or fetched by URL when allowed. Email notifications are opt-in per user for starred conversations and private invites.
Security measures
Input is sanitized early in init.php; sessions bind tokens for CSRF defense; passwords are hashed as md5($salt.$password) (legacy—consider modern hashing if you fork). File uploads rely on GD for processing; keep writable directories tight. The Debug plugin and verboseFatalErrors reveal internals—use them only in controlled contexts.
Configuration
Site-specific settings live in config/config.php (defaults in config.default.php). The installer writes DB credentials, salt, forum title, base URL, cookie name, and other essentials. Skins and plugin enablement are tracked in config/skin.php and config/plugins.php. Keep verboseFatalErrors false in production, and ensure writable paths for config/, avatars/, and upload targets.
Administrators manage plugins and skins through their respective controllers (tied to the admin bar). Uploading a plugin or skin is a matter of providing a zip; the controller unpacks, validates the presence of plugin.php or skin.php, and toggles activation by updating the config files. Languages are added manually by placing files in languages/. For appearance, forumLogo in config/config.php replaces the header image, and skins handle CSS.
Installer notes
Installer loops usually trace back to missing or unreadable config/config.php; skin/language errors point to mismatched names or files. Friendly URL 404s mean mod_rewrite or .htaccess is missing—fall back to useFriendlyURLs without rewrite.
Performance notes
Gzip is enabled by default. The Debug plugin can show query counts and timing. Asset sprites (icons, emoticons) keep requests lean. Tune MySQL (key buffer for MyISAM) and consider an opcode cache on the PHP side.
Upgrading your forum
Upgrades follow a simple pattern: backup DB and custom assets, upload new code, visit /upgrade/, and re-enable or update plugins/skins as needed. Version checks live in config/versions.php.
Due to the pre-release nature of the esoTalk beta releases, conducting an upgrade from version 1.0.0b2 to beta 3 (1.0.0b3) requires for some slight modifications to be made to the database (as indicated by the SQL error that may be displayed by the controller immediately after completing the aforementioned upgrade process).
Extensibility
Designed to be extensible from out of the box, at the center of the codebase is the Hookable base, whose addHook/callHook pair drives every extension story. Controllers inherit it so they can expose markers such as beforeGetPosts, validateAddReply, or head, while plugins register callbacks to those markers. The Plugin class adds a small lifecycle—version-aware init(), optional enable(), upgrade(), and settings read/write through writeConfigFile. The Skin class governs how views are resolved (registerView, getView) and how UI chrome is emitted (e.g., overriding button() or enqueuing CSS/JS in init()).
Plugins
Plugins live under plugins/{Name}/plugin.php, with the directory name matching the class. Captcha adds a join-form fieldset and validates GD; Emoticons registers a formatter and feed reverter; Debug instruments database hooks and appends a live diagnostics panel. To write your own, define IDs, names, and versions, call parent::init() for automatic upgrades, register hooks that scope to relevant actions (e.g., only act when $this->esoTalk->action == "join"), and keep configuration in a $defaultConfig array that will be materialized into config/{Name}.php.
The default Plastic skin demonstrates the model: a skin.php class that enqueues CSS and favicon assets and optionally wraps form controls. Any view under views/ can be overridden by calling registerView inside the skin and placing the replacement file in the skin directory. Color pickers in the user settings are driven by the skin’s $numberOfColors and corresponding .c1, .c2, … classes in its stylesheet.
Skins
The default Plastic skin demonstrates the model: a skin.php class that enqueues CSS and favicon assets and optionally wraps form controls. Any view under views/ can be overridden by calling registerView inside the skin and placing the replacement file in the skin directory. Color pickers in the user settings are driven by the skin’s $numberOfColors and corresponding .c1, .c2, … classes in its stylesheet.
Language packs
Language files are simple PHP arrays in languages/, each declaring "charset" => "utf-8" and mapping keys to strings. Users may choose their own language; admins set the default via config/config.php. Plugins add their own keys at runtime with addLanguage.