🦅 EaglePress v2.01 is here! Hot off the Press!

🦅 EaglePress v2.01 is here! Hot off the Press!
Download link: EaglePress Latest Version v2.01 eaglepress.zip

I am Stan Switaj, the programmer of EaglePress and owner of EaglePress.org. If you need paid support of EaglePress CMS for any reason. Need an update, ok ask. Need a feature to a plugin or have an idea for a new theme, I'm ready to help, my email is opensource3@yahoo.com.

• • •

EaglePress v2.01 — A 395 KB zip file (6 bundled themes including the new RedWhiteBlueTheme + ModernTheme via marketplace). Python 3, PostgreSQL as the database. No framework. A mountain of CMS features — more themes and plugins coming soon.

SHA-512 hash of EaglePress v2.01:

running
sha512sum eaglepress.zip
shows
c8013a9e6afac1b21635821ee01c77ca4a83aead259e412cbbe4ce7189e61e66441d15361c5170a3547a47c65dfdbfec82966bb30f52e5852387841b971f312a

• • •

🦅 What's New in v2.01 — Go Language, Mobile UX, Smart Updater & New Theme

🐹 Go Programming Language Support

EaglePress now supports Go as the 14th canonical language in the syntax highlighting engine — both for auto-detection and in the code block language selector. Fence with ~~~go or ~~~golang. The score-based detector uses 16 weighted signals unique to Go: package declarations, := short variable declarations, defer statements, goroutine launches, channel operators, method receivers, and standard library package references (fmt, os, sync, net/http, etc.).

• • •

📱 EaglePressTheme Mobile Hamburger — Redesigned

The mobile hamburger dropdown on EaglePressTheme is now a proper slide-out menu pinned below the sticky header — full-width navy background, gold accent border, and large 15 px tap targets. 🎨 Themes and 🔌 Plugins appear as plain, accessible links in the dropdown (the gold group border and "Marketplace" label only show on desktop where there is room for them).

• • •

🔧 Code Block Toolbar — Mobile Ready

On screens ≤640 px the language text label is replaced by a 💻 emoji button that shows a tap-dismissible tooltip with the detected language name. The "Wrap" label becomes to save space. Desktop toolbar is unchanged.

• • •

🔄 Smart Updater — SHA-512 + Timestamp Fingerprinting

The one-click updater can now detect when you upload a new archive with the same version number — no more having to manually click Reinstall. The distribution API now returns the archive's zip_mtime (modification timestamp) alongside its SHA-512. After each install, both values are stored in the database. On the next check, if either differs from the stored values, the Dashboard shows "Updated Package Available — v2.01 (same version, new content)" with a 🔄 Apply Updated Package button. The Dashboard card also displays the installed SHA-512 (first 24 characters) so you can verify your running installation at a glance.

• • •

🎨 RedWhiteBlueTheme — New Bundled Theme

RedWhiteBlueTheme is a new patriotic American Stars & Stripes theme bundled with EaglePress v2.01:

  • Deep navy header with diagonal stripe texture and a 4 px crimson bottom border
  • Crimson red buttons and links throughout (USATheme influence)
  • Gold ★ stars in the logo, sidebar widget titles, and footer
  • 3-colour stripe divider (red/white/blue) between the hero and the post grid
  • Thin stars banner below the header
  • Full dark mode, reading progress bar, image lightbox, and all standard theme features
  • ☀ / 🌙 light/dark mode toggle

💡 Existing installations get all v2.01 improvements automatically via the One-Click Updater.

• • •

🦅 What's New in v2.00 — Reader Defaults, EaglePressTheme & More

Reader Defaults

Three new Dashboard settings let you control the out-of-the-box experience for every visitor:

SettingDescription
Default Page ThemeLight or dark — applied on first visit before any localStorage preference is saved
Default Code Block ThemeWhich syntax-highlighting theme new code blocks start with
Default Code Block ModeLight or dark mode for every new code block

All five bundled themes (firstTheme, secondTheme, americanTheme, USAtheme, NewsTheme) and the admin panel now read this setting in their anti-FOUC inline script instead of hardcoding 'light'.

EaglePressTheme — Official Showcase Theme

A brand-new installable theme designed for eaglepress.org, now included in the bundle:

  • Deep navy + gold colour scheme — Playfair Display headings, Inter body
  • Home page with full-bleed hero post, card grid, and sidebar
  • /themes gallery — preview images, version badges, Download + Preview buttons for every theme in the repository
  • /plugins directory — Download + Source (GitHub) buttons for every plugin
  • Notice banner on non-eaglepress.org installs explaining the theme's distribution purpose
  • Dark mode, full syntax highlighting, responsive layout
  • Available in the Themes marketplace as 2_EaglePressTheme

New Core Routes

RouteBehaviour
Theme gallery (eaglepress.org) or redirect card to eaglepress.org/themes
Plugin directory (eaglepress.org) or redirect card to eaglepress.org/plugins
Live preview of any installed theme using the first published post

Global Lists System

A new Update Global Lists button in the Distribution Manager scans all theme and plugin zips in the repository, reads their manifests, and writes global_theme_list.json + global_plugin_list.json — the JSON files that power the /themes and /plugins showcase pages.

💡 Existing installations get all v2.00 improvements automatically via the One-Click Updater.

• • •

Every code block now has an independent light/dark mode toggle button — the 💡 / 🔅 emoji button placed between the word-wrap checkbox and the theme dropdown.

StateButtonBorder
Light mode💡 lightbulbYellow
Dark mode🔅 low-brightnessGreen

Key features:

  • Each code block is completely independent — toggling one block does not affect any other
  • Default is always light mode on first visit
  • Mode is persisted per block in localStorage (keyed by page path + block index), just like word-wrap and theme preferences
  • All 10 themes now have both a light and a dark variant:
ThemeLightDark
GitHubCDN githubCDN github-dark
Atom OneCDN atom-one-lightCDN atom-one-dark
MonokaiCustom (cream #fafaf6)CDN monokai
Visual StudioCDN vsCDN vs2015
NordCustom (Snow Storm #eceff4)CDN nord
AgateCustom (#f5f5f5)CDN agate
XcodeCDN xcodeCustom (#1d1f20)
ClassicCDN defaultCustom (#1e1e1e)
Notepad++Custom (white)Custom (#1e1e1e)
KateCustom (white)Custom (KDE Breeze #232629)

Previously separate paired entries (github + github-dark, atom-one-dark + atom-one-light, etc.) are now a single unified entry — the theme dropdown went from 13 entries to 10.

ModernTheme: The "Register" navigation and footer link has been renamed to "Create Account". The site title / tagline hover now lifts with a smooth animation and glow instead of dimming.

💡 Existing installations get all v2.00 improvements automatically via the One-Click Updater.

• • •

🎨 What's New in v1.98 — Kate Syntax Theme

A new Kate colour theme is now available in every code block's theme selector dropdown — a clean light theme inspired by the KDE Kate editor's Default KSyntaxHighlighting palette.

Colour scheme:

TokenColour
💬 CommentsGrey #898887
🔴 Plain strings ('…' / "…")Red #bf0303
🟠 F-strings / template literalsBold orange #ff5500
🔵 {interpolation} inside f-stringsBold sky blue #3daee9
⚫ Keywords — if, for, while, def, class, fnBold near-black #1f1c1b
🔷 Literals — True / False / None / nullBlue #0057ae
🟡 NumbersOchre #b08000
⚫ OperatorsNear-black #1f1c1b
🟣 Built-in functions & function namesPurple #644a9b
🔷 Class names & typesBlue #0057ae
🟢 Decorators / preprocessor (@property, #[derive], #include)Green #006e28
🔷 Variables — $var, @arr (Bash/PHP/Perl)Blue #0057ae
🟣 Regular expressionsPurple #924c9d
⚫ HTML tag namesNear-black #1f1c1b
🔷 HTML attribute namesBlue #0057ae
🔴 HTML attribute valuesRed #bf0303
🔷 CSS tag selectorsBlue #0057ae
🟣 CSS class selectorsPurple #644a9b
🔴 CSS id selectorsRed #bf0303

No CDN dependency — all colour rules live in styles_content.css; no extra network request is made when selecting this theme. Available on every code block in admin and frontend.

💡 Existing installations get the Kate theme automatically via the One-Click Updater — no manual steps required.

• • •

🎨 What's New in v1.97 — Notepad++ Syntax Theme

A new Notepad++ colour theme is now available in every code block's theme selector dropdown — a crisp light theme with distinct, high-contrast colours for every token type.

Colour scheme:

TokenColour
💬 CommentsGrey #808080
🔴 Plain strings ('…' / "…")Red #cc0000
🟠 F-strings / template literalsBold orange #ff8c00
🔵 {interpolation} inside f-stringsBold light blue #4fc3f7
⚫ Keywords — if, for, while, def, class, fnBold black
🔷 Literals — True / False / None / nullDark blue #000080
🟣 NumbersMagenta #c000c0
🟥 OperatorsDark red #8b0000
🟢 Function & class namesDark green #006400
🟣 Built-in functionsDark purple #800080
🫒 Decorators / preprocessor (@property, #include, #[derive])Olive #808000
🩵 Variables — $var, @arr, %hash (Bash/PHP/Perl)Sky blue #87ceeb
🟣 Regular expressionsPurple #800080
🩵 HTML tag namesBold turquoise #00ced1
🔴 HTML attributesRed #cc0000
🔷 CSS selectorsDark blue #000080

F-string detection — the JS engine adds class ep-fstring to any .hljs-string span that contains a .hljs-subst child (interpolated expression), so plain strings and f-strings can be coloured differently without browser-specific CSS selectors. Works in all modern browsers.

No CDN dependency — all colour rules live in styles_content.css; no extra network request is made when selecting this theme. Available on every code block in admin and frontend.

💡 Existing installations get the Notepad++ theme automatically via the One-Click Updater — no manual steps required.

• • •

🦀 What's New in v1.96 — Rust Syntax Highlighting

EaglePress now includes Rust as a fully supported language in the syntax highlighting engine — both for score-based auto-detection and in the editor language selector dropdown.

Detection signals — the auto-detector accumulates weighted scores from Rust's most distinctive patterns:

  • let mut bindings, use std:: imports, impl blocks, fn signatures with return types
  • Macro invocations: println!(), vec![], panic!(), assert_eq!()
  • Type parameters: Vec<T>, Option<T>, Result<T, E>, HashMap<K, V>, Arc<T>
  • Attribute macros: #[derive(...)], #[allow(...)], #[cfg(...)], #[test]
  • Pattern matching: match … { Some(x) => … }, .unwrap(), .expect(), .is_some()
  • Lifetime notation: 'a (guarded: Rust added to _APOSTROPHE_LANGS alongside Python, Bash, SQL)
  • Anti-false-positive: ATX heading penalty (-15) prevents Markdown documents from scoring as Rust

In the editor — "Rust" appears in the language selector dropdown in every code block toolbar, using the fence hint rust or the short alias rs.

Rendering — highlight.js handles Rust natively on the front end; no changes to highlight_custom_improved.js were needed.

💡 Existing installations receive Rust support automatically via the One-Click Updater — no manual steps required.

• • •

🆕 What's New in v1.95 — Fresh-Install Fix

Running python3 sql/install.py on a brand-new database failed every time at step 3 with:

ERROR running setup.sql: relation "ep_plugins" does not exist

Root causesetup.sql runs as a single transaction. The two index definitions for ep_plugins were placed before the ep_plugins CREATE TABLE, so PostgreSQL hit them first and aborted the entire install.

Fix — Both index lines moved to immediately after the CREATE TABLE ep_plugins block. Verified with a full clean install on a fresh database — all five steps complete without error.

💡 Existing installations are unaffected. This only impacted fresh installs from v1.94 and earlier.

• • •

example of a Poll_Vote plugin from EaglePress marketplace — notice the map of the United States displaying votes by choice and by state totals

Loading poll...

• • •

🦅 Welcome to EaglePress

EaglePress is a self-hosted, open-source CMS and blog platform built entirely from scratch in Python 3 backed by PostgreSQL. There is no Django, Flask, or any web framework underneath — just a single CGI router, clean SQL, and a theme engine that gives you full control over every rendered pixel. It runs on any Apache or Nginx server with CGI support, installs in minutes, and ships in a zip file under 400 KB.

• • •

🦅 Why EaglePress?

Most open-source CMS platforms carry enormous dependency trees, opaque plugin hooks, and years of legacy compatibility debt. EaglePress is the opposite: a lean, readable, auditable codebase where every feature was written deliberately, every SQL query is parameterized, and every line of code belongs to you.

  • 📦 One dependency — only psycopg2. Everything else is Python standard library.
  • 🔍 Fully readable — the entire router lives in index.py. No magic, no metaprogramming.
  • 🛡️ Security by design — 100% parameterized SQL, PBKDF2-HMAC-SHA256 passwords, XSS escaping throughout.
  • Fast installs — one SQL file + one Python script and you're live.
  • 🎨 Theme freedom — drop a directory into themes/ and you have a new theme.

• • •

✨ Feature Highlights

🚀 One-Click Automatic Updates

The Distribution Manager and Auto-Update System make upgrades completely effortless. The Dashboard displays a live version-check banner any time a new release is available. One click downloads the new release from eaglepress.org, verifies the SHA-512 checksum, extracts the archive, deploys all files, and runs any pending database migrations automatically — no SSH session, no manual file copying, no downtime.

• • •

🎨 Theme Marketplace with Live Previews

Install and switch themes entirely from the admin panel. Dashboard → Themes → Browse Repository lists every available theme with:

  • 🖼️ Live preview thumbnail images — see exactly how the theme looks before installing
  • Star ratings — community-rated quality scores
  • 📥 Download counts — see how popular each theme is
  • 🔘 One-click install and uninstall — no file management required

Five themes bundled in every install:

ThemeStyle
🎯 firstThemeClean, minimal blog layout — ideal starting point
📰 secondThemeTwo-column editorial style with sidebar
🇺🇸 americanThemePatriotic accent colors with bold typography
🔴 USAthemeRed-dominant americanTheme variant
🗞️ NewsThemeNews magazine layout — breaking-news ticker, hero card, 3-column post grid, right sidebar, 8-swatch color picker, full dark mode

Available in the marketplace:

ThemeStyle
🌟 ModernThemeBold magazine/news theme — full-width image carousel, trending ticker, 2×2 sidebar grid, 8 switchable color palettes, dark mode

• • •

🔌 Plugin Marketplace — Polling & Voting States

One-click plugin installs from Dashboard → Plugins → Browse Repository. Plugin assets load on every theme — including third-party marketplace themes — because EaglePress injects plugin CSS and JavaScript centrally via index.py, never relying on theme templates to know about plugins.

📊 Polling & Voting States — the first published EaglePress plugin

Embed live, interactive polls anywhere in a post or page using a single copy-paste shortcode block.

Core features:

FeatureDescription
🗳️ Multiple question typesyes/no, multiple choice, and open-ended polls — mix types in the same post
🗺️ United States vote mapResults visualized on a color-coded SVG map of all 50 states — per-choice and total vote counts per state
🔄 Real-time vote countersTallies update live without a page reload
📋 Copy-paste shortcodeThe 📊 Poll toolbar button inserts the block — no syntax to memorize
🗑️ Delete questionRemove individual poll blocks without affecting others
📥 Download counterOptional per-poll download tracking
👁️ Accurate admin preview_epPreviewTransforms hook injects temporary data so the Preview tab matches the live result, even before saving
jQuery 4.0 compatibleAll DOM attribute reads use .attr() for full jQuery 4.0 compatibility

• • •

✏️ Powerful Markdown Editor

  • 👁️ Live split-pane Markdown preview — renders as you type, 2-second debounce
  • Smart auto-save — first keystroke creates a draft in the database and assigns a live URL immediately
  • 🔒 Stale-tab guard (v1.94) — dirty flag + staleness detection prevents old tabs from overwriting your work
  • 🛠️ Clean installer (v1.95) — fresh-database installs complete without errors
  • 😊 Emoji picker — 1,500+ emojis across 10 categories with skin-tone selector and live keyword search
  • Markdown Help — toolbar ? button opens a Quick Reference cheat sheet or full Markdown Tutorial modal
  • 🔗 Custom slug control — title-derived, numeric ID, or fully custom URL slugs per post or page
  • 🖼️ Media library picker — insert images and files directly from the toolbar without leaving the editor
  • 📊 Poll toolbar button — one-click shortcode insertion when the Polling plugin is active
  • 📝 Word count — live word counter in the editor status bar

• • •

💡 Custom Syntax Highlighting Engine

EaglePress ships a 100% Python-native syntax highlighter with zero CDN or third-party package dependency:

  • 🌐 13 languages with score-based auto-detection: Python 3, JavaScript, CSS, HTML, PHP, Bash, C, C++, 🦀 Rust, Lua, Perl, SQL, Markdown
  • 🎨 13 colour themes: github-dark, atom-one-dark, monokai, dracula, nord, tokyo-night-dark, github, atom-one-light, solarized-light, vs, xcode, Notepad++, Kate (both custom, no CDN)
  • 🔧 Per-block toolbar: language selector, theme selector, word-wrap toggle, copy button
  • 🏷️ Inline language hint — force any language with =python3 as the first line of a fenced block

• • •

🔒 Security-First Architecture

LayerProtection
🔑 PasswordsPBKDF2-HMAC-SHA256 — 310,000 iterations (NIST-recommended)
🔐 Sessions64-character hex tokens, stored in PostgreSQL, 30-day expiry with IP + user-agent logging
🗄️ Database100% parameterized queries via psycopg2 — zero SQL injection surface
🧹 OutputAll user content routed through html.escape() — zero XSS surface
📁 UploadsExtension + MIME-type whitelist enforced server-side; 10 MB body / 5 MB file hard limits
📋 Error logsPasswords, tokens, cookies, and DB cursors auto-redacted in all CGI tracebacks
🔏 Log permissionsError log files set to 0o600 — readable only by the server process owner

• • •

👥 User Roles & Permissions

EaglePress has a five-tier role system giving you fine-grained control over who can do what:

RoleWhat They Can Do
👑 AdminFull access — manage all posts, pages, media, users, settings, themes, plugins, and the Distribution Manager
📝 EditorPublish and edit all posts and pages regardless of author; manage categories, tags, and comments; access the media library
✍️ AuthorCreate, edit, and publish their own posts; upload media; manage their profile
📬 ContributorWrite posts and submit them for review; cannot publish directly — an admin or editor must approve
👤 SubscriberRead content, leave comments, manage their own profile and avatar — no content creation access

Role changes take effect immediately from Admin → Users. Each role restriction is enforced server-side on every AJAX endpoint — client-side UI changes alone cannot bypass them.

• • •

📖 Rich Reader Experience

  • 🌙 Light/dark mode toggle — OS preference detected on first visit, then user-controlled; zero-flash anti-FOUC inline script
  • 🔍 Image lightbox with keyboard navigation (arrow keys + Escape)
  • 📊 Reading progress bar — smooth scroll-position indicator
  • ❤️ Like button — localStorage-backed, no login required
  • 🔗 Social share — Copy link, Twitter/X, Facebook
  • 💬 Threaded comments with moderation queue
  • 👤 User profiles with avatar upload and Gravatar fallback
  • 🌀 Lazy image loading with fade-in scroll animations

• • •

⚙️ Admin Panel

  • 📈 Dashboard — live stats (posts, pages, comments, media, users), drafts panel, pending-review count, and version-check banner
  • 📝 Post & page editor — categories, tags, featured image picker, comment toggle, slug control, status workflow
  • 🖼️ Media library — upload, browse, delete; paginated 24-item grid with thumbnail previews and file-type badges
  • 👥 User management — list all users, change roles, delete accounts
  • 🛡️ Comment moderation — approve, mark as spam, or trash with one click
  • 🗂️ Category management — create, rename, delete; live post counts
  • 🔧 Site settings — auto-save interval, active theme, default slug type, site name, and more
  • 🎨 Theme manager — installed themes with preview, one-click activate, uninstall
  • 🔌 Plugin manager — installed plugins with enable/disable toggle
  • 📦 Distribution Manager — upload new releases, manage the update feed (eaglepress.org only)

• • •

Screen Images of EaglePress

View some images of EaglePress: image1 , image2, image3 from my blog post of EaglePress Screen Images of the One Click Automatic Update

Images of the GUI editor, and others

Images of EaglePress Editor and Dashboard

Configuration of EaglePress

--- how to configuration of Apache2 / Nginx
--- GitHub EaglePress v1.83 <-- version is outdated, though simply update the version if you try it with the one-click automatic update feature to version 2.01.

Markdown + HTML
# EaglePress — Summary Project Press

**Platform:** Python 3 CGI + PostgreSQL Web Publishing System
**Current Version:** 2.01
**Date:** May 2026

---

## What Is EaglePress?

A self-hosted, open-source CMS and blog platform built entirely in Python 3 and PostgreSQL. No web framework. No ORM. Runs on any Apache or Nginx server with CGI support.

---

## Core Highlights

- Pure Python 3 CGI router — zero external framework dependency
- PostgreSQL backend — 10 normalized tables, FK constraints, indexed queries
- Zero-config installer — one SQL file + one Python script sets up everything
- Clean URL routing via `PATH_INFO` with `?r=` fallback
- Full theme system — drop-in theme directories, exec-based renderer

---

## Security

- PBKDF2-HMAC-SHA256 passwords — 310,000 iterations (NIST-recommended)
- Session tokens — 64-character hex, stored in DB, 30-day expiry with IP + user-agent logging
- 100% parameterized queries — no SQL injection surface
- XSS protection — all output routed through `html.escape()`
- Upload safety — extension + MIME-type whitelist, server-side enforced
- CGI errors isolated to `tmp_errors/` — never exposed to visitors

---

## CGI Library — `cgi_improved2.py`

A custom drop-in replacement for Python's deprecated `cgi` and `cgitb` standard library modules, written specifically for EaglePress.

**Parsing architecture:**
- Streaming 64 KB-chunk multipart parser — peak memory scales with the largest single part, not the total body
- Replaces the legacy approach of reading the entire POST body into RAM before parsing

**Hard request limits:**
- 10 MB maximum total POST body
- 5 MB maximum per uploaded file
- 200 maximum form fields per request
- 70-byte maximum boundary length (RFC 2046)
- 1024-byte maximum uploaded filename length

**Security measures built into the library:**
- RFC 5987 filename decoding — handles `filename*=UTF-8''encoded` form
- Charset validation for text parts against a safe-charsets allowlist
- Error log redaction — sensitive local variable names (`password`, `password_hash`, `token`, `session`, `USERNAME`, `PASSWORD`, `cc_number`, database cursors, raw request body) are replaced with `<redacted>` in all traceback logs
- HTTP header redaction — `HTTP_COOKIE`, `HTTP_AUTHORIZATION`, `HTTP_PROXY_AUTHORIZATION` stripped from logged environment dumps
- Log file permissions set to `0o600` — readable only by the server process owner
- Traceback output suppressed from HTTP responses by default (`display=0`)
- Variable repr truncation — log entries capped at 200 characters per value, 30 variables per frame

**Drop-in compatible** — same `cgi.FieldStorage()` / `cgitb.enable()` interface as the standard library.

---

## Content Management

- Posts and pages — draft, published, preview states; soft-delete to trash
- Auto-generated slugs — deduplicated with `-2`, `-3` suffixes
- Categories (hierarchical) and tags
- Featured images, view counter, comment toggle per post
- Comment threading with moderation queue
- User profiles with avatar upload and Gravatar fallback

---

## Markdown Parser

Custom server-side Markdown-to-HTML with no third-party packages:

- ATX headings, bold, italic, strikethrough
- Fenced code blocks with syntax highlighting
- Ordered and unordered lists, blockquotes, horizontal rules
- Extended image syntax — size (`=WxH`), alignment, title
- Download buttons for non-image file links
- Shortcodes for embedding post/page links
- External links auto-tagged `rel="noopener"`
- Raw HTML pass-through

---

## Syntax Highlighting

Custom pure-Python engine (`syntax_highlight.py` + `syntax_themes.py`) — no external packages.

**14 languages** + plain text: Python 3, JavaScript, CSS, HTML, PHP, Bash, C, C++, Go, Rust, Lua, Perl, SQL, Markdown + HTML

**13 colour themes**: github-dark, atom-one-dark, monokai, dracula, nord, tokyo-night-dark, github, atom-one-light, solarized-light, vs, xcode, Notepad++, Kate

**Per-block features:** language label, language selector drop-down, theme selector drop-down, copy button, keyboard navigation

**Score-based auto-detection** — no lang hint needed; fenced block content stripped before scoring to prevent embedded language examples from polluting outer document detection

---

## Frontend Reader Experience

- Image lightbox with keyboard navigation
- Reading progress bar
- Back-to-top button
- Like button (localStorage)
- Social share — Copy link, Twitter, Facebook
- Lazy image loading + fade-in scroll animations

---

## Admin Panel

- Dashboard with live stats
- Post / page editor with live Markdown preview
- Media library — upload, browse, delete
- User management — five roles: admin, editor, author, contributor, subscriber
- Comment moderation queue
- Category management
- Site settings

---

## User Roles

| Role | Permissions |
|---|---|
| Admin | Full access — all content, all users, all settings, themes, plugins, Distribution Manager |
| Editor | Publish/edit all posts and pages; manage categories, tags, comments; media library |
| Author | Create, edit, and publish own posts; upload media; manage profile |
| Contributor | Write posts, submit for review; cannot publish — requires admin/editor approval |
| Subscriber | Read, comment, manage own profile and avatar |

---

## Theme System

Themes are self-contained directories. The active theme's `theme.py` is exec'd by the router with all page variables pre-populated. Bundled themes: `firstTheme`, `secondTheme`, `americanTheme`, `USAtheme`, `NewsTheme`. Additional themes available via the marketplace (e.g. `ModernTheme` — bold magazine layout with carousel, ticker, 8 color palettes).

---

## Version History (overview)

| Version | Title |
|---|---|
| v1.0 | Foundation Release |
| v1.01 | Theme Expansion |
| v1.02 | Syntax Highlighting Engine |
| v1.03 | Markdown Parser Overhaul |
| v1.04 | SQL Language Support |
| v1.05 | Per-Block Theme Scoping |
| v1.06 | Reader Theme Persistence |
| v1.07 | Frontend Reader Experience |
| v1.08 | Streaming CGI Parser & Security (`cgi_improved2.py`) |
| v1.09 | Project Documentation & Archive Policy |
| v1.10 | Markdown + HTML Language & SQL Detection Fix |
| v1.11 | Markdown Auto-Detection Fix — fenced block stripping |
| v1.12 | Markdown Detection Hardened — ATX heading rule, tilde fence signal |
| v1.13 | highlight.js Markdown Grammar Fix — underscore in identifiers (`highlight_custom_improved.js`) |
| v1.14 | Markdown Highlighting — server-side Python tokenizer in `syntax_highlight.py`; JS grammar `h.regex.concat()` fixed |
| v1.15 | Markdown Highlighting — JS tokenizer in `highlight_custom_improved.js` replaces Python; patches `hljs.highlightElement()` for consistent single code path; all themes now load custom script |
| v1.16 | USAtheme + "Register" → "Create Account" |
| v1.17 | Code Block Word Wrap Toggle |
| v1.18 | Admin Password Change + Theme Preview |
| v1.19 | Firefox Android Word Wrap Fix |
| v1.20 | Custom Arbitrary Slug Mode |
| v1.21 | Dynamic sys.path in AJAX Scripts |
| v1.22 | Database Migration System |
| v1.23 | Image Alignment CSS Fix |
| v1.24 | Post Delete Count Correction |
| v1.25 | Editable Display Name + Profile Author Fix |
| v1.26 | Profile Page Featured Image Fix |
| v1.27 | Light/Dark Mode Toggle + Full Dark Theme |
| v1.28 | Dark Mode Post Title + Category Count Accuracy |
| v1.29 | Profile Page Post Count Accuracy |
| v1.30 | Admin Categories Post Count Accuracy |
| v1.31 | Admin Users Post Count + Posts/Pages/Frontend Comment Count Accuracy |
| v1.32 | Sidebar Tags Cloud Count Accuracy |
| v1.33 | Dashboard Drafts Panel + Configurable Auto-save |
| v1.34 | Syntax Highlighter — Markdown Detection Fix + Inline Language Hint |
| v1.35 | Emoji Picker |
| v1.36 | Emoji Picker Expansion — Skin Tones, Sports, Education & Tech |
| v1.37 | Markdown Italic/Bold Underscore Fix |
| v1.38 | Apostrophe Fix in Code Block Highlighting |
| v1.39 | Emoji Expansion + Markdown Help + Smart Auto-save + Light Mode Default + User Deletion |
| v1.40 | Code Block Markdown Rendering + Theme Fixes |
| v1.41 | NewsTheme + secondTheme LIVE Removal |
| v1.42 | NewsTheme URL Fix + Slug-Type Support |
| v1.43 | NewsTheme Home Page "No Posts" Fix |
| v1.44 | Category Delete + NewsTheme Toggle Icon + Ticker Empty State |
| v1.45 | Auto-Update System — one-click updates, version API, SQL migration runner |
| v1.46 | Update Check Force-Refresh + Comment Newline Preservation |
| v1.47 | Auto-Update: Permissions Fix + VERSION Bump |
| v1.48 | Update Failure Hint Line |
| v1.49 | Auto-Update: Preserve Distribution Zip |
| v1.50 | Media Library Modal: Immediate Upload Refresh |
| v1.51 | Polling Plugin: Map Totals Toggle, Copy Block Button, Delete Question, Download Counter, ep_counters table |
| v1.52 | Plugin & Theme Marketplace: repository system, one-click install, API endpoints, star ratings, likes, comments |
| v1.53 | ModernTheme: bold magazine/news theme with full-width carousel, 2×2 sidebar grid, trending ticker, dark mode, 8 color palettes |
| v1.54 | Fix one-click update migrations: run_migrations splits multi-statement SQL files |
| v1.55 | Fix login failure on older installs: 1.41.sql migration adds missing ep_users columns |
| v1.56 | Browse Repository stability: Polling_Voting_States to repository-only; star_avg Decimal→float fix |
| v1.57 | Version bump / archive rebuild for server sync |
| v1.58 | Marketplace UI: installed tab count increments on install; interactive star ratings; download count in footer |
| v1.59 | Plugin install migration: 1.53.sql creates ep_plugins table on existing installs |
| v1.60 | Plugin install dynamic card: no page refresh |
| v1.61 | Plugin delete: Installed tab count decrements after card fade-out |
| v1.62 | Plugin delete: restores Browse Repository Install button |
| v1.63 | Theme Browse Repository tab fix; ModernTheme preview.svg added |
| v1.64 | Theme repo cards: interactive star ratings; download count in footer |
| v1.65 | (skipped) |
| v1.66 | Auto-sync repository on Browse tab open: sync_themes_repo + sync_plugins_repo walk repo dirs, upsert DB |
| v1.67 | Consolidated marketplace release: dark mode emoji fix; migration runner PL/pgSQL fix |
| v1.68 | Theme uninstall: ep_theme_uninstall.py; Uninstall button; dynamic install card |
| v1.69 | Theme card has_manifest flag; bundled themes show info icon; apiV1 _api_not_found() helper |
| v1.70 | Fix missing timezone import; ModernTheme login fix |
| v1.71 | Bundled theme cards show author/created info rows; custom CSS tooltip system |
| v1.72 | Theme card tooltip z-index, box-shadow, CSS arrow polish |
| v1.73 | Theme install card preview: correct /themes/1_ModernTheme/preview.svg path |
| v1.74 | Installed marketplace theme cards show download count badge |
| v1.75 | Archive top-level fixed to www/ — one-click updater correctly deploys files |
| v1.76 | Version bump to trigger one-click update on eaglepress.org |
| v1.77 | Download count extended to non-prefixed manifest themes |
| v1.78 | Download count badge uses ep-repo-dl class |
| v1.79 | Remove bundled ModernTheme from CMS archive |
| v1.80 | Fix hardcoded themes/ModernTheme paths — theme works under any installed folder name |
| v1.81 | Theme-Independent Content Rendering — `.ep-prose` universal stylesheet; output buffering injects styles into every theme |
| v1.82 | Distribution Manager Overhaul + One-Click Updater Label |
| v1.83 | Distribution Manager Access Control — `DISTRIBUTION_SERVER` config variable |
| v1.84 | SyntaxWarning Fix — JavaScript regex escape sequences corrected in Python f-strings |
| v1.85 | Graceful DISTRIBUTION_SERVER import — `try/except ImportError` fallback; existing installs no longer crash on update |
| v1.86 | Theme preview images in Browse Repository — `sync_themes_repo` extracts `preview.svg` beside each theme zip; new `themes_repository` fastcgi route serves SVGs via symlink; Browse Repository cards show theme previews |
| v1.87 | Plugin Active folder on fresh installs — `ep_plugin_install.py` creates `plugins/Active/` alongside `plugin_list/` on first plugin install |
| v1.88 | Poll plugin slug detection fix — poll-ID injection now matches numeric-prefixed slugs (e.g. `1_Polling_Voting_States`) |
| v1.89 | Poll editor preview — styled visual mock for unsaved polls in admin Preview tab |
| v1.90 | Bare-name plugin symlink — legacy plugin builds resolve assets without reinstall |
| v1.91 | Plugin URL path patching — bare-name asset URLs auto-rewritten to numbered-slug path |
| v1.92 | `_epPreviewTransforms` hook — plugins inject temporary data into Preview tab before AJAX render |
| v1.93 | Theme-independent plugin loading — plugin CSS/JS injected centrally by `index.py`; jQuery 4.0 auto-injected when absent; `pvs_widget.js` `.attr()` fix |
| v1.94 | Stale-tab auto-save guard — dirty flag + `visibilitychange` staleness check; yellow banner prompts "Fetch latest version" on outdated tabs; auto-save paused until reload |
| v1.95 | Fresh-install fix — `idx_plugins_active` and `idx_plugins_slug` moved in `setup.sql` to after the `ep_plugins` CREATE TABLE; previously caused `relation "ep_plugins" does not exist` on every clean install |
| v1.96 | Rust Syntax Highlighting — Rust language added to score-based auto-detection engine, editor language selector dropdown, and fence hint aliases (`rust`, `rs`); lifetime notation `'a` guarded via `_APOSTROPHE_LANGS` |
| v1.97 | Notepad++ Syntax Theme — custom light theme added to code block theme selector; 34 token rules; f-strings detected via `ep-fstring` JS class; CSS in `styles_content.css` (no CDN) |
| v1.98 | Kate Syntax Theme — Kate editor-inspired light colour theme; KDE KSyntaxHighlighting palette (keywords bold #1f1c1b, strings #bf0303 red, f-strings #ff5500 bold orange, numbers #b08000 ochre, built-ins/functions #644a9b purple, literals/types/variables #0057ae blue); CSS in `styles_content.css` (no CDN) |
| v2.00 | **Reader Defaults** (Dashboard settings for default page theme, code block theme & mode); anti-FOUC dynamic default in all 5 bundled themes; **EaglePressTheme** — deep navy + gold showcase theme with /themes gallery, /plugins directory, theme preview route; **Global Lists** system (ep_update_global_lists.py scans repos → global_theme_list.json + global_plugin_list.json); new /themes, /plugins, /theme-preview/<slug> core routes; _ep_is_distrib_server flag available to all themes |
| v1.99 | Per-Block Light/Dark Mode Toggle — 💡/🔅 emoji toggle (yellow/red border); 10 unified themes each with light+dark; dual CDN CSS scoping per mode; custom palettes for monokai-light, nord-light, agate-light, xcode-dark, classic-dark, notepadpp-dark, kate-dark; legacy keys auto-migrated; ModernTheme: "Register" → "Create Account", header hover glow effect |
| v2.00 | **Major release.** Reader Defaults settings card — three new site settings: Default Page Theme (light/dark), Default Code Block Theme (syntax theme key), Default Code Block Mode (light/dark); applied server-side so every new page/code block starts with the Dashboard-chosen defaults instead of always light/GitHub. **Anti-FOUC dynamic default** — all 5 bundled themes (firstTheme, secondTheme, americanTheme, USAtheme, NewsTheme) + admin panel now use `_settings.get('default_page_theme','light')` in their inline `<script>` anti-FOUC tag instead of hardcoded `'light'`. **New core routes** — `/themes` → theme showcase (distribution server) or redirect page to eaglepress.org/themes (other installs); `/plugins` → plugin directory (distribution server) or redirect to eaglepress.org/plugins; `/theme-preview/<slug>/post/<post-slug>` → execs any installed or repo theme with a live post as preview content. **EaglePressTheme** — new installable showcase theme with deep navy + gold colour scheme (Playfair Display + Inter fonts); home page with hero post + card grid + sidebar; `/themes` gallery with preview image, version badge, Download + Preview buttons; `/plugins` directory; Marketplace nav group (🛍️ Marketplace + 🎨 Themes + 🔌 Plugins) with gold border, before Home; notice banner on non-distribution installs; standard page types; dark mode; full syntax highlighting; responsive; published to `themes_repository/2026/05/27/2_EaglePressTheme.zip`. **Global Lists system** — `global_theme_list.json` and `global_plugin_list.json`; `ep_update_global_lists.py` AJAX endpoint; "Update Global Lists" button in Distribution Manager. **Distribution-server flag** — `_ep_is_distrib_server` boolean. |
| v2.01 | **Go language support** (14th canonical language, 16-signal auto-detect, `~~~go`/`~~~golang`). **EaglePressTheme mobile hamburger redesigned** (proper dropdown below header; 🎨 Themes + 🔌 Plugins as accessible links). **Code block toolbar mobile** (💻 emoji + tap tooltip replaces lang label; ↵ replaces Wrap). **Smart updater fingerprinting** (SHA-512 + zip_mtime detection; content_updated state; installed SHA shown on Dashboard). **RedWhiteBlueTheme** bundled (navy/crimson/gold, stars, dark mode, ☀/🌙 toggle). **EaglePressTheme v1.1** (preview.svg corrected — EaglePress.org inline logo, widened marketplace border). |

> **On every version update:** One-Click Update from the Dashboard handles everything — download, verify, deploy, and migrate automatically.



## Technical Stack

| Layer | Technology |
|---|---|
| Language | Python 3.8+ |
| Database | PostgreSQL 12+ — 10 normalized tables, FK constraints, indexed queries, parameterized throughout |
| Web server | Apache `mod_cgi` / Nginx `fcgiwrap` |
| Frontend JS | jQuery 4.0 (CDN) |
| Syntax highlighting | highlight.js (CDN) + custom JS tokenizer (`highlight_custom_improved.js`) |
| Dependencies | `psycopg2` only |

💡 Example of the Syntax Highlighting:

Python 3
import os

for root, dirs, files in os.walk("."):
    for name in files:
        print(os.path.join(root, name)) # Prints the full path of every file
    for name in dirs:
        print(os.path.join(root, name)) # Prints the full path of every folder
Bash
traverse() {
    for file in "$1"/*; do
        if [ -d "$file" ]; then
            echo "Directory: $file"
            traverse "$file"  # Recursive call
        elif [ -f "$file" ]; then
            echo "File: $file"
        fi
    done
}

# Usage
traverse "/your/start/path"
JavaScript
function listFiles($dir) {
    $files = scandir($dir);
    foreach ($files as $file) {
        if ($file === '.' || $file === '..') continue;

        $path = $dir . DIRECTORY_SEPARATOR . $file;
        if (is_dir($path)) {
            listFiles($path); // Recursive call
        } else {
            echo $path . PHP_EOL;
        }
    }
}
C
#include <stdio.h>
#include <dirent.h>

int main() {
    struct dirent *entry;
    DIR *dp = opendir("."); // Open current directory

    if (dp == NULL) {
        perror("opendir");
        return 1;
    }

    while ((entry = readdir(dp))) {
        printf("%s\n", entry->d_name);
    }

    closedir(dp);
    return 0;
}
C++
#include <iostream>
#include <filesystem>

namespace fs = std::filesystem;

int main() {
    std::string path = "./my_directory";

    for (const auto& entry : fs::recursive_directory_iterator(path)) {
        std::cout << entry.path() << std::endl;
    }
    return 0;
}
Lua
local lfs = require("lfs")
local path = "."

for file in lfs.dir(path) do
    if file ~= "." and file ~= ".." then
        local full_path = path .. "/" .. file
        print("Found: " .. full_path)

        -- Check if it's a directory to recurse
        local mode = lfs.attributes(full_path, "mode")
        if mode == "directory" then
            print(full_path .. " is a directory")
        end
    end
end
Perl
use strict;
use warnings;
use File::Find;

# Specify the directory you want to start from
my $dir = '.';

# find() takes a code reference and the starting directory
find(\&process_file, $dir);

sub process_file {
    # $_ contains the current filename
    # $File::Find::name contains the full path to the file
    print "Found file: $File::Find::name\n" if -f $_;
}
SQL
CREATE TABLE Inventory (
    ProductID INT PRIMARY KEY,           -- Unique identifier (Integer)
    ProductName VARCHAR(100) NOT NULL,   -- Variable-length text (Name)
    Quantity INT DEFAULT 0,              -- Whole number (Stock count)
    UnitPrice DECIMAL(10, 2),            -- Precise decimal for currency (Price)
    IsActive BIT DEFAULT 1,              -- Boolean flag (1 for true, 0 for false)
    LastUpdated DATETIME DEFAULT CURRENT_TIMESTAMP -- Date and time stamp
);
Rust
use std::fs;
use std::path::Path;

fn traverse(path: &Path) {
    if let Ok(entries) = fs::read_dir(path) {
        for entry in entries.flatten() {
            let entry_path = entry.path();
            println!("{}", entry_path.display());
            if entry_path.is_dir() {
                traverse(&entry_path);
            }
        }
    }
}

fn main() {
    traverse(Path::new("."));
}
Go
package main

import (
    "fmt"
    "os"
    "path/filepath"
)

// walkDir recursively prints every file and directory under root
func walkDir(root string) error {
    return filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.IsDir() {
            fmt.Printf("[dir]  %s\n", path)
        } else {
            fmt.Printf("[file] %s  (%d bytes)\n", path, info.Size())
        }
        return nil
    })
}

func main() {
    root := "."
    if len(os.Args) > 1 {
        root = os.Args[1]
    }
    if err := walkDir(root); err != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", err)
        os.Exit(1)
    }
}

🖼️ Image Tag Reference

EaglePress Markdown supports an extended image syntax that lets authors control dimensions and layout alignment directly in content — no raw HTML needed.

Syntax

Markdown + HTML
![alt text](url =WIDTHxHEIGHT ALIGN "title")

All parameters after the URL are optional and can be combined in any order (width/height must come before alignment if both are used).

Parameters

ParameterFormatDescription
alt text![alt text]Alt text for accessibility / broken-image fallback
url(urlAbsolute or relative URL to the image
width × height=800x600Sets width and height HTML attributes in pixels
alignmentleft / center / rightApplies CSS class for float or centering
title"tooltip text"Sets the title tooltip attribute

Alignment Classes

ValueCSS Class AppliedVisual Effect
leftep-img ep-img-leftFloat image left, text wraps right
centerep-img ep-img-centerCenter image (block, no float)
rightep-img ep-img-rightFloat image right, text wraps left
(none)ep-imgInline, no alignment override

Examples

MarkdownOutput
![logo](/uploads/logo.png)Basic inline image, no sizing
![chart](/uploads/chart.png =800x400)Image with explicit 800×400 px dimensions
![photo](/uploads/photo.jpg center)Centered image, natural size
![icon](/uploads/icon.png =64x64 left)64×64 floated left
![hero](/uploads/hero.jpg =1200x600 center "Homepage banner")Full-width centered image with tooltip
![report](/uploads/report.pdf)Non-image file → renders as a styled download button

🔦 Syntax Highlighting Language Reference

Usually the Syntax Highlighting Language is auto detected, however, it may be manually stated of which syntax language a code block is utilizing.

Identifier example

● In the EaglePress post/page editor, fenced code blocks work like standard
Markdown with an optional language identifier after the opening backticks:

Basic fenced code block:
```python
def greet(name):
print(f"Hello, {name}!")
```

will display as:

Python 3
  def greet(name):
      print(f"Hello, {name}!")

Supported language identifiers:

Identifier(s)Language
python, py, python3🐍 Python 3
javascript, js, jsx, ts, tsx🟨 JavaScript
css, scss, sass, less🎨 CSS
html, htm, xml, svg🌐 HTML
php🐘 PHP
bash, sh, shell, zsh🖥️ Bash
c, h⚙️ C
cpp, c++, cxx, cc, hpp⚙️ C++
go, golang🐹 Go
rust, rs🦀 Rust
lua🌙 Lua
perl, pl, pm🐪 Perl
sql, mysql, pgsql, postgresql, sqlite🗄️ SQL
markdown, md, mdown, mkd📝 Markdown
text, txt, plain, plaintext📄 Plain Text

Force language with inline hint (when the opening fence can't carry a label):
```
=python3
def hello():
pass
```

will display as:

Python 3
  def hello():
      pass

The first line =python3 is consumed as a language hint and not shown in the
output.

If you omit the identifier, the engine auto-detects the language from the
content using score-based heuristics. For short or ambiguous code areas you can
always force it explicitly with the language selector dropdown that appears in
the code block toolbar after the page renders.

• • •

Post-Release Updates (2026-05-27)

v2.01 — ModernTheme Dark Mode Fix + Theme Preview Cache Priority

  • ModernTheme dark mode button emoji corrected — on first visit the button was hardcoded as 🌙 regardless of mode; JS init now always calls _applyDark() using the server-side default when localStorage is absent; button correctly shows ☀️ in light mode and 🌙 in dark mode
  • ModernTheme bundled into themes/ModernTheme/ in the main distribution zip so the Distribution Manager deploys it directly to eaglepress.org
  • Theme-preview search order fixed — installed themes (themes/<name>/) are now checked before the _preview_* extracted cache, preventing a stale cache from overriding an updated installed theme

v2.02 — EaglePressTheme Inline Code Color Fix

  • Inline code text inside post content was appearing too light because the github-dark highlight.js CDN theme was applying light-on-dark token colors to a white background
  • Added .ept-post-content .ep-inline-code-wrap code { color: #000 } and .ept-post-content .ep-inline-code-wrap code * { color: #000 } to EaglePressTheme CSS — forces all inline code and hljs token spans to black, overriding the CDN theme without touching fenced code blocks

v2.03 — Theme Preview Sidebar Data

  • get_sidebar_data(db) was never called inside the /theme-preview/ route handler, leaving _sidebar_data as an empty dict; theme previews showed no search widget, no recent posts, and no categories
  • One-line fix — sidebar data now populated identically to every other frontend route

v2.04 — EaglePressTheme Marketplace Navigation Group

  • Nav reordered: 🛍️ Marketplace label + 🎨 Themes + 🔌 Plugins links moved before the Home link on the distrib server
  • Three items wrapped in ept-nav-market-group — a flex inline container with a subtle gold border (rgba(200,151,46,.28)) and rounded corners to visually distinguish the Marketplace section from the main navigation
  • Vertical hairline separator (ept-nav-sep) between the Marketplace group and the rest of the nav links

• • •

Latest Archive

File: eaglepress_v2.00.zip — 371 KB

SHA-512:

Plain Text
d19523ae38d5c4e058c6f364e76f7d352eff00720a2f826d7413f901c2fc9469
4bd3e1a61cd13b8a8f4ccf13cbbd4a32cdc56c03213a7d587921c8c6a4ecded4

0 Comments

No comments yet. Be the first to share your thoughts!

Leave a Comment