The blogging engine (and many more) formerly known as Typo
Publify is a modern, lightweight, comprehensive, full featured weblog engine using Ruby on Rails. It’s been around since 2004 and probably the oldest open source project based on Ruby on Rails.
Publify provides you with everything you need to easily publish content on the Web.
Multi user: role based management for multiple author websites.
Powerful plugin engine: available both in page, as text filters and as widgets.
Comprehensive theme support: every aspect of the blog can be redesigned according to your needs without changing a single line of the core engine.
Cool API: Publify supports various blogging engine APIs so you can publish from desktop clients.
On demand syntax: Publify supports various syntax (plain HTML, Markdown, Textile)
Multilingual: Publify is (more or less) translated in English, French, German, Danish, Norvegian, Japanese, Hebrew, Simplified Chinese, Mexicain Spanish, Italian, Lituanese, Dutch, Polish, Romanian…
If you want to give Publify a try, check out our full featured demo
The login / password to the admin are:
- Administrator: admin / admin
- Publisher: publish / publish
The demo is reset every hour.
For a production blog, you should download Publify 7.0.0.
If you feel adventurous or want to hack on Publify, clone Publify repository.
To install Publify you need the following:
- Ruby 1.9.3 or 2.0
- Ruby On Rails 3.2.13
- A database engine, MySQL, PgSQL or SQLite3
- Unzip Publify archive
- Rename database.yml.yourEngine as database.yml
- Edit database.yml to add your database name, login and password.
$ bundle install
$ rake db:create
$ ./script/rails server
You don’t need to run rake db:migrate
and rake db:seed
as Publify will
take care of everything the first time you access 127.0.0.1:3000.
In order to install Publify on Heroku, you’ll need to do some minor tweaks.
Just add the Heroku Postgres plugin to your app. When deploying, Heroku will write the database configuration so you don’t have to do anything.
You need to setup Amazon s3 storage to be able to upload files on your
blog. Edit config/storage.yml
provider: AWS
engine: AWS
aws_access_key_id: YOUR_AWS_ACCESS_KEY_ID
aws_secret_access_key: YOUR_AWS_SECRET_ACCESS_KEY
aws_bucket: YOUR_AWS_BUCKET_NAME
Replace the default Gemfile
by Gemfile.heroku
:
cp Gemfile Gemfile.heroku
.
Heroku may also need the Ruby version to be declared. You may add
ruby "1.9.3"
after the source to use the latest Ruby version.
Heroku will also boot your app on Webrick, the default Ruby web server, which is rather slow. Just add thin to get some free speed.
Now, run
bundle install
Heroku needs Gemfile.lock to be in the Git repository. Remove
Gemfile.lock from .gitignore and add it git add .gitignore Gemfile.lock
Publify offers a very slick and evolved theme engine. It allows theme developers to override every view of the application, or just add their own layout, stylesheet, and let Publify do the job.
A Publify template is made with a minimum of three main files:
- The layout.
- A CSS stylesheet.
- An about file using Markdown.
You can eventually add a screenshot, and some fancy pictures in your theme, but they are not mandatory.
Browsing a default Publify theme looks like:
themes
\_ my theme
\_ about.markdown
\_ images
\_ layouts
\_ default.html.erb
\_ preview.png
\_ stylesheets
\_ style.css
Your main file is in layouts/default.html.erb
, which is your theme
main template. This is a simple RHTML file in which you’ll call Publify
main methods.
This is a standard HTML file header, along with some Ruby calls. Nothing complicated at all here.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr">
<head profile="http://gmpg.org/xfn/11">
<title><%= h(page_title) %></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="fr" />
<%= stylesheet_link_tag "/stylesheets/theme/style", :media => ‘all’ %>
<%= page_header %>
</head>
There are some things you must pay attention to:
h(page_title)
is the title of the current document. This is generated by Publify, and translation in supported languages is done when available.stylesheet_link_tag
is where you call your CSS stylesheet. It will always be in/stylesheets/theme/
. Some call itstyle.css
, someapplication.css
, but do whatever you want.page_header
with display a page header generated by Publify. It will provide:- ICBM tag, for geo localization
- Your meta description
- Your meta keywords
- Your RSD
- URLs for both your RSS and Atom feeds, for automatic discovery
- Stylesheets used by Publify embedded plugins, so that you don’t have to care
- Google Analytics tags, if provided
Every div
included here is not mandatory. You just need to care about
the Ruby calls.
<body>
<div id="header">
<h1><a href="<%= this_blog.base_url %>"><%= this_blog.blog_name %></a></h1>
<h2><%= this_blog.blog_subtitle %></h2>
</div>
<div id="page">
<div id="content">
<%= yield %>
</div>
<div id="sidebar">
<%= render_sidebars %>
</div>
</div>
</body>
</html>
The important things are:
this_blog.base_url
is your blog URL defined in your settings.this_blog.name
is your blog title, defined in your settings.this_blog.blog_subtitle
is your blog tagline, defined in your settings.yield
is the most important part of your layout. It renders the page main content according to what you’re browsing (articles, tags, categories…)render_sidebars
displays your sidebar made of Publify plugins.
Here you are. You can now build a standard Publify theme and profit from the great things Publify can provide.
Publify offers custom post type. Let’s say you blog about tech and wine, and want to display wine posts differently. You upload an attached picture to every wine related post and want it to be displayed in every article. You also have a custom CSS for wine blocks, and don’t want people to comment on your wine reviews (this is to make the sample template more readable). You also want to apply this to the category page.
First, login to your blog admin and go to Article → Post Types. Create a new post type called Wine.
Now, create a new category in Articles → Categories. We’ll call it Wine too.
Create two custom templates: one to display wine related articles, and one to display the Wine category.
First, create a template called wine.html.erb
in your
theme/views/articles/
directory. If the views/articles
directory
doesn’t exist, create it. The template will probably look like something
like this:
<div class="wine" %>>
<h2><%= link_to_permalink @article, @article.title %></h2>
<p class="auth"><%= _("Posted by")%> <%= author_link(@article) %>
<%= display_date_and_time @article.published_at %></p>
<%= @article.html(:body) %>
<!-- This display the attached images -->
<% @article.resources.each do |upload| %>
<img src='<%= "#{this_blog.base_url}/files/#{upload.filename}" %>' class="centered" />
<% end %>
<div class="extended">
<%= @article.html(:extended) %>
</div>
</div>
<p class="meta">
<%= article_links @article %>
</p>
Do the same with the wine category. In your theme /views/categories
,
create a wine.html.erb
template. This is adapted from the
category/show.html.erb
of one of the stock themes.
<h1><%= link_to "Wine", "#{this_blog.base_url}/category/#{params[:id]}" %></h1>
<div class='category-excerpt <%= "border" if @article_counter >= 0 %>' id="article-<%= article.id %>">
<% @articles.each do |article| %>
<h2><%= link_to_permalink(article, article.title) %></h2>
<p class="auth"><%= _("Posted by")%> <%= author_link(earticle) %>
<%= display_date_and_time article.published_at %></p>
<%= article.html(:body) %>
<!-- This display the attached images -->
<% article.resources.each do |upload| %>
<img src='<%= "#{this_blog.base_url}/files/#{upload.filename}" %>' class="centered" />
<% end %>
<div class="extended">
<%= article.html(:extended) %>
</div>
<% end %>
</div>
<div id='paginate'>
<%= paginate @articles, { :previous_label => _('Previous'), :next_label => _('Next') } %>
</div>
Here you are, you can now write about wine. Just don’t forget to choose the wine post type within the editor.
As Publify plugins are just plain Rails plugins, creation is kind of trivial.
./script/rails generate plugin publify_sample_plugin
Create some folders to reflect a Rails application tree:
cd vendor/plugins/publify_sample_plugin
mkdir -p app/controllers/admin app/models app/helpers/admin config app/views/admin
Make Publify access your code. Edit your init.rb
file and add the
following:
PLUGIN_NAME = 'publify_sample_plugin'
PLUGIN_PATH = "#{::Rails.root.to_s}/vendor/plugins/#{PLUGIN_NAME}"
PLUGIN_CONTROLLER_PATH = "#{PLUGIN_PATH}/app/controllers"
PLUGIN_VIEWS_PATH = "#{PLUGIN_PATH}/app/views"
PLUGIN_HELPER_PATH = "#{PLUGIN_PATH}/app/helpers"
PLUGIN_MODELS_PATH = "#{PLUGIN_PATH}/app/models"
config.autoload_paths += %W(#{PublifySamplePlugin::PLUGIN_CONTROLLER_PATH}
#{PublifySamplePlugin::PLUGIN_HELPER_PATH}
#{PublifySamplePlugin::PLUGIN_VIEWS_PATH}
#{PublifySamplePlugin::PLUGIN_MODELS_PATH}
ActionView::Base.send(:include, PublifySamplePlugin::Helper)
Unless Rails generators, your plugin won’t be allowed to change
routes.rb. We want our end users to remove them if they don’t want them
anymore. So we’re going to create our own config/routes.rb
. It’s going
to look like this:
ActionController::Routing::Routes.draw do |map|
map.connect 'sample_plugin/:action', :controller => 'publify_sample', :action => 'index'
%w{ sample_plugin }.each do |i|
map.connect "/admin/#{i}", :controller => "admin/#{i}", :action => 'index'
map.connect "/admin/#{i}/:action/:id", :controller => "admin/#{i}", :action => nil, :id => nil
end
end
I know, we’re still using Rails 2 routing DSL. It’s bad but Rails 3 can’t handle everything we do.
The first block is for your frontend controllers, the second one for the admin. Easy as pie isn’t it?
Add your models files in app/models exactly like on any Rails application. You can use any Active Record relations you want and access or extend existing Publify models.
To create your database schema, edit your init.rb
file, and add the
following code:
unless ::PublifySamplePlugin.table_exists?
ActiveRecord::Schema.create_table(PublifySamplePlugin.table_name) do |t|
t.column :name, :string
t.column :description, :text
end
end
To be able to display your content within your Publify blog layout, every front end controller will need the following code:
class PublifySamplePluginController < ActionController::Base
unloadable
layout :theme_layout
before_filter :template_root
def template_root
self.class.view_paths = ::ActionController::Base.view_paths.dup.unshift(PublifySamplePlugin::PLUGIN_VIEWS_PATH)
end
def theme_layout
File.join("#{::Rails.root.to_s}/themes/#{Blog.default.theme}/views", Blog.default.current_theme.layout(self.action_name))
end
end
There’s certainly a cleaner way to do it by not repeating the code, but I’ll dig into it later.
Nothing special here. Really.
OK, now you want to give your plugin a fancy back office? Let’s go.
Edit your init.rb
. In your model creation block, add the following:
admin = Profile.find_by_label('admin')
admin.modules << :publifysampleplugin
admin.save
publisher = Profile.find_by_label('publisher')
publisher.modules << :publifysampleplugin
publisher.save
This will update both admin and publisher profiles giving them the rights to access your plugin admin.
Add them to the access control list (and the menu as well). This is still in init.rb
AccessControl.map :require => [ :admin, :publisher, :contributor ] do |map|
map.project_module :publifysampleplugin, nil do |project|
project.menu "My plugin meny", { :controller => "admin/publify_sample_plugin" }
project.submenu "My submenu", {:controller => "admin/publify_sample_plugin_other" }
end
end
Edit your lib/publify_sample_plugin.rb and add the following:
module Helper
def class_publifysampleplugin
return class_selected_tab if controller.controller_name =~ /publify_sample_plugin/
class_tab
end
end
This allows you to manage the tabs highlight in the admin.
Your controllers will go to app/controllers/admin
and will all look
like this, pretty like normal admin controllers:
module Admin; end
class Admin::PublifySamplePluginController < Admin::BaseController
layout 'administration'
unloadable
...
end
Publify plugins admin views look like normal admin views. Minimum code is:
<% @page_heading = _('Sample plugin') %>
<% subtabs_for(:publifysampleplugin) %>
You can access any admin helper like save_or_cancel or link_to_new.
- Download Publify source code
- Report a bug
- Frequently Asked Questions
- Official Publify blog
- Follow us on Twitter
If you need help or want to contribute to Publify, you should start with the following:
- IRC: #publify on irc.freenode.net
This is a list of Publify maintainers. If you have committed, please add your name and contact details to the list.
Frédéric de Villamil frederic@publify.co blog: http://t37.net irc: neuro`
Matijs van Zuijlen blog: http://www.matijs.net/blog/ irc: matijs
Thomas Lecavelier blog: http://blog.ookook.fr/ irc: ook
Yannick François blog: http://elsif.fr irc: yaf
And many more cool people who’ve one day or another contributed to Publify.
Original Author: Tobias Luetke blog: http://blog.leetsoft.com/ irc: xal
Enjoy, The Publify team