PressGrid v2.5.0  ·  Documentation

WordPress Theme Documentation

WordPress Theme · v2.5.0

PressGrid

A production-ready, security-hardened WordPress theme engineered for high-traffic news and magazine websites. Classic editorial newspaper design, modular layout system, OpenWeatherMap weather integration, Frankfurter ECB forex ticker, and enterprise-grade security — zero JS dependencies beyond WordPress core.

WordPress 6.3+ PHP 8.0+ Lighthouse 95+ GPL-2.0+ Vanilla JS WCAG 2.1 AA v2.5.0
95+
Lighthouse
9
Layout Sections
6
Ad Zones
3
API Integrations

Core Features

What's Included

PressGrid v2.5.0 combines classic editorial newspaper design with engineering discipline. Every feature is purposefully built for modern news operations.

📰
Newspaper Design
Classic black/white/red palette. Playfair Display headings, Barlow Condensed navigation, hero grid with sidebar stack.
Performance First
Transient caching, deferred JS, lazy images, preconnect hints, zero render-blocking resources.
🔒
Security Hardened
Nonces, capability checks, WOFF2 MIME validation, security headers, full output escaping throughout.
🏗️
Layout Builder
9 configurable homepage sections. Enable/disable, set layout, category, and post count per section.
🌤️
Weather Widget
OpenWeatherMap integration — sidebar widget + top bar mini widget, 5-day forecast, geolocation. v2.5
💱
Forex Ticker
ECB rates via Frankfurter. Auto-activates on Business/Finance sections. No API key needed. v2.5
📖
Reading UX
Progress bar, read time, native share buttons, related posts, back-to-top. Zero external JS. v2.5
📊
SEO & Schema
NewsArticle JSON-LD, Open Graph, Twitter Cards, breadcrumbs, canonical tags on every page type.
WCAG 2.1 AA
Skip links, ARIA labels, keyboard navigation, focus-visible, semantic HTML5 throughout.

Prerequisites

Requirements

RequirementMinimumRecommended
WordPress6.36.7+
PHP8.08.2+
MySQL / MariaDB5.7 / 10.38.0 / 10.6+
BrowserAll modern browsers (ES2017+, CSS Grid)
ℹ️
Cache CompatibilityWP Super Cache, W3 Total Cache, LiteSpeed Cache, WP Rocket, and Redis Object Cache are all fully supported.

Setup

Installation

Method 1 — WordPress Admin Upload

  1. 1
    UploadGo to Appearance → Themes → Add New → Upload Theme. Select pressgrid-v2.5.0.zip and click Install Now.
  2. 2
    ActivateClick Activate on the theme page, or go to Appearance → Themes.
  3. 3
    Configure ColorsGo to Appearance → Customize → PressGrid: Colors to adjust the default red/black palette.
  4. 4
    Add Weather (optional)Go to Appearance → Customize → PressGrid: Weather. Add your free OpenWeatherMap API key and set your city.
  5. 5
    Build LayoutGo to Appearance → Layout Builder. If you assign a Business/Finance category to any section, the forex ticker activates automatically.
  6. 6
    Set Up MenusGo to Appearance → Menus. Assign menus to Primary, Footer, and Secondary locations.

Method 2 — WP-CLI

wp theme install pressgrid-v2.5.0.zip --activate

Method 3 — FTP

# Unzip and upload to:
/wp-content/themes/pressgrid/

Architecture

File Structure

pressgrid/ ├── style.css # Theme header + complete CSS (~22KB) ├── functions.php # Setup, enqueue, transients, SEO, preconnect ├── header.php # Top bar, masthead, sticky nav, breaking/forex bar ├── footer.php # Widgets, nav, developer credit ├── index.php # Fallback archive template ├── front-page.php # Layout Builder homepage ├── single.php # Single post — progress bar, share, related posts ├── archive.php # Category / tag / author archives ├── page.php # Static pages ├── search.php # Search results ├── comments.php # Threaded comments + form ├── sidebar.php # Sticky sidebar widget area ├── 404.php # Custom 404 page ├── API-GUIDE.md # Step-by-step API setup documentation │ ├── inc/ │ ├── security.php # Headers, XMLRPC toggle, font upload security │ ├── customizer.php # Customizer controls + CSS variable output │ ├── typography.php # Secure .woff2 upload admin page │ ├── ads.php # 6 ad zones, wp_kses sanitization, rendering │ ├── layout-builder.php # Layout Builder + Security settings │ ├── weather.php # OpenWeatherMap integration + Customizer │ └── forex.php # Frankfurter ECB ticker + business detection │ ├── template-parts/ │ ├── content/ │ │ ├── post-card.php # Post card component (hover animation) │ │ └── none.php # No results state │ └── layout/ │ ├── hero.php # Hero grid: 1 large left + 3 sidebar stack │ ├── latest-posts.php # Latest posts — grid-2/3/4 or list │ ├── category-grid.php # Category grid (transient cached) │ ├── trending.php # 3-col tab block: Trending + Editor's Picks + Video │ ├── editor-picks.php # Editor picks standalone (cached 30min) │ ├── opinion.php # Opinion section with author avatar │ └── newsletter.php # Newsletter CTA section │ ├── assets/js/ │ ├── main.js # Nav, progress bar, share, back-to-top (deferred) │ └── customizer-preview.js # Live CSS variable Customizer preview │ ├── languages/ │ ├── pressgrid.pot # Translation template (182 strings) │ ├── pressgrid-bg_BG.po/mo # Bulgarian (complete) │ └── pressgrid-en_GB.po/mo # English UK (complete) │ ├── screenshot.png # 880×660 theme screenshot └── readme.txt # WordPress.org compliant readme

Red = new or changed in v2.5.0


Appearance → Customize

Customizer

All visual settings are managed through the WordPress Customizer with live preview via postMessage CSS variable transport.

Color Panel

SettingCSS VariableDefault
Primary Color--pg-primary#cc0000
Secondary Color--pg-secondary#990000
Accent Color--pg-accent#cc0000
Background Color--pg-bg#ffffff
Text Color--pg-text#1a1a1a
Link Hover Color--pg-link-hover#cc0000

Social Media Panel New in v2

Set social profile URLs at Appearance → Customize → PressGrid: Social Media. Configured URLs render as icon links in the black top bar.

SettingMod KeyIcon
Facebook URLpressgrid_social_facebookf
X / Twitter URLpressgrid_social_twitter𝕏
YouTube URLpressgrid_social_youtube
Instagram URLpressgrid_social_instagram

Layout Options

SettingOptions
Sidebar PositionRight / Left / None (Full Width)
Breaking News BarEnable / Disable
Breaking News CategoryCategory ID — 0 = all posts
Developer CreditShow / Hide in footer

Typography

PressGrid ships with a full editorial font stack loaded from Google Fonts. Three font roles are defined as CSS custom properties:

VariableFontUsed For
--font-displayPlayfair Display (700/800/900)Post titles, section headers, masthead
--font-uiBarlow Condensed (400–800)Navigation, tabs, buttons, labels
--font-bodyBarlow (300–600)Body copy, meta, excerpts, top bar

Appearance → Layout Builder

Layout Builder

Configure the homepage at Appearance → Layout Builder. Each section can be independently enabled, assigned a layout type, source category, and post count.

💡
Forex TipAssign a Business or Finance category to any section — the Breaking News ticker in the top bar will automatically switch to the Frankfurter ECB forex ticker. No other configuration needed.

Available Sections

SectionDefault LayoutStateDescription
herohero-gridOn1 large article left + 3 thumbnail sidebar stack right
latest_postsgrid-3OnMost recent posts in configurable grid with sidebar
category_gridgrid-4OnPosts from a specific category (transient cached)
trendinglistOn3-column tab block: Trending Now + Editor's Picks + Video
editor_picksgrid-4OffStandalone editor picks grid, random, 30-min cache
opiniongrid-2On2-column opinion items with author avatar
newsletternewsletterOnFull-width newsletter CTA section
custom_htmlcustom_htmlOffFree-form HTML (wp_kses_post sanitized)
ad_blockad_blockOffRenders the between-posts ad zone inline

Appearance → Theme Ads

Advertisement System

Manage all ad placements at Appearance → Theme Ads. Each zone is independently configurable with HTML or ad network tags.

Zone IDLocationTypical Size
headerBelow sticky navigation728×90
sidebar_topTop of sidebar300×250
sidebar_middleBetween sidebar widget areas300×250 or 300×600
in_articleAbove article content on single postsResponsive
between_postsHomepage Ad Block sectionResponsive
footerAbove site footer728×90

Rendering in Templates

pressgrid_render_ad( 'sidebar_top' );
pressgrid_render_ad( 'in_article' );
pressgrid_render_ad( 'footer' );
🔒
SecurityAll ad HTML runs through wp_kses() with a strict allowed-tags whitelist. Desktop/mobile visibility is handled with .pg-ad-desktop-only / .pg-ad-mobile-only CSS classes.

New in v2.5 · Appearance → Customize → PressGrid: Weather

Weather Widget v2.5

Powered by OpenWeatherMap. Displays current conditions and a 5-day forecast in the sidebar, plus a compact mini widget in the top bar. Visitors can tap the geolocation button to see their local weather. All data is fetched server-side and cached — the visitor's browser never contacts OpenWeatherMap directly.

⚠️
Free API Key RequiredRegister at openweathermap.org — the free tier (1,000 req/day) is more than sufficient. New keys activate after 10–15 minutes.

Configuration

SettingWhereExample
API KeyCustomize → Weathera1b2c3d4e5f6...
CityCustomize → WeatherSofia,BG or London,GB
UnitsCustomize → Weathermetric (°C) or imperial (°F)
Sidebar widgetCustomize → WeatherEnable / Disable
Top bar mini widgetCustomize → WeatherEnable / Disable

What the Sidebar Widget Shows

  • Current: City name, description, icon, temperature, feels like, hi/lo
  • Details: Humidity, wind speed, cloud cover
  • Forecast: 5 days with daily icon and temperature
  • Geolocation: ⊕ button — asks browser permission, updates widget live, no data stored

Cache & API Usage

DataCache TTLRequests/day
Current conditions30 minutes~48
5-day forecast1 hour~24
Free tier limit1,000

Endpoints Used

# Current weather
GET https://api.openweathermap.org/data/2.5/weather
    ?q=Sofia,BG&appid=YOUR_KEY&units=metric

# 5-day forecast
GET https://api.openweathermap.org/data/2.5/forecast
    ?q=Sofia,BG&appid=YOUR_KEY&units=metric&cnt=40

New in v2.5 · Appearance → Customize → PressGrid: Currencies

Forex Ticker v2.5

Powered by Frankfurter — free, open-source, European Central Bank data. No API key required. The ticker automatically replaces the Breaking News bar when the Layout Builder has an active section targeting a Business or Finance category.

Zero ConfigurationCreate a category with slug business, finance, economy, or similar. Assign it to a Layout Builder section. The ticker activates automatically — no API key, no further settings required.

How the Auto-Detection Works

On every page load, pressgrid_has_business_section() checks all active Layout Builder sections for a category slug matching the built-in list. If found, the forex ticker is rendered in place of Breaking News. The result is cached for 5 minutes.

Auto-Detected Category Slugs

business, biznes, бизнес,
finance, finances, finansi, финанси,
economy, ikonomika, икономика,
markets, pazari, пазари,
money, pari, пари

Customizer Settings

SettingDefaultDescription
Base currencyEURRates are calculated from this currency
Target currenciesUSD,GBP,BGN,CHF,JPYComma-separated ISO 4217 codes
Business category slugauto-detectOverride only if your slug is non-standard
Always showfalseForce ticker on regardless of Layout Builder

API Details

Data sourceEuropean Central Bank via frankfurter.app
API key requiredNo
Update frequencyOnce per day (weekdays ~16:00 CET)
Cache TTL6 hours (~4 requests/day)
Rate limitNone for normal usage

Endpoint & Response

GET https://api.frankfurter.app/latest?from=EUR&to=USD,GBP,BGN,CHF,JPY

{
  "base": "EUR",
  "date": "2025-03-07",
  "rates": {
    "BGN": 1.9558, "CHF": 0.9305,
    "GBP": 0.8351, "USD": 1.0823
  }
}

New in v2.5 · single.php

Single Post UX v2.5

Five reader experience enhancements added to every single post. All implemented in vanilla JS — zero external scripts, zero SDKs, zero third-party requests from the browser.

Reading Progress Bar

A 3px red line at the top of the viewport tracks reading progress as the user scrolls. Only activates on single-post pages (detected via body class). Implemented in main.js and styled in style.css. Marked aria-hidden="true" as it is decorative.

Estimated Read Time

Displayed in post meta alongside author and date. Calculated server-side in functions.php:

str_word_count( wp_strip_all_tags( $content ) ) / 200
# Returns minimum 1 minute, rounded up

Native Share Buttons

ButtonMechanismFallback
Share ↗Web Share API (mobile/desktop)Hidden if not supported by browser
Copy link 🔗navigator.clipboarddocument.execCommand('copy')
LinkedInPlain <a href> linkAlways available, no JS needed

Related Posts

3 posts from the same category shown after the article content. Uses a standard WP_Query with orderby=rand and post__not_in to exclude the current post. No plugin required. Only rendered if the current post has at least one category with other matching posts.

Back-to-Top Button

A fixed button (bottom-right) that appears after 400px of scroll and smoothly scrolls to the top. ~10 lines of JS, pure CSS styling, injected before get_footer() in single.php.


New in v2.5 · External Services

API Reference v2.5

All external API calls are made server-side via PHP wp_remote_get(). The visitor's browser never contacts these services directly. Data is stored as WordPress transients.

Google Fonts
✓ No key required
Playfair Display, Barlow Condensed, Barlow via @import in CSS. For self-hosting, upload .woff2 files via Font Upload.
fonts.google.com ↗
OpenWeatherMap
⚿ Free key required
Weather widget. Free tier: 1,000 req/day. Cache: 30 min / 1 hr. Key ready in 15 minutes after registration.
openweathermap.org/api ↗
Frankfurter (ECB)
✓ No key required
ECB exchange rates. Completely free, open-source. Cache: 6 hours (~4 req/day). Updates daily on weekdays.
frankfurter.app/docs ↗
📘
Full Setup GuideSee API-GUIDE.md in the theme root for step-by-step registration instructions, endpoint documentation, and GDPR notes for each API.

Appearance → Font Upload

Typography

PressGrid ships with a complete editorial Google Fonts stack. For custom brand fonts, upload a .woff2 file via Appearance → Font Upload.

Secure Upload Process

  1. 1
    Upload fontSelect a .woff2 file (max 1MB). MIME type is validated against WOFF2 magic bytes before saving.
  2. 2
    Set family nameGo to Appearance → Customize → Typography and enter the font-family name (e.g. MyFont).
  3. 3
    Apply to elementsCheck: Body, Headings, Menu, or Buttons. The fallback stack (Georgia / Arial) is always preserved.
🔒
SecurityValidates WOFF2 magic bytes (0x774F4632), enforces 1MB cap, randomly renames files, stores in a protected directory with .htaccess restricting access to .woff2 only.


Engineering

Performance Architecture

95+
Lighthouse Score
Performance target
0
Render-Blocking JS
All scripts deferred
~22KB
CSS Size
No framework overhead
0
External JS
100% vanilla JS

v2.5 Performance Additions

  • Preconnect hints<link rel="preconnect"> for Google Fonts, OpenWeatherMap, and Frankfurter added conditionally only when those features are active. Saves 100–200ms on first external connection.
  • Sticky sidebarposition:sticky, no JS needed
  • Card hover animations — pure CSS translateY(-3px) + box-shadow, no JS
  • fetchpriority="high" on hero image for LCP optimization

Transient Cache Strategy

Transient KeyTTLCleared When
pressgrid_hero_posts5 minsave_post / delete_post
pressgrid_trending_posts10 minsave_post / delete_post
pressgrid_cat_grid_{id}5 minPer-category on post save
pressgrid_editor_picks30 minsave_post / delete_post
pressgrid_weather_*30 min / 1 hrcustomize_save_after
pressgrid_forex_*6 hourscustomize_save_after
pressgrid_has_biz_section5 minLayout sections option update

Query Optimization

  • No query_posts() — All queries use WP_Query directly
  • no_found_rows: true — Skips SQL_CALC_FOUND_ROWS on cached queries
  • Post ID caching — Only IDs stored in transients, query reconstructed from cache
  • Indexed columns only — No meta_query on unindexed keys

Hardening

Security

  • Every $_POST goes through wp_verify_nonce() + current_user_can()
  • All output escaped with esc_html(), esc_url(), esc_attr(), wp_kses_post()
  • Ad HTML filtered through wp_kses() with strict allowed-tags whitelist
  • Font upload: WOFF2 magic-byte validation, 1MB cap, random filename, protected dir
  • Security headers: X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy
  • WordPress version removed from head and all feeds
  • Author enumeration blocked via /?author=N redirect
  • Login error messages genericized to prevent username enumeration
  • No eval(), no direct DB queries, no obfuscated code
  • Direct file access blocked: if(!defined('ABSPATH')) exit; in every PHP file
  • Optional XML-RPC disable at Appearance → Theme Security
  • All functions prefixed pressgrid_ — no global namespace pollution
  • All external API calls server-side only (wp_remote_get) — browser never contacts APIs directly
  • Weather geolocation: browser Geolocation API, user consent required, no location data stored

Security Headers

X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()

Search & Discovery

SEO & Schema

Structured data and social metadata output automatically on every applicable page type.

NewsArticle JSON-LD

{
  "@context": "https://schema.org",
  "@type": "NewsArticle",
  "headline": "Article title",
  "datePublished": "2025-01-01T00:00:00+00:00",
  "dateModified": "2025-01-02T00:00:00+00:00",
  "author": { "@type": "Person" },
  "publisher": { "@type": "Organization" }
}

Other SEO Features

  • Open Graph: og:title, og:description, og:image, og:type, og:site_name
  • Twitter Cards: summary_large_image with auto-featured image
  • Canonical <link> tag on every page
  • Breadcrumb navigation with schema-ready markup
  • Semantic HTML5: header, main, article, nav, aside, footer
  • Reading time estimation shown in post meta

Developer API

Hooks & Public Functions

Key Public Functions

# Template functions
pressgrid_breadcrumbs();
pressgrid_post_meta( $post_id );       # author, date, read time
pressgrid_render_ad( 'sidebar_top' );
pressgrid_get_category_label( $post_id );

# Cached queries
$q = pressgrid_get_hero_posts( 4 );
$q = pressgrid_get_trending_posts( 6 );
$q = pressgrid_get_editor_picks( 4 );
$q = pressgrid_get_category_posts( $cat_id, 4 );

# v2.5 — Weather
$weather  = pressgrid_get_weather();
$forecast = pressgrid_get_forecast();

# v2.5 — Forex
$has_biz = pressgrid_has_business_section();
$rates   = pressgrid_get_forex_rates();

# v2.5 — Read time
$mins = pressgrid_reading_time( $post_id );

Filters

FilterDefaultDescription
pressgrid_content_width860Global $content_width in pixels
excerpt_length20Words in auto-excerpts
wp_headersSecurity headers added here

i18n / l10n

Translation

Text domain: pressgrid. The .pot template (182 strings) is in /languages/. Two translations ship with the theme:

LocaleFileStatus
bg_BGpressgrid-bg_BG.po/moComplete (182 strings)
en_GBpressgrid-en_GB.po/moComplete
# Generate fresh POT file
wp i18n make-pot . languages/pressgrid.pot --domain=pressgrid

# Compile PO to MO
msgfmt languages/pressgrid-bg_BG.po -o languages/pressgrid-bg_BG.mo

Modular Architecture

Template Parts

Calling with Args

# Category grid with custom args
get_template_part(
  'template-parts/layout/category-grid',
  null,
  array( 'layout' => 'grid-3', 'category' => 5, 'post_count' => 6 )
);

# Opinion section filtered to a specific category
get_template_part(
  'template-parts/layout/opinion',
  null,
  array( 'category' => 7, 'post_count' => 4 )
);

Child Theme Override

# Copy at same relative path inside child theme:
child-theme/template-parts/content/post-card.php
child-theme/template-parts/layout/opinion.php

Infrastructure

Caching

Full CompatibilityWorks with WP Super Cache, W3TC, LiteSpeed, WP Rocket, Redis, and Memcached. When a persistent object cache is active, set_transient() automatically uses it.

Manual Cache Clear

delete_transient( 'pressgrid_hero_posts' );
delete_transient( 'pressgrid_trending_posts' );
delete_transient( 'pressgrid_editor_picks' );
delete_transient( 'pressgrid_cat_grid_' . $cat_id );
delete_transient( 'pressgrid_has_biz_section' );
# Weather and forex transients cleared automatically via customize_save_after

History

Changelog

v2.5.0 Latest Reading UX · Weather · Forex · SEO
  • New — Frankfurter forex ticker Auto-activates when Layout Builder has a Business/Finance section. No API key required. ECB data, 6-hour cache.
  • New — OpenWeatherMap weather widget Sidebar widget + top bar mini widget, 5-day forecast, browser geolocation support.
  • New — Reading progress bar Thin red line at top of viewport on single posts only.
  • New — Estimated read time Calculated from word count, shown in post meta.
  • New — Native share buttons Web Share API + copy-to-clipboard + LinkedIn. Zero external JS or SDKs.
  • New — Related posts 3 posts from same category after article content. No plugin required.
  • New — Back-to-top button Appears at 400px scroll, smooth scroll.
  • New — Sticky sidebar position:sticky, no JS needed.
  • New — Card hover animations translateY(-3px) + box-shadow, pure CSS.
  • New — Open Graph + Twitter Card Full social meta tags on all page types.
  • New — NewsArticle JSON-LD Schema markup on all single posts.
  • New — Breadcrumb navigation Semantic, accessible, schema-ready.
  • New — Preconnect hints Google Fonts, OpenWeatherMap, Frankfurter (conditional).
  • New — API-GUIDE.md Step-by-step documentation for all three APIs.
  • New — bg_BG + en_GB translations 182 strings, compiled .mo files included.
  • Improved — pressgrid_post_meta() Now includes read time and modified date.
v2.0.0 Previous Newspaper Design Overhaul
  • New design system Classic newspaper aesthetic: black/white/red palette, replacing previous blue-accent palette
  • Font stack Playfair Display (headings) + Barlow Condensed (UI) + Barlow (body) via Google Fonts
  • Top bar Black strip with current date and social icon links; URLs configurable in Customizer
  • Masthead Centered newspaper-style logo with split-colour name and em-dash tagline
  • Hero section Rebuilt as 3:2 newspaper grid: full-bleed image left, three thumbnail sidebar items right
  • Trending section Rebuilt as 3-column tab block: Trending Now, Editor's Picks, and Video
  • Opinion section New Layout Builder section: 2-column grid with author byline
  • Social Media Customizer panel Facebook, X/Twitter, YouTube, Instagram URLs
  • Layout Builder expanded 8 → 9 sections with the addition of opinion
  • CSS overhaul Full rewrite using newspaper-appropriate typography scale and CSS custom properties
v1.0.0 Initial Release
  • Full theme architecture: Layout Builder, Ad Zones, Customizer
  • Security hardening: headers, MIME validation, nonces, escaping throughout
  • Transient caching for hero, trending, category, editor picks
  • Vanilla JS: nav, lazy load, dropdowns, smooth scroll
  • WCAG 2.1 AA accessibility compliance
  • WordPress.org Theme Review guidelines compliance
  • GPL-2.0-or-later license
🔗
Links GitHub Repository ↗  ·  Author Website ↗  ·  Theme by Milen Stanchev