Welcome to TextPress

TextPress is a simple, light weight blogging engine for PHP geeks, which can be hosted in PHP clouds like PHP Fog, Pagodabox, Orchestra.io, etc (though you can use traditional hosting to host TextPress, it is less preferred). It is inspired from toto, a flat-file blog engine in Ruby. TextPress is built on top of Slim, a light weight php framework. It uses Git, the most popular version control system, for publishing articles. Articles can be written in markdown or html syntax.


  • Simple, easy to use.
  • Publish article using git => Content versioning Yaay!
  • Highly secure (as secure as your hosting platform).
  • Blazing fast.
  • Write articles in text file, with metadata in json format.
  • Easy integration with disqus commenting system.
  • Feeds, Sitemap, etc.
  • Caching.


  • PHP > 5.3
  • You should have Git installed, if using Git for publishing articles.
  • You should not hate using commands
  • Knowledge or willingness to learn HTML/Markdown
  • Account in any PHP PaaS like PHP Fog, Pagodabox, etc.


TextPress can be installed by downloading from Github.

Or, clone TextPress using Git.

shameer@ubuntu:~$ git clone git@github.com:shameerc/TextPress.git your-project

After downloading TextPress, you will have to install vendor packages using composer from the project folder.

shameer@ubuntu:~$ cd your-project
shameer@ubuntu:~$ curl -s https://getcomposer.org/installer | php //If you don't have composer
shameer@ubuntu:~$ ./composer.phar install

It will install Slim framework and other required libraries.

Running the application

To see a real-live page in action, start the PHP built-in web server with command:

$ composer run

Then, browse to http://localhost:8888/.


├── articles
│   └── 2012-02-07-welcome-to-textpress.txt
├── cache
├── config
│   └── config.php
├── src
│   └── shameerc
│       └── Textpress
├── tests
├── themes
│   └── textpress
│       └── assets
│           ├── css
│           ├── img
│           └── js
├── vendor
├── composer.json
└── index.php


Config file located in config directory returns an array of site configuration which consists of site settings and routes. Site settings includes

'site.name'         => 'TextPress',   // Site name (Global)
'site.title'        => 'PHP Flat-file blog engine',  // Site default title (Global)
'site.description'  => 'TextPress is an open source flat-file blog engine for PHP',  // Site default description (Global)
'author.name'       => 'Author name', // Global author name
'article.path'      => './articles',      // Path to articles
'date.format'       => 'd M, Y',   // Date format to be used in article page (not for routes)
'themes.path'       => './themes',  // Path to templates
'active.theme'      => 'textpress',  // Current active template
'layout.file'       => 'layout',    // Site layout file
'file.extension'    => '.txt',   // file extension of articles
'disqus.username'   => '',   // Your disqus username or false (Global)
'markdown'          => true, //Enable of disable markdown parsing.
'assets.prefix'     => '', // prefix to be added with assets files
'prefix'            => '',   // prefix to be added with all URLs (not to assets). eg : '/blog'
'google.analytics'  => false, // Google analytics code. set false to disable
'cache' => array(
    'enabled'   => true, // Enable/Disable cache
    'expiry'    => 24, // Cache expiry, in hours. -1 for no expiry
    'path'      => './cache'


TextPress defines all routes as an array. Each route should have a url pattern and a template file. You can write route conditions optionally. For a particular route, layout can be setting layout => false. TextPress comes with the following default routes.

'__root__'  => array(
    'route'     => '/',
    'template'  =>'index',
    'layout'    => 'layout_home'
'article' => array(
    'route'     => '/:year/:month/:date/:article',
    'template'  =>'article',
    'conditions'    => array(
         'year'     => '(19|20)\d\d'
        ,'month'    =>'([1-9]|[01][0-9])'
        ,'date'     =>'([1-9]|[0-3][0-9])'
'category' => array(
    'route'     => '/category/:category',
    'template'  => 'index'
'tag'   => array(
    'route'     => '/tag/:tag',
    'template'  => 'index'
'archives' => array(
    'route'     => '/archives(/:year(/:month(/:date)))',
    'template'  => 'archives',
    'conditions'=> array(
        'year'      => '(19|20)\d\d',
        'month'     =>'([1-9]|[01][0-2])'
'about' => array(
    'route'     => '/about',
    'template'  => 'about'
'rss'   => array(
    'route'     => '/feed/rss(.xml)',
    'template'  => 'rss',
    'layout'    => false,
'atom'  => array(
    'route'     => '/feed(/atom(.xml))',
    'template'  => 'atom',
    'layout'    => false,
'sitemap' => array(
    'route'     => '/sitemap.xml',
    'template'  => 'sitemap',
    'layout'    => false,

Writing posts

All posts need to be stored in article.path. articles is the default location for posts. To write a new post, create a text file with name in the format yyyy-mm-dd-article-slug.txt. URL to this article will be /yyyy/mm/dd/article-slug/. An article will have a meta part and a content part which must be separated with a blank line. Article must start with the meta informations stored in json format. "title" and "date" are the mandatory meta information. Inside meta, You can specify "article-slug" which is not necessary. If slug is not present, TextPress will take the title to create slug. For example, metadata of this artilce will look like this.

 "title":"Welcome to TextPress",
 "date" : "07-02-2012",
 "slug" : "welcome-to-textpress",
 "author" : "Admin",
 "tag" : "intro"

You can write articles in markdown, html or mix of both formats. Articles will be passed to Markdown parser for generating corresponding html. If you are not using markdown, it can be disabled globally by setting markdown => false in config file.


For each request, TextPress has to generates HTML files from the article files and send it to the browser. To improve the performance, TextPress caches the HTML files generated for each request. All the subsequent requests will be served from the cache.

To enable caching you need to set the cache configuration in config.php file.

'cache' => array(
    'enabled' => true, // Enable/Disable cache
    'expiry' => 24, // Cache expiry, in hours. -1 for no expiry
    'path' => './cache' // Cache directory

Cache can be enabled by setting enabled to true. Cache expiry can be specified with expiry, in hours (default is 24 hours). Make sure that you've created the cache directory and given write permission.

One caveat is that you will have to clear the cache when you update the post/ write new one.


Right now it may not be befitting to your requirements. So don't be afraid to fork and customize TextPress. Just take the code, do what ever you want :)


Slim Framework

PHP Markdown extra

Twitter Bootstrap

PHP Fog For their awesome platform which allowed me to host this site for free .


If you find any issues feel free to report it here.

Happy Blogging