GopherPress
WordPress plugin that serves your site over the Gopher protocol (RFC 1436)
by Derrick Tennant · github.com/emrikol/gopherpress · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/emrikol/gopherpress/archive/refs/heads/main.zipReadme
GopherPress
Serve your WordPress site over the Gopher protocol (RFC 1436). Because the web peaked in 1991.
____ _ ____
/ ___| ___ _ __ | |__ ___ _ __| _ \ _ __ ___ ___ ___
| | _ / _ \| '_ \| '_ \ / _ \ '__| |_) | '__/ _ \/ __/ __|
| |_| | (_) | |_) | | | | __/ | | __/| | | __/\__ \__ \
\____|\___/| .__/|_| |_|\___|_| |_| |_| \___||___/___/
|_|
Serving the web since 1991.
Overview
GopherPress runs a lightweight Gopher TCP daemon from inside WordPress, turning your posts, pages, and categories into a proper Gopher hole. It also exposes a REST endpoint so Gopher content is always reachable over HTTP — useful for managed hosts, curl, and the bundled local proxy.
Three ways to browse your site over Gopher:
| Mode | How | Requires |
|---|---|---|
| Native daemon | Point any Gopher client at gopher://yoursite.com:7070/ |
exec() or proc_open() on the server |
| REST endpoint | GET /wp-json/gopherpress/v1/serve?selector= |
Nothing — always available |
| Local proxy | Run node gopher-proxy.js locally, then use any Gopher client |
Node.js on your machine |
Requirements
- WordPress 5.9+
- PHP 8.0+
exec()orproc_open()for the live daemon (optional — see below)
Installation
Install from the WordPress plugin directory, or drop the plugin folder into wp-content/plugins/ and activate it. Then go to the GopherPress admin page, set your port (default: 7070), and click START.
If exec() and proc_open() are both disabled on your host (common on managed WordPress platforms), the daemon controls are hidden. Your content is still fully accessible via the REST endpoint and the local proxy.
Selectors
| Selector | Content |
|---|---|
(empty) or / |
Root menu |
recent |
Last 10 posts |
categories |
Category list |
category/{slug} |
Posts in a category |
post/{id} |
Individual post (by ID or slug) |
tags |
Tag cloud menu |
tag/{slug} |
Posts with a tag |
authors |
Author list |
author/{slug} |
Posts by an author |
archives |
Archive menu |
archives/{year} |
Year menu |
archives/{year}/{month} |
Month post list |
about |
About page |
about-gopher |
Gopher protocol history document |
search\t{query} |
Full-text search (Type-7) |
gopher |
ASCII gopher art |
secret |
Alias for about-gopher |
Post documents render with FIGlet ASCII art headings, inline images converted to aalib ASCII art, and [LINK: text → url] substitutions for hyperlinks.
Local proxy
The local proxy lets you browse your site with any legacy Gopher client without opening a public TCP port. It's a zero-dependency Node.js script that listens locally and forwards selectors to the GopherPress REST endpoint over HTTP.
Get the script
Download gopher-proxy.js from the Local Proxy section of the GopherPress admin page, or grab it directly from this repo at proxy/gopher-proxy.js.
Run it
node gopher-proxy.js --url=https://yoursite.com
By default it listens on localhost:7070. Use --port to change that:
node gopher-proxy.js --url=https://yoursite.com --port=7071
Browse
Point any Gopher client at gopher://localhost:7070. For example, with Lynx:
lynx gopher://localhost:7070
Options
| Flag | Default | Description |
|---|---|---|
--url |
(required) | Base URL of your WordPress site |
--port |
7070 |
Local port to listen on |
The proxy binds to 127.0.0.1 only — it is not reachable from other machines on your network.
Development
Prerequisites: Composer, PHP 8.0+
git clone https://github.com/emrikol/gopherpress.git
cd gopherpress
composer install
npm install
Scripts
composer test # Run PHPUnit test suite
composer test:coverage # Run tests with coverage report
composer lint # Run PHPCS (WordPress Coding Standards)
composer lint:fix # Run PHPCBF auto-fixer
composer stan # Run PHPStan static analysis
composer dist # Build distributable zip → dist/gopherpress-{version}.zip
npm run lint:js # Run ESLint
Project structure
gopherpress.php # Plugin entry point, constants, hooks
inc/
class-admin.php # Admin page, AJAX handlers
class-content.php # Gopher content dispatcher (menus, posts, pages)
class-daemon.php # Daemon process management (start/stop/status)
class-rest.php # REST endpoint
class-figlet.php # FIGlet ASCII art renderer
class-aalib.php # AAlib ASCII art renderer (images → ASCII)
gopher-server.php # Gopher TCP server (spawned as a child process)
polyfills.php # WP function backports
assets/
admin.css # Retro terminal admin styles
admin.js # Admin page JS (AJAX controls, live log polling)
proxy/
gopher-proxy.js # Local Node.js proxy — bridges Gopher clients to the REST endpoint
tests/ # PHPUnit test suite
Tests use PHPUnit 11 with WordPress stubs — no running WordPress instance required.
Contributing
This is a personal project. Issues and pull requests are not accepted. See CONTRIBUTING.md.
License
GPL-2.0-or-later. See LICENSE.