A production-ready, security-hardened WordPress theme engineered for high-traffic news and magazine websites.
PressGrid is a fully open-source WordPress theme built for the demands of modern news operations. It ships with a visual Layout Builder, 6 advertisement zones, a secure font upload system, CSS variable theming, OpenWeatherMap weather integration, Frankfurter ECB forex ticker, and full WordPress.org Theme Review compliance β all with zero JavaScript dependencies beyond WordPress core.
π Full Documentation β π API Setup Guide β
| Category | Details |
|---|---|
| Performance | Lighthouse 95+, deferred JS, lazy images, no_found_rows, Redis-compatible transient cache, preconnect hints |
| Security | Nonces, capability checks, WOFF2 MIME validation, security headers, author enumeration block |
| Layout Builder | 8 configurable homepage sections with enable/disable, layout type, category, and post count |
| Ad System | 6 ad zones with mobile/desktop visibility, async load, and wp_kses() sanitization |
| Customizer | CSS custom property theming with live postMessage preview β 6 color controls |
| Typography | Secure .woff2 font upload (MIME-validated, 1MB cap, random rename, .htaccess protected) |
| Weather | OpenWeatherMap widget β sidebar + top bar mini widget, 5-day forecast, geolocation, Bulgarian UI |
| Forex Ticker | Frankfurter ECB rates β auto-activates when a Business/Finance section is present in Layout Builder |
| Reading UX | Progress bar, estimated read time, native share buttons, related posts, back-to-top button |
| SEO | NewsArticle schema, Open Graph, Twitter Cards, breadcrumbs, canonical tags |
| Accessibility | WCAG 2.1 AA β skip links, ARIA labels, focus-visible, semantic HTML5 |
| Compatibility | WP Super Cache, W3TC, LiteSpeed, WP Rocket, Redis, Memcached |
| Standards | GPL-2.0+, PHPCS WordPress Coding Standards, WP.org Theme Review compliant |
Repo Name:
pressgrid
Repo Description:
Production-ready WordPress theme for high-traffic news & magazine websites. Layout Builder, 6 Ad Zones, OpenWeatherMap, Frankfurter forex ticker, CSS variable Customizer, security-hardened, Lighthouse 95+, vanilla JS, GPL licensed.
Topics / Tags:
wordpress wordpress-theme news-theme magazine-theme layout-builder
customizer advertisement-zones performance security-hardened
vanilla-js gpl lighthouse accessibility wcag schema-org
openweathermap frankfurter forex weather
pressgrid/
βββ style.css # Theme header + complete CSS (~22KB)
βββ functions.php # Setup, enqueue, transients, SEO, schema, preconnect
βββ header.php # Sticky nav, breaking ticker / forex ticker, logo
βββ 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
βββ API-GUIDE.md # API setup guide (Google Fonts, OWM, Frankfurter)
β
βββ inc/
β βββ security.php # Headers, XMLRPC toggle, font upload security
β βββ customizer.php # All 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 admin pages
β βββ weather.php # OpenWeatherMap integration + Customizer settings
β βββ forex.php # Frankfurter ECB forex ticker + business section detection
β
βββ template-parts/
β βββ content/
β β βββ post-card.php # Reusable post card component (with hover animation)
β β βββ none.php # No results state
β βββ layout/
β βββ hero.php # Hero grid (1 large + sidebar cards)
β βββ latest-posts.php # Latest posts β grid-2/3/4 or list
β βββ category-grid.php # Category grid (transient cached)
β βββ trending.php # Trending by comment count (cached)
β βββ editor-picks.php # Editor picks random (cached 30min)
β βββ newsletter.php # Newsletter CTA section
β
βββ assets/js/
β βββ main.js # Nav, lazy-load, 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 translation
β βββ pressgrid-en_GB.po/mo # English (UK)
β
βββ screenshot.png # 880Γ660 theme screenshot
βββ readme.txt # WordPress.org compliant readme
- Go to Appearance β Themes β Add New β Upload Theme
- Select
pressgrid-v2.5.0.zipβ Install Now β Activate - Configure at
Appearance β Customize,Layout Builder,Theme Ads
wp theme install pressgrid-v2.5.0.zip --activate# Unzip and upload to your WordPress themes directory:
/wp-content/themes/pressgrid/| Requirement | Minimum | Recommended |
|---|---|---|
| WordPress | 6.3 | 6.7+ |
| PHP | 8.0 | 8.2+ |
| MySQL / MariaDB | 5.7 / 10.3 | 8.0 / 10.6+ |
| Browser | ES2017+, CSS Grid | β |
Navigate to Appearance β Customize β PressGrid: Colors to set your brand palette. All colors are output as CSS custom properties on :root with live postMessage preview.
| Setting | CSS Variable | Default |
|---|---|---|
| Primary Color | --pg-primary |
#1a73e8 |
| Secondary Color | --pg-secondary |
#0d47a1 |
| Accent Color | --pg-accent |
#e91e63 |
| Background Color | --pg-bg |
#ffffff |
| Text Color | --pg-text |
#212121 |
| Link Hover Color | --pg-link-hover |
#0d47a1 |
Appearance β Layout Builder β Configure 8 homepage sections:
| Section | Default Layout | Description |
|---|---|---|
hero |
hero-grid | 1 large featured + sidebar cards |
latest_posts |
grid-3 | Most recent posts |
category_grid |
grid-4 | Posts from a category (cached) |
trending |
list | By comment count, last 7 days |
editor_picks |
grid-4 | Random featured posts (30-min cache) |
newsletter |
newsletter | Newsletter CTA section |
custom_html |
custom_html | Free-form HTML (wp_kses_post) |
ad_block |
ad_block | Renders between-posts ad zone |
Tip: Assign a Business or Finance category to any section and the top bar Breaking News ticker will automatically switch to the Frankfurter forex ticker β no configuration needed.
Appearance β Theme Ads β Manage 6 zones:
| Zone | Location | Typical Size |
|---|---|---|
header |
Below sticky navigation | 728Γ90 |
sidebar_top |
Top of sidebar | 300Γ250 |
sidebar_middle |
Middle of sidebar | 300Γ600 |
in_article |
Above article content | Responsive |
between_posts |
Homepage ad block | Responsive |
footer |
Above site footer | 728Γ90 |
Each zone: enable/disable toggle, HTML/JS ad code input (sanitized with wp_kses()), desktop/mobile visibility, async load option.
Powered by OpenWeatherMap (free API key required).
Appearance β Customize β PressGrid: ΠΡΠ΅ΠΌΠ΅ΡΠΎ
| Feature | Details |
|---|---|
| Current conditions | Temperature, feels like, hi/lo, humidity, wind, clouds |
| 5-day forecast | Daily icons + temps in a compact row |
| Top bar mini widget | βοΈ 7Β°C Β· Sofia β hidden on small screens |
| Geolocation | β button β detects user location, no data stored |
| Cache | 30 min (current) Β· 1 hour (forecast) |
| Language | Bulgarian day names, translated UI |
π How to get a free OpenWeatherMap API key β
Powered by Frankfurter β free, no API key, ECB data.
The forex ticker automatically replaces the Breaking News bar when the Layout Builder has an active section targeting a Business or Finance category. No configuration required.
Appearance β Customize β PressGrid: ΠΠ°Π»ΡΡΠΈ (Forex)
| Setting | Default |
|---|---|
| Base currency | EUR |
| Target currencies | USD, GBP, BGN, CHF, JPY |
| Business category slug | Auto-detected (business, biznes, Π±ΠΈΠ·Π½Π΅Ρ, finance, ΡΠΈΠ½Π°Π½ΡΠΈβ¦) |
| Force always on | false |
| Feature | Details |
|---|---|
| Data source | European Central Bank via frankfurter.app |
| Update frequency | Once daily (weekdays ~16:00 CET) |
| Cache | 6 hours |
| API key required | No |
| Feature | How it works |
|---|---|
| Reading progress bar | Thin red line at top of viewport, JS-driven, single posts only |
| Estimated read time | str_word_count / 200 β shown in post meta |
| Share buttons | Web Share API (mobile) + copy-to-clipboard fallback + LinkedIn β zero external JS |
| Related posts | 3 posts from same category, random order, no plugin |
| Back-to-top button | Appears after 400px scroll, smooth scroll, pure CSS + ~8 lines JS |
- Transient caching β hero, trending, category grid, editor picks (5β30 min TTL, cleared on
save_post) no_found_rows: trueon cached queries β skipsSQL_CALC_FOUND_ROWS- Post ID caching β only IDs stored in transients; query reconstructed from cache
- Preconnect hints β
<link rel="preconnect">for Google Fonts, OpenWeatherMap, Frankfurter (conditional) - Deferred JS β
<script defer>strategy for all theme scripts - Native lazy loading β
loading="lazy"+decoding="async"on all non-LCP images - LCP optimization β
fetchpriority="high"on hero image - No render-blocking resources β all scripts in footer or deferred
- No jQuery, no Bootstrap β 100% vanilla JavaScript
- CSS Grid + Flexbox β no CSS framework overhead (~22KB unminified CSS)
- Redis/Memcached compatible β
set_transient()uses object cache backend when available
- β
Every
$_POST/$_GETβwp_verify_nonce()+current_user_can() - β
All output β
esc_html(),esc_url(),esc_attr(),wp_kses_post() - β
Ad HTML β
wp_kses()with strict allowed-tags whitelist - β
Font upload β WOFF2 magic-byte validation (
0x774F4632), 1MB cap, random rename,.htaccessprotected directory - β
Security headers via
wp_headersfilter βX-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy - β
WordPress version removed from
<head>and all feeds - β
Author enumeration blocked via
/?author=Nredirect - β Login errors genericized β no username enumeration
- β
No
eval(), no direct DB queries, no obfuscated code - β Direct file access blocked in every PHP file
- β
Optional XML-RPC disable β
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
- NewsArticle JSON-LD on all single posts (auto-generated)
- Open Graph β
og:title,og:description,og:image,og:type,og:site_name - Twitter Cards β
summary_large_imagewith featured image auto-population - Canonical
<link>on every page - Breadcrumb navigation β semantic, accessible
- Semantic HTML5 β
<header>,<main>,<article>,<nav>,<aside>,<footer> - Reading time estimation displayed in post meta
- Pagination
rel="prev"/rel="next"via WordPress core
Text domain: pressgrid β .pot file included in /languages/ (182 strings).
Bundled translations:
| Locale | File | Status |
|---|---|---|
bg_BG |
pressgrid-bg_BG.po/mo |
Complete |
en_GB |
pressgrid-en_GB.po/mo |
Complete |
# Generate 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.moCompatible with Loco Translate and WPML.
All external API calls are made server-side (PHP). The visitor's browser never contacts these services directly.
| API | Key required | Cost | Cache | Used for |
|---|---|---|---|---|
| Google Fonts | No | Free | Browser | Playfair Display, Barlow fonts |
| OpenWeatherMap | Yes (free tier) | $0 | 30 min / 1 hr | Weather widget |
| Frankfurter | No | Free | 6 hours | Forex ticker (ECB data) |
π Full API setup guide with step-by-step instructions β
// Output breadcrumbs
pressgrid_breadcrumbs();
// Output post meta (author, date, reading time)
pressgrid_post_meta( $post_id );
// Render an ad zone
pressgrid_render_ad( 'sidebar_top' );
// Get first category label HTML
pressgrid_get_category_label( $post_id );
// Get cached hero WP_Query
$query = pressgrid_get_hero_posts( 3 );
// Get cached trending WP_Query
$query = pressgrid_get_trending_posts( 6 );
// Get cached category WP_Query
$query = pressgrid_get_category_posts( $cat_id, 4 );
// Check if a Business/Finance section is active (for forex ticker logic)
$show_forex = pressgrid_has_business_section();
// Get exchange rates from Frankfurter ECB API
$rates = pressgrid_get_forex_rates(); // ['base' => 'EUR', 'rates' => [...], 'date' => '...']
// Get weather data from OpenWeatherMap
$weather = pressgrid_get_weather(); // current conditions array
$forecast = pressgrid_get_forecast(); // 5-day forecast array
// Get estimated reading time in minutes
$mins = pressgrid_reading_time( $post_id );- Skip-to-content link (
.skip-link) - All navigation has
aria-label - Mobile toggle with
aria-expandedstate management - Keyboard-accessible dropdown menus with
aria-haspopup focus-visibleoutline styles for keyboard users- Sufficient color contrast ratios (WCAG AA)
- Semantic heading hierarchy on all templates
- Images require
alttext β enforced via template functions - Progress bar marked
aria-hidden="true"(decorative) - Share buttons with descriptive
aria-labelattributes
- β GPL-2.0-or-later license
- β
Proper theme header in
style.css - β
Text domain:
pressgrid - β All strings translatable
- β No upsells, no tracking, no affiliate links
- β No obfuscated code
- β No required plugins
- β No admin nags
- β No hidden backlinks
- β Developer credit is removable
- β
readme.txtincluded - β
screenshot.pngincluded (880Γ660)
- New: Frankfurter ECB forex ticker β auto-activates when Layout Builder has a Business/Finance section
- New: OpenWeatherMap weather widget (sidebar + top bar mini widget, 5-day forecast, geolocation)
- New: Reading progress bar on single posts
- New: Estimated read time in post meta
- New: Native share buttons (Web Share API + copy-to-clipboard + LinkedIn, zero external JS)
- New: Related posts section after article content (same category, no plugin)
- New: Back-to-top button (appears at 400px scroll)
- New: Sticky sidebar
- New: Card hover animations (
translateY+ shadow) - New: Open Graph + Twitter Card meta tags
- New: NewsArticle JSON-LD schema
- New: Breadcrumb navigation
- New:
preconnecthints for Google Fonts, OpenWeatherMap, Frankfurter - New:
API-GUIDE.mdβ step-by-step API setup documentation - New:
bg_BGanden_GBtranslations (182 strings) - Improved: Hero grid layout rewrite (flex, 3-item limit, category labels, thumb hover)
- Improved:
pressgrid_post_meta()now includes read time and modified date
- Initial release
PressGrid WordPress Theme
Copyright (C) 2024 Milen Stanchev
Released under the GNU General Public License v2 or later.
Milen Stanchev
π https://stanchev.bg/
π github.com/stantchev
PressGrid is an independent open-source project. No affiliation with WordPress.org or Automattic.