PraisonPressGit - A powerful WordPress plugin that loads content from files (Markdown, JSON, YAML) without database writes, featuring Git-based version control and cloud-native deployment support.
- π€ Export to Markdown: Convert existing WordPress content to Markdown files
- Admin UI with progress tracking and background processing
- CLI support for automation and large exports
- Preserves all metadata, custom fields, taxonomies, categories, and tags
- Full ACF (Advanced Custom Fields) support
- Handles 50,000+ posts efficiently
- File-Based Content Management: Store posts, pages, and custom post types as Markdown files
- Version Control Ready: Designed to work with Git for tracking content changes
- No Database Writes: Read-only approach - content stays in files
- Dynamic Post Type Discovery: Automatically registers custom post types based on directory structure
- Custom URL Routing: Support for custom post type routing (e.g.,
/recipes/xxx,/posts/xxx) - Cache Management: Built-in caching system for optimal performance
- Front Matter Support: YAML front matter for comprehensive metadata
- Markdown Parsing: Full Markdown support with automatic HTML conversion
- π High Performance Index System: Handle 100,000+ files with build-time indexing
- βοΈ Cloud-Native Ready: Docker, Kubernetes, and multi-cloud deployment support
- π Separate Content Repos: Keep content in separate Git repositories
- π Security Hardened: All outputs escaped, nonce verification, timezone-safe
- π Admin Dashboard: Real-time statistics and content management
- π― Smart Caching: WordPress transients with automatic invalidation
- π Multi-Pod Support: Horizontal scaling with shared storage
- π§ WP-CLI Support: Command-line tools for automation
- βοΈ "Report Error" Button: Allow logged-in users to suggest edits on any post
- π Pull Request Workflow: Automatic PR creation for user-submitted edits
- π My Submissions Page: Users can view status of their submitted edits with pagination (5 per page)
- π¨ Custom Modals: Beautiful WordPress-style modals (no browser popups)
- π View Diff: Direct links to GitHub PR file changes
- π View Page: Links to actual WordPress page for each submission
- π₯ View All Submissions: Admins can view ALL users' pull requests, not just their own
- π Filter Views: Toggle between "My Submissions" and "All Users" with filter buttons
- β One-Click Approve: "Approve & Merge" button directly on submissions page
- π Auto-Sync After Merge: Content automatically syncs from GitHub when PRs are merged
- π¨βπΌ Admin PR Review: Full PR review interface in WordPress admin with diffs
- π Pagination: Efficient pagination for large numbers of submissions
- π·οΈ Status Badges: Color-coded badges (Open/Merged/Closed)
- π GitHub Integration: One-click OAuth connection to GitHub repositories
- π Secure & Private: User-specific PR tracking with no PII exposed on GitHub
- π Scalable Architecture: Optimized for 200K+ users with caching
- πΎ Database Tracking: Submissions table with post_type support for file-based posts
- π― Smart Post Detection: Finds posts by slug + post_type for file-based content
- Intelligent Caching: Transient-based caching with configurable TTL
- Index System: Optional indexing for 100K+ files (50-100x faster)
- Lazy Loading: Content loaded on-demand, not at boot
- Cache Invalidation: Automatic detection of file changes
- Memory Efficient: Only loads requested content
- PSR-4 Autoloading: Modern PHP namespace structure
- Filters & Actions: Extensive hook system for customization
- WP Coding Standards: Follows WordPress best practices
- Git Integration: Built for version control workflows
- API Ready: Programmatic access to all features
PraisonPressGit supports two flexible workflows to fit your team's needs:
1. Create posts in WordPress admin
2. Use Export feature to convert to .md files
3. Commit files to Git
4. Deploy to production
Best for:
- Teams familiar with WordPress
- Content editors who prefer GUI
- Gradual migration to file-based content
1. Create .md files directly in /content/
2. Files automatically appear on frontend
3. Commit to Git
4. Deploy
Best for:
- Developers and technical writers
- Git-first workflows
- JAMstack architectures
- CI/CD pipelines
You can mix and match both workflows:
- Use admin for quick edits and drafts
- Export to files for version control
- Create files directly for new content
- All content accessible on frontend
Key Benefits:
- π Flexibility: Choose the workflow that fits each task
- π Reversible: Export admin posts to files anytime
- π Scalable: File-based content performs better at scale
- π Trackable: Full Git history for all file-based content
- Go to Plugins > Add New in WordPress admin
- Search for "PraisonPressGit"
- Click Install Now and then Activate
- Content directory will be created at
/content/(root level, independent of WordPress)
- Download the plugin ZIP file
- Go to Plugins > Add New > Upload Plugin
- Upload the ZIP file and click Install Now
- Click Activate Plugin
# Clone to plugins directory
cd wp-content/plugins/
git clone https://github.com/your-repo/praisonpressgit.git
# Or via WP-CLI
wp plugin install praisonpressgit --activatePraisonPressGit works out-of-the-box with sensible defaults. Configuration files are optional and only needed for customization.
When you install the plugin, it automatically:
- Exports to
/content/{post_type}/directories - Uses flat structure (no subdirectories)
- Includes date prefix in filenames:
YYYY-MM-DD-slug.md - Preserves all metadata, categories, tags, and custom fields
Example: A post titled "My Article" published on 2025-11-01 exports to:
/content/post/2025-11-01-my-article.md
For advanced customization, you can create configuration files:
Location: /wp-content/plugins/praisonpressgit/site-config.ini
Example: /wp-content/plugins/praisonpressgit/site-config.ini.example
[site]
title = "My WordPress Site"
description = "A Git-powered WordPress site"
[content]
enabled = true
content_dir = "content"
post_types[] = "post"
post_types[] = "page"
post_types[] = "lyrics"
post_types[] = "bible"
[cache]
enabled = true
ttl = 3600
[performance]
use_build_index = true
build_index_threshold = 1000Location: /wp-content/plugins/praisonpressgit/export-config.ini
Example: /wp-content/plugins/praisonpressgit/export-config.ini.example
This file is optional. Only create it if you need custom export behavior.
Without a config file, all post types export with:
- Directory:
/content/{post_type}/ - Structure: Flat (no subdirectories)
- Filename:
{date}-{slug}.md(with date prefix) - All metadata preserved
To customize export behavior:
- Copy
export-config.ini.exampletoexport-config.ini - Uncomment and modify the post types you want to customize
- Leave other post types commented to use defaults
Lyrics (Alphabetical):
[lyrics]
directory = "lyrics"
structure = "alphabetical"
alphabetical_field = "title"
filename_pattern = "{slug}.md"
custom_fields[] = "artist"Result: /content/lyrics/a/amazing-grace.md
Bible (Hierarchical):
[bible]
directory = "bible"
structure = "hierarchical"
hierarchy_levels[] = "book"
hierarchy_levels[] = "chapter"
hierarchy_levels[] = "verse"
filename_pattern = "{verse}.md"Result: /content/bible/genesis/1/1.md
Articles (Date-Based):
[articles]
directory = "articles"
structure = "date"
date_depth = 2
filename_pattern = "{date}-{slug}.md"Result: /content/articles/2025/11/2025-11-01-article.md
| Structure | Description |
|---|---|
flat |
No subdirectories |
alphabetical |
By first letter (a/, b/, c/) |
hierarchical |
Custom field-based (e.g., /genesis/1/1.md) |
category |
By post category |
date |
By year/month/day |
| Variable | Example |
|---|---|
{slug} |
my-post |
{title} |
my-post-title |
{date} |
2025-11-01 |
{id} |
123 |
/content/
βββ posts/ # Blog posts
βββ pages/ # Static pages
βββ recipes/ # Custom post type: Recipes
βββ config/ # Configuration files
Create .md files with YAML front matter:
---
title: "My Post Title"
slug: "my-post-slug"
author: "admin"
date: "2024-10-31 12:00:00"
status: "publish"
categories:
- "General"
tags:
- "example"
---
# Your content here
Write your content in Markdown format.Simply create a new directory in /content/ to add a custom post type:
mkdir /content/recipesThe plugin will automatically:
- Register the
recipespost type - Create the URL route
/recipes/{slug} - Load content from the directory
- WordPress 5.0 or higher
- PHP 7.4 or higher
- Git (for version control)
PraisonPressGit is designed for cloud-native deployments and works seamlessly in:
- Docker containers
- Kubernetes pods
- Cloud platforms (AWS, Azure, GCP)
- Roots/Bedrock WordPress structure
Perfect for: Static content, rarely updated sites, immutable infrastructure
β Pros:
- Fast pod startup (no volume mounts needed)
- Simple deployment
- Content versioned with image tags
- Works great with
kubectl rollout restart deployment/wordpress
FROM wordpress:latest
COPY ./praisonpressgit /var/www/html/wp-content/plugins/praisonpressgit
COPY ./content /var/www/html/content
RUN chown -R www-data:www-data /var/www/html/contentUpdate workflow: Build new image β Push to registry β kubectl rollout restart deployment/wordpress
Separate Content Repository Pattern:
Keep content in a separate Git repo for better organization:
# Multi-stage build - fetch content from separate repo
FROM alpine/git AS content
ARG CONTENT_REPO_URL=https://github.com/your-org/content-repo.git
RUN git clone --depth 1 ${CONTENT_REPO_URL} /content
FROM wordpress:latest
COPY ./praisonpressgit /var/www/html/wp-content/plugins/praisonpressgit
COPY --from=content /content /var/www/html/contentCI/CD: Push to content repo β Trigger WordPress image rebuild β Auto-deploy
Perfect for: Frequently updated content, multi-author sites
β Pros:
- Content updates without rebuilding images
- Multi-pod deployments with ReadWriteMany (RWX) volumes
- Git sidecar container support
- Redis/Memcached integration for shared caching
- Health checks and autoscaling ready
# Using Docker Compose
docker-compose up -d
# Content persists in named volume: praison-content# Deploy with persistent volumes
kubectl apply -f k8s/praison-pvc.yaml
kubectl apply -f k8s/wordpress-deployment.yaml
# Scale horizontally
kubectl scale deployment wordpress --replicas=3π Full Documentation: See PRAISONPRESS-README.md for complete Docker/Kubernetes configurations, storage options, and production best practices.
PraisonPressGit uses a virtual post injection system:
βββββββββββββββββββββββββββββββββββββββββββ
β WordPress Request β
ββββββββββββββββ¬βββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β PraisonPress Bootstrap β
β β’ Discovers post types dynamically β
β β’ Registers custom post types β
β β’ Hooks into posts_pre_query β
ββββββββββββββββ¬βββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β PostLoader β
β β’ Checks for _index.json (fast) β
β β’ Falls back to directory scan β
β β’ Parses Markdown + YAML β
β β’ Creates WP_Post objects β
ββββββββββββββββ¬βββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββ
β WordPress Display β
β β’ Theme renders posts normally β
β β’ No database queries for content β
β β’ Caching for performance β
βββββββββββββββββββββββββββββββββββββββββββ
- Bootstrap.php: Main entry point, discovers post types
- PostLoader.php: Loads and parses Markdown files (with index support)
- CacheManager.php: Transient-based caching
- MarkdownParser.php: Converts Markdown to HTML
- FrontMatterParser.php: Parses YAML metadata
- Admin Pages: Dashboard, history, and statistics
- Content Statistics: Total posts, pages, and custom post types
- Last Modified: Track recent content changes
- Cache Status: View and clear cache
- Quick Actions: Access management tools
- PraisonPress Dashboard: Overview and statistics
- Version History: Git-based content tracking (if available)
- Settings: Configure cache and content directories
- Clear Cache: Manual cache invalidation
- Quick access to PraisonPress features from admin bar
- Cache clear shortcut
- Content statistics at a glance
Standard Setup - No index needed
Performance: ~0.5s load time
Memory: ~50MB
Cache: WordPress transientsIndex Recommended
Performance: ~0.2s load time (5x faster)
Memory: ~80MB
Cache: Transients + Object cacheIndex Required
Performance: ~0.5-2s load time (50x faster)
Memory: ~150MB
Cache: Redis/Memcached recommended
Storage: RWX volumes for multi-pod# Kubernetes example - Scale to 10 pods
kubectl scale deployment/wordpress --replicas=10
# All pods share same content via RWX volume
# Or bake content into image for immutable infrastructure// Modify loaded posts
add_filter('praison_posts', function($posts) {
// Your modifications
return $posts;
});
// Customize cache duration
add_filter('praison_cache_ttl', function($ttl, $post_type) {
if ($post_type === 'lyrics') {
return 7200; // 2 hours for lyrics
}
return $ttl;
}, 10, 2);
// Modify content directory
add_filter('praison_content_dir', function($dir) {
return '/custom/content/path';
});// Before posts load
add_action('praison_before_load_posts', function() {
// Your code
});
// After posts load
add_action('praison_after_load_posts', function($posts) {
// Process posts
}, 10, 1);
// Cache cleared
add_action('praison_cache_cleared', function() {
// Additional cleanup
});// Get posts
$posts = praison_get_posts([
'posts_per_page' => 10,
'post_type' => 'lyrics'
]);
// Get stats
$stats = praison_get_stats();
// Clear cache
praison_clear_cache();# Check plugin status
wp plugin is-active praisonpressgit
# Clear cache
wp cache flush
# Get content statistics
wp eval "print_r(praison_get_stats());"
# Test content loading
wp eval "
\$posts = praison_get_posts();
echo 'Loaded ' . count(\$posts) . ' posts';
"// Install Redis Object Cache plugin
wp plugin install redis-cache --activate
// Configure in wp-config.php
define('WP_REDIS_HOST', 'redis-service');
define('WP_REDIS_PORT', 6379);See Containerized Deployment section above.
// In wp-config.php
define('PRAISON_CACHE_TTL', 7200); // 2 hours// Warm up cache on deployment
wp eval "praison_get_posts(['posts_per_page' => -1]);"Check:
- File has correct YAML front matter
- File is in correct directory:
/content/posts/ - Cache is cleared
- Post status is
publish
Debug:
// Enable debug mode in wp-config.php
define('PRAISON_DEBUG', true);
// Check what's loaded
wp eval "var_dump(praison_get_posts());"Solutions:
- Enable caching (Redis/Memcached)
- Use index system for 1K+ files
- Increase cache TTL
- Check file system performance
# Force clear all caches
wp cache flush
wp transient delete --all
# Check permissions
chmod -R 755 /content/# Clear cache after content changes
wp cache flush
# Or use admin dashboard "Clear Cache" buttonAll security best practices implemented:
- β
Output Escaping: All outputs use
esc_html(),esc_url(),esc_attr() - β Nonce Verification: Form submissions protected with nonces
- β
Capability Checks: Admin features require
manage_options - β
Timezone Safe: Uses
gmdate()instead ofdate() - β SQL Safe: No direct database queries (read-only from files)
- β Input Sanitization: All user inputs sanitized
- GitHub Repository: [Your GitHub URL]
- Documentation: See PRAISONPRESS-README.md for technical details
- Support: WordPress.org support forums
- Issues: Report on GitHub
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
- β Initial release
- β File-based content management
- β Dynamic post type discovery
- β YAML front matter support
- β Markdown parsing
- β Cache management
- β Admin dashboard
- β Index system for large datasets
- β Docker/Kubernetes support
- β Security hardening
- β WP-CLI integration
MervinPraison
Website: https://mer.vin
GitHub: [Your GitHub Profile]
GPL v2 or later
If you find this plugin helpful, please:
- β Star the repository
- π’ Share with others
- π Report issues
- π‘ Suggest features
Production-Ready Feature - Convert your existing WordPress content to Markdown files with full metadata preservation. Tested with large-scale exports (50,000+ posts).
CLI Export (All post types):
php wp-content/plugins/praisonpressgit/scripts/export-to-markdown.phpAdmin Panel Export:
- Go to PraisonPress β Export
- Select post type (or "All Post Types")
- Choose batch size (100 recommended for 50K+ posts)
- Click "Start Export"
- Background processing with real-time progress tracking
β All Content & Metadata:
- Post title, content, excerpt, status, dates
- Categories, tags, and ALL custom taxonomies
- Featured images
- ALL custom fields (including ACF fields)
- Author information
β ACF (Advanced Custom Fields) Support:
- Automatically detects ACF plugin
- Exports ALL ACF field types (repeaters, flexible content, galleries, relationships)
- Uses ACF API for proper formatting
- Works with 50+ field groups
β Large Exports (50K+ posts):
- Background processing (WP-Cron)
- Configurable batch sizes
- Real-time progress tracking
- Safe for shared hosting
- Page-closeable (runs in background)
---
title: "Post Title"
slug: "post-slug"
author: "admin"
date: "2024-10-31 12:00:00"
status: "publish"
categories:
- "Category 1"
tags:
- "tag1"
# All custom taxonomies (artist, album, book, etc.)
artist:
- "Artist Name"
# All custom fields including ACF
custom_fields:
field_name: "value"
acf_repeater:
- item: "value1"
- item: "value2"
---
# Content in Markdown
Your content here...Made with β€οΈ for WordPress developers who love Git and Markdown
Important: Each WordPress site needs its own GitHub OAuth App!
For detailed instructions on setting up GitHub OAuth for your site, see:
- Create GitHub OAuth App: https://github.com/settings/developers
- Set Redirect URL:
https://yoursite.com/wp-admin/admin.php?page=praisonpress-settings&oauth=callback - Configure Plugin: Add Client ID and Secret to
site-config.ini - Connect: Click "Connect to GitHub" in WordPress admin
See the full guide for detailed step-by-step instructions.