PHPackages                             ghastly/ghastly - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. ghastly/ghastly

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

ghastly/ghastly
===============

A PHP markdown blog with customizable themes and plugins.

v0.2(12y ago)4151PHP

Since Mar 27Pushed 12y ago1 watchersCompare

[ Source](https://github.com/GhastlyBlog/Ghastly)[ Packagist](https://packagist.org/packages/ghastly/ghastly)[ RSS](/packages/ghastly-ghastly/feed)WikiDiscussions master Synced 2d ago

READMEChangelog (2)Dependencies (4)Versions (3)Used By (0)

Ghastly
=======

[](#ghastly)

---

[![Build Status](https://camo.githubusercontent.com/e3926b050c22020506ec567afaec742d924e680b67ee7a6060ffab95994dcb78/68747470733a2f2f7472617669732d63692e6f72672f47686173746c79426c6f672f47686173746c792e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/GhastlyBlog/Ghastly) [![Scrutinizer Code Quality](https://camo.githubusercontent.com/d0bf8acdf062051e4c0229541515e00b8ac839358424f349067f9f436eaaf72b/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f47686173746c79426c6f672f47686173746c792f6261646765732f7175616c6974792d73636f72652e706e673f733d66313664623334613466323731623131383864323139376135306661303736613266386564636237)](https://scrutinizer-ci.com/g/GhastlyBlog/Ghastly/) [![Code Coverage](https://camo.githubusercontent.com/352aa99222577b5976a0e47a955f508648be1ec9a628662fad3863a9dded809c/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f47686173746c79426c6f672f47686173746c792f6261646765732f636f7665726167652e706e673f733d66616336383838646563663661653233623961653030633031383935643761653334323439646237)](https://scrutinizer-ci.com/g/GhastlyBlog/Ghastly/)

Ghastly is a minimal static blog engine that emphasizes the use of themes and plugins. Get a blog up and running in seconds, then customize it with plugins and themes.

[![ProjectImage](https://camo.githubusercontent.com/5c7bfcae24fc818351db083a5e33816eb9f68998d8b78b58bf985dc22ff1eb8f/687474703a2f2f67686173746c79626c6f672e6769746875622e696f2f47686173746c792f67686173746c792e706e67)](https://camo.githubusercontent.com/5c7bfcae24fc818351db083a5e33816eb9f68998d8b78b58bf985dc22ff1eb8f/687474703a2f2f67686173746c79626c6f672e6769746875622e696f2f47686173746c792f67686173746c792e706e67)

Installation
------------

[](#installation)

Ghastly requires PHP 5.4+.

```
git clone http://github.com/ghastlyblog/ghastly
cd ghastly
composer install
cp config.sample.php config.php
```

Edit `config.php` and you're done.

If you're installing in a sub directory, add `RewriteBase /path/to/dir` to `.htaccess`.

Ghastly ships with the following plugins enabled: [Archive](http://github.com/ghastlyblog/archive), [Rss](http://github.com/ghastlyblog/rss), [Admin](http://github.com/ghastlyblog/admin).

Posting
-------

[](#posting)

Create posts in `posts/` in the format of `2014-12-28-my-blog-post-title.md`. If you have the [Admin](http://github.com/ghastlyblog/admin) plugin installed, you can login at `http://localhost/admin`.

A post should have a jekyll-like front matter. An example post would look like:

```
---
title: My blog post title!
summary: A short summary about this post
tags: something, stuff
---

Lorem ipsum dolor sit amet...

```

##### Front Matter Items

[](#front-matter-items)

OptionExplanationtitleThe title of your blog postsummaryA summary of your blog posttagsA comma seperated list of tags for a postInstalling new Plugins and Themes
---------------------------------

[](#installing-new-plugins-and-themes)

Ghastly plugins and themes are available via Composer. Add them to your `composer.json` and run `composer update`.

Developing Themes
-----------------

[](#developing-themes)

Ghastly uses the `spooky` theme by default. You can copy it to a folder and rename it to something else to make your own theme. You can modify the html files however you like. Ghastly uses the [Twig](https://github.com/fabpot/twig) template engine.

Your template must have a `layout.html` file and a `single_post_layout.html` file.

### Template Variables

[](#template-variables)

Ghastly exposes the following variables for you to use in your templates:

VariableExplanation`posts`This is an array of posts`post`A single post`post.date`The date of a post`post.tags`The tags of a post`post.title`The title of a post`post.summary`The summary of a post if supplied through front matter`post.content`The html content of a postAll of the options in `config.php` are available as template variables.

### Publishing your theme for others

[](#publishing-your-theme-for-others)

Your theme must be in a repository and it must contain a `composer.json` file that references a type of `ghastly-theme` and must require `ghastly/theme-installer` as a dependency. Your repository must also be available on [Packagist](http://packagist.org). If your theme requires any plugins, list those as dependencies as well.

```
{
    "name" : "ghastly/spooky",
    "description" : "An excellent theme for Ghastly",
    "type" : "ghastly-theme",
    "license" : "UNLICENSE",
    "require" : {
        "ghastly/theme-installer" : "dev-master",
        "ghastly/archive" : "dev-master"
    }
}
```

Developing Plugins
------------------

[](#developing-plugins)

Before you embark on creating Ghastly plugins, be aware that the plugin API is likely going to be changing a lot as I play around with it.

Create a class that extends `Plugin` and put it in a folder with a name the same as the class you just created. . Your class should populate a public class property `$this->events` with any events the plugin will subscribe to.

```
class Archive extends \Ghastly\Plugin\Plugin {
    public $events;
    public function __construct()
    {
        $this->events = [
            ['event'=>'Ghastly.PreRoute', 'func'=>'onPreRoute'],
            ['event'=>'Ghastly.PreRender', 'func'=>'onPreRender']
        ];
    }
}
```

The plugin constructor can also accept a `$config` array if the user adds a configuration array for your plugin in their `config.php`.

Add the plugin to the `plugins` config option in `config.php` to enable it.

EventEvent Properties`Ghastly.PreRoute`Make your plugin respond to routes`Ghastly.PreRender`Inject template variables prior to renderingNote that all events are passed an instance of $Ghastly.

##### Ghastly.PreRoute

[](#ghastlypreroute)

Exposes: $router, $postModel, $renderer

Your Ghastly plugin can respond to routes by subscribing to this event. Example:

```
class Hello extends \Ghastly\Plugin\Plugin {
    public $events;
    public function __construct()
    {
        $this->events = [
            ['event'=>'Ghastly.PreRoute', 'func'=>'onPreRoute'],
        ];
    }

    public function onPreRoute(\Ghastly\Event\PreRouteEvent $event){
        $event->router->respond('/some_route', function() use ($event){
            $event->renderer->setTemplateVar('greeting', 'Hello World!');
            $event->renderer->addTemplateDir('plugins/hello');
            $event->renderer->setTemplate('hello_world.html');
        });
    }
}
```

The `hello_world.html` template now has `{{ greeting }}` available to it when Ghastly is responding to `some_route`. You can modify existing template variables in the same manner.

##### Ghastly.PreRender

[](#ghastlyprerender)

Exposes: $renderer, $postModel

This event lets you modify the Ghastly instance on any route after it and all plugins have responded to the route.

### Event Objects

[](#event-objects)

The $event object passed to your event function contains several useful objects:

##### $renderer

[](#renderer)

$renderer-&gt;addTemplateDir($str) - add a directory to the renderer to search for additional templates
$renderer-&gt;addTemplateVar($key,$val) - add a template variable
$renderer-&gt;setTemplate($str) - set the template ghastly will render

##### $postModel

[](#postmodel)

$postModel-&gt;findAll($limit) - will retrieve $limit posts and parse them
$postModel-&gt;findAllHeaders($limit) - will retrieve $limit posts but without getting the file contents
$postModel-&gt;getPostById($id) - will retrieve a single parsed post, $id should be a slug

##### $router

[](#router)

A [Klein](http://github.com/chriso/klein.php) instance. See their documentation. Use it for responding to new routes.

### Publishing your plugin for others

[](#publishing-your-plugin-for-others)

Your plugin must be in a repository and it must contain a `composer.json` file that references a type of `ghastly-plugin` and must require `ghastly/plugin-installer` as a dependency. Your repository must also be available on [Packagist](http://packagist.org)

```
    {
        "name" : "ghastly/archive",
        "description" : "An archive plugin for Ghastly",
        "type" : "ghastly-plugin",
        "license" : "UNLICENSE",
        "require" : {
            "ghastly/plugin-installer" : "dev-master"
        }
    }
```

Contributing
------------

[](#contributing)

Bring on the pull requests. I'm open to your ideas and suggestions. If you want to be very active, I can add you to the team.

Unit tests exist in `Ghastly/Test`. To run them, execute `vendor/bin/phpunit`.

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity11

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

4430d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5438bccecdb77af306356a1c802071f601dd3725e09eb1c3d62927908d566ed7?d=identicon)[chrisgillis](/maintainers/chrisgillis)

---

Top Contributors

[![chrisgillis](https://avatars.githubusercontent.com/u/40451?v=4)](https://github.com/chrisgillis "chrisgillis (111 commits)")

### Embed Badge

![Health badge](/badges/ghastly-ghastly/health.svg)

```
[![Health](https://phpackages.com/badges/ghastly-ghastly/health.svg)](https://phpackages.com/packages/ghastly-ghastly)
```

###  Alternatives

[sculpin/sculpin

Static Site Generator

1.5k102.8k12](/packages/sculpin-sculpin)[wallabag/wallabag

open source self hostable read-it-later web application

12.6k2.2k](/packages/wallabag-wallabag)[codefog/contao-haste

haste extension for Contao Open Source CMS

42650.8k139](/packages/codefog-contao-haste)[netgen/layouts-core

Netgen Layouts enables you to build and manage complex web pages in a simpler way and with less coding. This is the core of Netgen Layouts, its heart and soul.

3689.4k10](/packages/netgen-layouts-core)[netgen/content-browser

Netgen Content Browser is a Symfony bundle that provides an interface which selects items from any kind of backend and returns the IDs of selected items back to the calling code.

14112.1k8](/packages/netgen-content-browser)[leapt/core-bundle

Symfony LeaptCoreBundle

2529.1k4](/packages/leapt-core-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
