A community directory of blogs built on the PureBlog platform. Automatic verification, instant approval. https://discover.thinkroot.xyz/
  • PHP 42.8%
  • CSS 21.3%
  • HTML 21.3%
  • JavaScript 14.6%
Find a file
2026-05-13 09:26:12 +03:00
assets fix error 2026-05-13 09:26:12 +03:00
data pureblog discover 2026-04-22 23:40:17 +03:00
.gitignore pureblog discover 2026-04-22 23:40:17 +03:00
.htaccess add badge, 404 page & fix 2026-04-27 16:45:35 +03:00
404.html add badge, 404 page & fix 2026-04-27 16:45:35 +03:00
about.html fix error 2026-05-13 09:26:12 +03:00
admin.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
aggregated-feed.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
api.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
apple-touch-icon.png pureblog discover 2026-04-22 23:40:17 +03:00
badge.svg add badge, 404 page & fix 2026-04-27 16:45:35 +03:00
blog.php fix error 2026-05-13 09:26:12 +03:00
cron-scan.php Improve detection, admin, frontend, SEO and cleanup 2026-05-08 10:38:37 +03:00
favicon.ico pureblog discover 2026-04-22 23:40:17 +03:00
feed.atom.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
feed.json.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
feed.xml.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
index.html fix error 2026-05-13 09:26:12 +03:00
latest.php fix error 2026-05-13 09:26:12 +03:00
LICENSE pureblog discover 2026-04-22 23:40:17 +03:00
migrate-feeds.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
og-image.png fixe Pure Blog name 2026-04-25 15:26:52 +03:00
opml.php add ompl export for blogs 2026-04-25 18:59:12 +03:00
privacy.html fix error 2026-05-13 09:26:12 +03:00
random.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
README.md update README.md 2026-05-08 18:29:07 +03:00
robots.txt fix 2026-04-27 16:23:31 +03:00
set-password.php Improve detection, admin, frontend, SEO and cleanup 2026-05-08 10:38:37 +03:00
sitemap.php Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
sitemap.xml Add latest articles, blog profiles, privacy page and security fixes 2026-05-08 18:25:49 +03:00
submit.html fix error 2026-05-13 09:26:12 +03:00

Pure Blog Discover

A community directory of blogs and websites built on the Pure Blog platform. Users can submit their blog for listing - the system automatically verifies whether the site uses Pure Blog and approves it instantly, without any manual review.

Built with PHP, vanilla JavaScript, and HTML/CSS. No frameworks, no databases - just flat JSON files.

Live: discover.thinkroot.xyz


Features

  • Automatic verification - the server fetches the submitted URL and uses an 8-signal scoring system anchored in Pure Blog's source code to detect the platform
  • Instant approval - if Pure Blog is detected, the blog is added to the directory immediately
  • Blog descriptions - automatically fetched from <meta name="description"> at submit time
  • Language detection - automatically detects the blog's language from the <html lang> attribute
  • Feed detection - automatically detects the blog's RSS/Atom feed and displays an icon on each card
  • Favicon fetching - displays each blog's favicon via Google Favicon Service
  • "New" badge - blogs added in the last 7 days are marked with a badge in the directory
  • Blog profile pages - each blog has a dedicated page with description, meta-data and recent articles
  • Latest Articles - aggregated feed of recent posts from all listed blogs, updated hourly with language filter, keyword search, pagination and random article button
  • Aggregated RSS feed - subscribe to articles from all listed blogs at once via /aggregated-feed.php
  • Dark mode - respects system preference (prefers-color-scheme), toggleable via header button, persisted in localStorage; also available in the admin panel
  • Random order - blog list is shuffled on every page load
  • Search - client-side search by blog name, URL and description
  • Language filter - filter the directory by blog language
  • Pagination - 21 blogs per page
  • RSS, Atom and JSON Feed - subscribe to the directory to follow new additions
  • OPML export - import all blog feeds into any RSS reader at once
  • Share prompt - after approval, share your listing on Mastodon or Bluesky
  • Admin panel - password-protected panel to add, edit, remove and scan blogs
  • Periodic scan - automatic cron job checks all blogs and flags those that no longer use Pure Blog
  • Rate limiting - max 3 submissions per IP per hour (bypassed in admin)
  • Privacy policy - documents data collected, third-party services and user rights
  • SEO - meta tags, Open Graph, Twitter Card, JSON-LD structured data, dynamic sitemap, defer on scripts
  • Accessible - semantic HTML, skip links, ARIA labels, keyboard navigation, focus-visible styles, reduced-motion support
  • Responsive - tested from 320px to 1440px; 3-column grid on desktop, 2 on tablet, 1 on mobile
  • Security hardened - CSRF protection, SSRF prevention, honeypot, security headers via .htaccess
  • Open source - MIT License

File structure

pureblog-discover/
├── index.html              # Directory listing page
├── submit.html             # Blog submission form
├── about.html              # About page
├── privacy.html            # Privacy policy
├── latest.php              # Latest articles aggregator (RSS feeds from all blogs)
├── blog.php                # Individual blog profile page
├── api.php                 # REST API - all endpoints
├── admin.php               # Password-protected admin panel
├── aggregated-feed.php     # RSS feed of latest articles from all blogs
├── random.php              # Redirects to a random article
├── sitemap.php             # Dynamic XML sitemap
├── sitemap.xml             # Static sitemap fallback
├── feed.xml.php            # RSS 2.0 feed for the directory
├── feed.atom.php           # Atom feed for the directory
├── feed.json.php           # JSON Feed for the directory
├── opml.php                # OPML export of all blog feeds
├── cron-scan.php           # Periodic cron script to scan all blogs
├── set-password.php        # CLI utility to generate admin password hash
├── robots.txt              # Search engine directives
├── .htaccess               # Apache config - security headers, caching, gzip
├── favicon.ico             # Multi-size favicon (16/32/48px) - must stay in root
├── apple-touch-icon.png    # iOS home screen icon - must stay in root
├── og-image.png            # Open Graph image - must stay in root
├── badge.svg               # "Listed on Pure Blog Discover" badge for blogs
├── LICENSE
├── README.md
├── assets/
│   ├── css/
│   │   ├── main.css        # Public site styles
│   │   ├── latest.css      # Latest Articles page styles
│   │   ├── blog.css        # Blog profile page styles
│   │   └── admin.css       # Admin panel styles
│   ├── js/
│   │   ├── main.js         # Public site JavaScript
│   │   └── admin.js        # Admin panel JavaScript
│   └── images/
│       ├── logo.svg        # Vector logo
│       ├── favicon.svg     # Vector favicon
│       ├── favicon-32.png
│       ├── favicon-48.png
│       └── og-image.png    # Open Graph image (1200x630)
└── data/
    ├── .htaccess           # Denies all web access to this directory
    ├── blogs.json          # Blog database
    ├── articles.json       # Cached article feed (auto-managed, excluded from git)
    └── rate.json           # Rate limit tracking (auto-managed)

Requirements

  • PHP 7.4 or higher (PHP 8.1+ recommended)
  • Apache with mod_rewrite, mod_headers, mod_deflate, mod_expires
  • cURL enabled in PHP
  • Write permissions on data/blogs.json and data/rate.json

Deploy on shared hosting

  1. Upload all files to public_html/ (or a subdirectory)

  2. Set file permissions:

    data/blogs.json     644
    data/rate.json      644
    data/articles.json  644  (created automatically on first visit to /latest.php)
    data/               755
    
  3. Set the admin password - run this command via SSH or a PHP terminal:

    php set-password.php
    

    Copy the generated hash and paste it into admin.php as the value of ADMIN_PASSWORD_HASH.

  4. Set a secret key for the scan endpoint - open api.php and change:

    define('SCAN_SECRET', 'CHANGE_THIS_TO_A_RANDOM_SECRET_KEY');
    
  5. Replace all occurrences of YOUR_DOMAIN with your actual domain in:

    • index.html, submit.html, about.html - canonical URL, OG tags
    • sitemap.php - BASE_URL constant
    • robots.txt - Sitemap directive
  6. Set up the periodic cron job in cPanel or via SSH:

    Minute: 0 | Hour: 8 | Day: * | Month: * | Weekday: 1
    Command: /usr/local/bin/php /home/YOUR_USER/public_html/YOUR_DIR/cron-scan.php
    
  7. Verify the setup is working by visiting:

    https://YOUR_DOMAIN/api.php?action=ping
    

    All values should return true.


API endpoints

All endpoints are served by api.php.

Method Endpoint Auth Description
GET ?action=list - Returns all approved blogs as JSON
GET ?action=token - Returns a CSRF token for the submit form
GET ?action=ping - Diagnostic endpoint - checks PHP, cURL, file permissions
GET ?action=scan Admin session or secret key Scans all blogs and flags those no longer using Pure Blog
POST ?action=submit CSRF token Public blog submission with rate limiting
POST ?action=admin-submit Admin session Add a blog with Pure Blog verification, no rate limit
POST ?action=admin-force-add Admin session Add a blog without Pure Blog verification
POST ?action=admin-edit Admin session Edit a blog's name, URL, language or description
POST ?action=admin-approve Admin session Clear the needs_review flag on a flagged blog
POST ?action=admin-delete Admin session Remove a blog by ID

Pure Blog detection

The system uses a two-stage scoring approach. Signals 1-4 are checked in the page HTML; signals 5-8 are checked in the linked CSS file. A blog is approved when htmlScore + cssScore >= 10.

HTML signals

Signal Description Points
1 <meta name="generator" content="Pure Blog"> 10 (definitive)
2 data-theme="light|dark|auto" on <html> tag +3
3 Inline CSS variable pairs: --bg-light/--bg-dark, --text-light/--text-dark, --accent-light/--accent-dark, --border-light/--border-dark, --accent-bg-light/--accent-bg-dark +2 per pair (max 8)
4 Inline SVG sprite containing id="icon-calendar", id="icon-tag", id="icon-edit" +7 (all 3)

Signals 2-4 require htmlScore + cssScore >= 10 to confirm detection.

CSS signals

Signal Description Points
5 /* !pb:9e4f2a817c3d6b05 */ fingerprint in style.css 10 (definitive)
6 CSS class combo: .post-nav-next, .admin-edit-link, p.tagline, .post-nav +3 per class (max 9)
7 CSS variable indirection: --bg-color: var(--bg-light) and --accent-bg-color: +3-4
8 html[data-theme="auto"] in CSS +3

Signals 1 and 5 are definitive on their own (score = 10). All other signals require combinations to reach the threshold. Signals 3-4 are emitted by includes/header.php and are absent when a user overrides it via Layout Partials; signals 6-8 are read from assets/css/style.css and survive layout customization.

For reliable detection, add this tag to your Pure Blog template:

<meta name="generator" content="Pure Blog">

If your blog is not detected automatically, contact discover@thinkroot.xyz to have it added manually.


Admin panel

Access the admin panel at /admin.php. After logging in you can:

  • Add a blog with automatic Pure Blog verification (no rate limit) and optional language override
  • Force add a blog without Pure Blog verification (for confirmed Pure Blog sites that cannot be verified automatically)
  • Edit a blog's name, URL, language code and description inline
  • Remove a blog with a browser confirmation dialog
  • Approve a flagged blog and clear its review status
  • Filter flagged - show only blogs that need review with one click
  • Search the blog list by name, URL or description
  • Scan all blogs manually via the scan button - flags blogs that no longer use Pure Blog
  • Stats - total, approved and flagged counts at a glance; breakdown by language

Automatic scan

The cron job (cron-scan.php) checks every blog in the directory and:

  • Marks blogs that no longer detect Pure Blog as needs_review
  • Restores blogs back to approved if Pure Blog is detected again
  • Leaves blogs unreachable due to temporary server errors unchanged

Flagged blogs appear in the admin panel with a yellow highlight and Needs review badge. They remain visible in the public directory until manually removed.


Feeds

The directory provides three feed formats, updated automatically as blogs are added:

Format URL
RSS 2.0 /feed.xml.php
Atom /feed.atom.php
JSON Feed /feed.json.php
OPML export /opml.php

Security

  • CSRF protection - all public form submissions require a session-bound CSRF token
  • SSRF prevention - submitted URLs are checked against private IP ranges before the server fetches them
  • Honeypot - an invisible field traps automated bot submissions
  • Rate limiting - public submissions are limited to 3 per IP per hour
  • Security headers - X-Frame-Options, X-Content-Type-Options, Content-Security-Policy, Referrer-Policy, Permissions-Policy
  • IP hashing - submitter IPs are stored as SHA-256 hashes, never in plain text
  • Atomic writes - blogs.json is written via temp file + rename to prevent data corruption
  • Data directory - data/ is protected by its own .htaccess that denies all web access

Contributing

Contributions are welcome. To contribute:

  1. Fork the repository
  2. Create a branch: git checkout -b feature/your-feature
  3. Commit your changes: git commit -m 'Add your feature'
  4. Push to the branch: git push origin feature/your-feature
  5. Open a pull request

Please keep the spirit of the project: no frameworks, no databases, minimal dependencies.


License

MIT License - see LICENSE for full text.