Skip to content

WebgateSystems/blog-am-template

Repository files navigation

BlogAm - Multilingual Blog Platform

BlogAm is a multilingual blog platform built on Hanami 2.3.2, featuring a Liquid-based theming system and Elasticsearch search. The project is designed to be compatible with Ruby on Rails, enabling easy data export/import between applications.

🌍 Languages

  • 🇬🇧 English (en)
  • 🇵🇱 Polski (pl)
  • 🇺🇦 Українська (ua) - default
  • 🇷🇺 Русский (ru)

🚀 Quick Start

Requirements

  • Ruby 3.2+
  • PostgreSQL 14+
  • Elasticsearch 8.x
  • Node.js 18+ (for asset pipeline)

Installation

# Clone the repository
git clone https://github.com/webgate-pro/blog_am.git
cd blog_am

# Install Ruby dependencies
bundle install

# Install Node.js dependencies
npm install

# Copy and customize configuration
cp config/settings/development.yml.example config/settings/development.yml

# Create database and run migrations
rake db:setup

# Start development server
rake server

Configuration (YAML)

The project uses the config gem instead of .env environment variables:

# config/settings/development.yml
database:
  url: postgres://localhost/blog_am_development

session:
  secret: your-secret-key-here-at-least-64-characters

elasticsearch:
  host: http://localhost:9200
  index_prefix: blog_am

📁 Project Structure

blog_am/
├── app/
│   ├── actions/          # HTTP actions (controllers)
│   ├── relations/        # Table definitions (ROM)
│   ├── repos/            # Repositories (data access)
│   ├── structs/          # Data structures (entities)
│   ├── services/         # Business services
│   │   ├── theme_renderer.rb      # Liquid renderer
│   │   └── elasticsearch_service.rb
│   └── views/            # Hanami views
├── config/
│   ├── db/
│   │   ├── migrate/      # Database migrations
│   │   └── seeds/        # Seed data (modular)
│   │       ├── 000_users.rb
│   │       ├── 010_categories.rb
│   │       ├── 020_tags.rb
│   │       ├── 030_posts.rb
│   │       └── data/posts.yml   # Content in YAML
│   ├── locales/          # I18n translations
│   ├── settings/         # Per-environment configuration
│   └── routes.rb         # Routing
├── lib/tasks/            # Rake tasks
│   ├── db.rake           # Database management
│   ├── search.rake       # Elasticsearch
│   ├── server.rake       # Development server
│   └── quality.rake      # RuboCop, SimpleCov
├── themes/               # Liquid themes
│   └── default/
│       ├── layouts/
│       ├── partials/
│       ├── assets/
│       └── theme.yml
├── spec/                 # RSpec tests
│   ├── factories/        # FactoryBot
│   ├── repos/            # Repository tests
│   ├── services/         # Service tests
│   ├── requests/         # HTTP tests
│   ├── features/         # Integration tests
│   └── structs/          # Struct tests
└── docs/                 # Documentation

🛠️ Rake Tasks

Database

rake db:create          # Create database
rake db:drop            # Drop database
rake db:migrate         # Run migrations
rake db:seed            # Load seed data
rake db:setup           # create + migrate + seed
rake db:reset           # drop + setup
rake db:recreate        # reset with confirmation
rake db:status          # Migration status

Server

rake server             # Start Puma on port 2300
rake console            # Hanami console

Elasticsearch

rake search:status      # Check ES status
rake search:setup       # Create index
rake search:reindex     # Reindex all content
rake search:rebuild     # drop + setup + reindex
rake search:test[query] # Test search

Code Quality

rake rubocop            # Check code style
rake rubocop_fix        # Auto-fix issues
rake quality            # RSpec + RuboCop
rake quality:coverage   # RSpec with SimpleCov

🗄️ Database Schema

Main Tables

Table Description
users Users and administrators
posts Blog articles/posts
videos Video content
photos Photo galleries
tags Tags
taggings Polymorphic many-to-many for tags
categories Categories (hierarchical)
comments Comments (polymorphic)
pages Static pages (About, Terms, etc.)
themes Installed themes
site_settings Site settings (JSONB)
partners Blog partners/friends
media_attachments Media attachments

Key Features

  • UUID as primary keys (protection against enumeration attacks)
  • JSONB for multilingual content (title, content, etc.)
  • Full Rails compatibility (naming conventions)
  • Polymorphic associations (tags, comments, attachments)

🔍 Search (Elasticsearch)

BlogAm uses Elasticsearch for full-text search across multiple languages:

# Configuration in config/settings.yml
elasticsearch:
  host: http://localhost:9200
  index_prefix: blog_am
  log: false

# Reindex after changes
rake search:reindex

Search includes:

  • Titles, subtitles, leads, content
  • All language versions
  • Fuzzy matching (typo tolerance)
  • Result highlighting

🎨 Theme System (Liquid)

BlogAm uses Liquid as its template engine:

Theme Structure

themes/my-theme/
├── theme.yml           # Theme metadata
├── layouts/
│   └── application.liquid
├── partials/
├── index.liquid        # Homepage
├── post.liquid         # Single article
├── posts/index.liquid  # Article listing
├── videos/
├── photos/
├── search/
└── assets/
    ├── css/
    ├── js/
    └── img/

Available Filters

{{ 'navigation.home' | t }}              {# I18n translation #}
{{ post.published_at | date_format }}    {# Date formatting #}
{{ post.content | strip_html | truncate_words: 50 }}
{{ post | post_url }}                    {# Post URL #}
{{ content | reading_time }} min         {# Reading time #}

Detailed documentation: docs/THEMES.md

🌐 Multilingual Support

Content (JSONB)

# Multilingual field structure in database
{
  "en" => "Title in English",
  "ua" => "Заголовок українською",
  "ru" => "Заголовок на русском",
  "pl" => "Tytuł po polsku"
}

UI (I18n)

# config/locales/ua.yml
ua:
  navigation:
    home: "Головна"
    about: "Про мене"
{{ 'navigation.home' | t }}

Language Switching

GET /locale/en  # Switch to English
GET /locale/ua  # Switch to Ukrainian

🧪 Testing

# Run all tests
bundle exec rspec

# Run specific file
bundle exec rspec spec/repos/post_repo_spec.rb

# With code coverage (SimpleCov)
bundle exec rspec
open coverage/index.html

# Fast tests only (skip features)
bundle exec rspec --tag ~type:feature

Test Structure

  • spec/repos/ - Repository tests (CRUD, queries)
  • spec/services/ - Service tests (ThemeRenderer, Elasticsearch)
  • spec/requests/ - HTTP tests (actions, routing)
  • spec/features/ - Integration tests (browser)
  • spec/structs/ - Data structure tests

Code Coverage

Current: ~82% Line Coverage, ~33% Branch Coverage

🔒 Security

  • UUID instead of incremental IDs (protection against enumeration)
  • BCrypt for passwords
  • Liquid - safe template language (no Ruby code execution)
  • CSRF protection in forms
  • Sanitization of user content
  • Content Security Policy headers

📦 Rails Compatibility

The database is designed according to Rails conventions:

# In a Rails application
class Post < ApplicationRecord
  belongs_to :author, class_name: "User"
  belongs_to :category
  has_many :taggings, as: :taggable
  has_many :tags, through: :taggings
  has_many :comments, as: :commentable
  
  # Multilingual with mobility gem
  extend Mobility
  translates :title, :subtitle, :lead, :content, backend: :jsonb
end

📋 Project Status

  • Stage 1: Data structure and migrations (UUID, Rails-compatible)
  • Stage 2: Multilingual seeds EN/UA/RU/PL
  • Stage 3: HTML/CSS/JS layout adaptation
  • Stage 4: Liquid theme system + documentation
  • Stage 5: RSpec tests (82% coverage)
  • Elasticsearch search engine
  • RuboCop + SimpleCov
  • Stage 6: Administrative panel

👤 Author and License

Author: Jerzy Sładkowski
Company: Webgate Systems LTD
Blog: Ayder Muzhdabaiev

License: GNU Affero General Public License v3.0


This project is part of a larger media platform.

About

Blog template, based on Hanami framework to test Liquid templates skins

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors