Skip to content
This repository has been archived by the owner on Apr 13, 2021. It is now read-only.
/ Paste Public archive

Paste is a lightweight CMS built around static files and folders instead of a database.


Notifications You must be signed in to change notification settings


Folders and files

Last commit message
Last commit date

Latest commit


Repository files navigation


  • Paste is a lightweight "CMS" built around static files and folders instead of a database.
  • Each HTML file represents a page in the menu, each folder represents a section, to infinite depth.
  • Mustache is used for logic-less templating including partials.
  • Variables and templating cascade down through the site heirarchy.
  • Configuration is defined within the HTML source, like so:
@template: master
@partial: project
@title: The Page Title
@visible: TRUE // visible in menu
@label: Menu Label (optional)

Design Goals

  • simple routing with user-definable routes and closures
  • Mustache for ultra dumb templating
  • flexible templates and cascading page partials
  • configuration via simple inline syntax
  • takes some cues from Stacey App.
  • use latest PHP tech, e.g. Composer


  • PHP 5.3+
  • Apache mod_rewrite
  • Mustache.php (installed automatically by Composer)

Quick Start / Demo

The fastest way is to clone the demo site and modify to taste! Be sure to run composer update to install dependencies.

Demo Site:



Use Composer. Add paste/paste to your project's composer.json:

    "require": {
        "paste/paste": "dev-master"

Create an index.php file for the front router: (or copy from the demo site)


// composer autoload
require 'vendor/autoload.php';
use Paste\Paste;

// configuration
$config = array(
	// optionally specify a 'base_url' if serving Paste from a subdirectory, i.e. RewriteBase
	// 'base_url' => '/paste-demo',
	// relative path to content directory
	// 'content_dir' => 'content',
	// relative path to template directory
	// 'template_dir' => 'templates',
	// relative path to cache directory
	// 'cache_dir' => 'cache',

// load config and parse content directory
$paste = new Paste($config);

// (optional) user defined routing
// 'route regex' => any valid callback
// matched tokens from the regex will be passed as parameters, with $paste instance first
$paste->add_route('blog/([0-9]{4})/([0-9]{2})/([0-9]{2})/([A-Za-z0-9-_]+)', function($paste, $year, $month, $day, $name) {
	// ignore date and run normal content request
	return $paste->render_url("blog/$name");

// init routing and run

Create the content, templates, cache directories in your web root. The cache folder must be writeable by Apache. Your web root should end up looking something like this:


Add the root content index file, content/index.html:

<!-- @title: Hello World -->
<!-- @template: template -->
<h3>Hello, world!</h3>

Add the first template, e.g. templates/template.stache:

<!doctype html>
	<meta charset="utf-8">

Create an .htaccess file to enable URL rewriting: (or copy from the demo site)

# don't list directories
Options -Indexes

# Turn on URL rewriting
RewriteEngine On

# Installation directory -- same as your 'base_url'
RewriteBase /

# Protect dot files from being viewed
<Files .*>
	Order Deny,Allow
	Deny From All

# Protect application and system files from being viewed
RewriteRule ^(?:vendor|content|templates|cache)\b.* index.php/$0 [L]

# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php/$0 [PT]

# use utf-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8

# force utf-8 for a number of file formats
AddCharset utf-8 .html .css .js .xml .json .rss

Now visit your Paste site in a web browser and take in the magic!


  • allow a rewrite base that is not root, i.e. allow running Paste from a subdirectory
  • classes seem arbitrary, combine Paste & Content?
  • make it completely OO, not sure why so much static


  • render content with Mustache string loader to allow referencing partials and context
  • add a shortcut to hide pages like _ underscore prefix in the filename
  • make example site more generic, add dummy text and illustrative CSS for menu heirarchy
  • write new description and a quick usage guide w/ screenshots
  • single template(), rest is partials()
  • move static content stuff into Paste
  • refactor Page lib
    • Page Constructor -- change factory to Page::from_path()
    • update Page->is_current() and Page->is_parent
    • consolidate nav stuff to next() and prev(), remove unused
    • change page->parents to something like parent_paths
    • simplify find and find_all, etc.
    • render menu() separately to remove invisible pages
    • remove section in favor of parent
  • use Mustache filesystem loader for partials and cache
  • make Menu mustache partial resursive for infinite depth -- fix CSS
  • more unique syntax for page/section vars
  • proper cascading templates
  • redo the section control as suggested in Page->factory? no
  • return Paste to all static class
  • Combine Content into Page
  • Combine Controller & Content
  • Combine Page & Template classes
  • change mustache templates to just .stache
  • just link to tumblr instead of using Tumblr blog driver
  • consider only loading structure on demand (e.g. menu()), and then only loading page vars
  • does a file based site really need a file cache? -- use memcache if anything. benchmark cache vs. no cache
  • use namespacing, make autoloader PSR-0 compatible and package it for composer
  • Paste::route() syntax for user defined routes
  • separate core and a sample site for this repo, move personal portfolio stuff to separate repo
  • simplify as much as possible. too much code for what it's supposed to be


Paste is a lightweight CMS built around static files and folders instead of a database.








No releases published


No packages published