SkillAgentSearch skills...

SteamPress

A Blogging Engine and Platform written in Swift for use with the Vapor Framework

Install / Use

/learn @brokenhandsio/SteamPress

README

<p align="center"> <img src="https://user-images.githubusercontent.com/9938337/29742058-ed41dcc0-8a6f-11e7-9cfc-680501cdfb97.png" alt="SteamPress"> <br> <br> <a href="https://swift.org"> <img src="http://img.shields.io/badge/Swift-5.1-brightgreen.svg" alt="Language"> </a> <a href="https://github.com/brokenhandsio/SteamPress/actions"> <img src="https://github.com/brokenhandsio/SteamPress/workflows/CI/badge.svg?branch=master" alt="Build Status"> </a> <a href="https://codecov.io/gh/brokenhandsio/SteamPress"> <img src="https://codecov.io/gh/brokenhandsio/SteamPress/branch/master/graph/badge.svg" alt="Code Coverage"> </a> <a href="https://raw.githubusercontent.com/brokenhandsio/SteamPress/master/LICENSE"> <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License"> </a> </p>

SteamPress is a Swift blogging engine for use with the Vapor Framework to deploy blogs to sites that run on top of Vapor. It uses Fluent so will work with any database that has a Fluent Driver. It also incorporates a Markdown Provider allowing you to write your posts in Markdown and then use Leaf to render the markdown.

The blog can either be used as the root of your website (i.e. appearing at https://www.acme.org) or in a subpath (i.e. https://www.acme.org/blog/).

There is an example of how it can work in a site (and what it requires in terms of Leaf templates and the parameters is passes to them) at https://github.com/brokenhandsio/SteamPressExample.

Features:

  • Blog entries with Markdown
  • Multiple user accounts
  • Tags on blog posts
  • Snippet for posts
  • Draft Posts
  • Works with any Fluent driver
  • Protected Admin route for creating blog posts
  • Pagination on the main blog page
  • Slug URLs for SEO optimisation and easy linking to posts
  • Support for comments via Disqus
  • Open Graph and Twitter Card support
  • RSS/Atom Feed support
  • Blog Search

How to Use

Add as a dependency

SteamPress is easy to integrate with your application. There are two providers that provide implementations for PostgreSQL or MySQL. You are also free to write your own integrations. Normally you'd choose one of the implementations as that provides repository integrations for the database. In this example, we're using Postgres.

First, add the provider to your Package.swift dependencies:

dependencies: [
    // ...
    .package(name: "SteampressFluentPostgres", url: "https://github.com/brokenhandsio/steampress-fluent-postgres.git", from: "1.0.0"),
],

Then add it as a dependecy to your application target:

.target(name: "App",
    dependencies: [
        // ...
        "SteampressFluentPostgres"
    ])

In configure.swift, import the provider:

import SteampressFluentPostgres

Next, register the provider with your services:

try services.register(SteamPressFluentPostgresProvider())

The Provider's require you to add SteamPress' models to your migrations:

/// Configure migrations
var migrations = MigrationConfig()
// ...
migrations.add(model: BlogTag.self, database: .psql)
migrations.add(model: BlogUser.self, database: .psql)
migrations.add(model: BlogPost.self, database: .psql)
migrations.add(model: BlogPostTagPivot.self, database: .psql)
// Optional but recommended - this will create an admin user for you to login with
migrations.add(migration: BlogAdminUser.self, database: .psql)
services.register(migrations)

Manual Setup

First add SteamPress to your Package.swift dependencies:

dependencies: [
    // ...,
    .package(name: "SteamPress", url: "https://github.com/brokenhandsio/SteamPress", from: "1.0.0")
]

And then as a dependency to your target:

.target(name: "App",
    dependencies: [
        // ...
        "SteamPress"
    ])

This will register the routes for you. You must provide implementations for the different repository types to your services:

services.register(MyTagRepository(), as: BlogTagRepository.self)
services.register(MyUserRepository(), as: BlogUserRepository.self)
services.register(MyPostRepository(), as: BlogPostRepository.self)

You can then register the SteamPress provider with your services:

let steampressProvider = SteamPress.Provider()
try services.register(steampressProvider)

Integration

SteamPress offers a 'Remember Me' functionality when logging in to extend the duration of the session. In order for this to work, you must register the middleware:

var middlewares = MiddlewareConfig()
// ...
middlewares.use(BlogRememberMeMiddleware.self)
middlewares.use(SessionsMiddleware.self)
services.register(middlewares)

Note: This must be registered before you register the SessionsMiddleware.

SteamPress uses a PasswordVerifier protocol to check passwords. Vapor doesn't provide a default BCrypt implementation for this, so you must register this yourself:

config.prefer(BCryptDigest.self, for: PasswordVerifier.self)

Finally, if you wish to use the #markdown() tag with your blog Leaf templates, you must register this. There's also a paginator tag, to make pagination easy:

 var tags = LeafTagConfig.default()
tags.use(Markdown(), as: "markdown")
let paginatorTag = PaginatorTag(paginationLabel: "Blog Posts")
tags.use(paginatorTag, as: PaginatorTag.name)
services.register(tags)

Configuration

There are a number of configuration options you can pass to the provider to configure SteamPress:

  • blogPath: the path to add the blog to. By default the blog routes will be registered to the root of your site, but you may want to register the blog at /blog. So if you pass in "blog" the blog will be available at https://www.mysite.com/blog.
  • feedInformation: Information to vend to the RSS and Atom feeds.
  • postsPerPage: The number of posts to show per page on the main index page of the blog. Defaults to 10.
  • enableAuthorsPages: Flag used to determine whether to publicly expose the authors endpoints or not. Defaults to true.
  • enableTagsPages: Flag used to determine whether to publicy expose the tags endpoints or not. Defaults to true.

To configure these, you can pass them to the provider. E.g.:

let feedInformation = FeedInformation(
    title: "The SteamPress Blog", 
    description: "SteamPress is an open-source blogging engine written for Vapor in Swift", 
    copyright: "Released under the MIT licence", 
    imageURL: "https://user-images.githubusercontent.com/9938337/29742058-ed41dcc0-8a6f-11e7-9cfc-680501cdfb97.png")
try services.register(SteamPressFluentPostgresProvider(blogPath: "blog", feedInformation: feedInformation, postsPerPage: 5))

Additionally, you should set the WEBSITE_URL environment variable to the root address of your website, e.g. https://www.steampress.io. This is used to set various parameters throughout SteamPress.

Logging In

When you first launch SteamPress, if you've enabled the BlogAdminUser migration, an admin user is created in the database. The username is admin and the password will be printined out to your app's logs. It is recommended that you reset your password when you first login as soon as your site is up and running.

Comments

SteamPress currently supports using Disqus for the comments engine. To use Disqus, start the app with the environment variable BLOG_DISQUS_NAME set to the name of your disqus sute. (You can get the name of your Disqus site from your Disqus admin panel)

This will pass it through to the Leaf templates for the Blog index (blog.leaf), blog posts (blogpost.leaf), author page (profile.leaf) and tag page (tag.leaf) so you can include it if needs be. If you want to manually set up comments you can do this yourself and just include the necessary files for your provider. This is mainly to provide easy configuration for the example site.

Open Graph Twitter Card Support

SteamPress supports both Open Graph and Twitter Cards. The blog post page context will pass in the created date and last edited date (if applicable) in ISO 8601 format for Open Graph article support, under the parameters createdDateNumeric and lastEditedDateNumeric.

The Blog Post page will also be passed a number of other useful parameters for Open Graph and Twitter Cards. See the blogpost.leaf section below.

The Twitter handle of the site can be configured with a BLOG_SITE_TWITTER_HANDLE environment variable (the site's twitter handle without the @). If set, this will be injected into the public pages as described below. This is for the twitter:site tag for Twitter Cards

Google Analytics Support

SteamPress makes it easy to integrate Google Analytics into your blog. Just start the application with the BLOG_GOOGLE_ANALYTICS_IDENTIFIER environment variable set to you Google Analytics identifier. (You can get your identifier from the Google Analytics console, it will look something like UA-12345678-1)

This will pass a googleAnalyticsIdentifier parameter through to all of the public pages in the pageInformation variable, which you can include and then use the Example Site's javascript to integrate with.

Atom/RSS Support

SteamPress automatically provides endpoints for registering RSS readers, either using RSS 2.0 or Atom 1.0. These endpoints can be found at the blog's atom.xml and rss.xml paths; e.g. if you blog is at https://www.example.com/blog then the atom feed will appear at https://wwww.example.com/blog/atom.xml. These will work by default, but you will probably want to conf

Related Skills

View on GitHub
GitHub Stars381
CategoryDevelopment
Updated2d ago
Forks24

Languages

Swift

Security Score

100/100

Audited on Mar 22, 2026

No findings