Bespoke October CMS Plugin Development – Expert Engineering

Custom October CMS Plugin Development

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1240
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    982
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1104
  • image_website-_0.webp
    Website development for Red Pear
    553

Custom October CMS Plugin Development

Imagine: a ready-made plugin from the marketplace doesn't offer the flexibility you need — the form doesn't collect custom fields, filtering by related models fails, or the API integration hangs. The solution is to develop a plugin tailored to your needs. Over 5 years, we have shipped more than 50 custom solutions for October CMS, and this experience allows us to build them quickly, without surprises.

How a Custom Plugin Solves Business Tasks?

A plugin in October CMS is a full Laravel package that registers components, models, routes, and backend controllers. It can replace an entire microservice: manage reviews, integrate with 1C or CRM, output custom filters. Unlike modifications via copy‑paste in the theme, a plugin is easy to update, doesn't break the core, and is reusable across projects.

Why a Bespoke Extension Beats Modifying an Existing One?

Tweaking someone else's code means risking stability. Every time the plugin updates, your modifications get overwritten. A custom plugin is written from scratch for your architecture: we control every table, every event. A bespoke extension is 3x faster to update and 2x more reliable than modifying an existing one. Compare: modifying an existing plugin takes 2–3 days, but then another week to catch bugs. A new plugin — 5 days and done, with a warranty and documentation.

What Problems Do We Solve?

Most often, clients face missing fields in forms, suboptimal SQL queries (N+1), and the inability to flexibly configure access rights. We address these issues at the design stage: use eager loading, caching via Cache::remember, and custom validators.

Plugin Development Process

Our Development Process

  1. Analysis — we receive your specifications or define requirements together. We pin down models, relationships, components, access rights.
  2. Design — we create an ER diagram, component scheme, backend navigation.
  3. Implementation — we write migrations, models, components, controllers, and events. Code is covered with tests (Pest/PHPUnit, 95% coverage).
  4. Integration — we connect the plugin to your site, configure caching, optimize queries.
  5. Deployment and Documentation — we deliver an archive with composer.json, README, configs, plus training for your team.

What Is Included in the Extension

  • Source code under MIT license (or yours)
  • composer.json with autoloading
  • Migrations and seed data
  • Backend controllers and navigation menu
  • Frontend components (Twig/Partial)
  • Events and hooks for extensibility
  • Tests (if needed)
  • README with installation and usage instructions
  • 30 days of support after delivery

Typical Mistakes and How to Prevent Them

Common Mistakes

  • N+1 queries in components — forgetting with() and load(). We use eager loading and caching via Cache::remember.
  • Hard‑coded IDs in navigation — breaks on migration to another server. We build navigation automatically via Backend::url().
  • Missing validation — users input anything. We use the Validation trait with rules.
  • Ignoring events — not subscribing to cms.page.beforeDisplay, so customizations don't fire. We always use the event model.

Real‑world example: CRM integration in 2 days. One project required syncing orders with AmoCRM. The problem was that standard plugins didn't support custom deal fields. We developed a plugin with a component that sent data via REST API when an order was created. The whole job took 2 days, tests covered 95% of the code.

Comparison: Custom Plugin vs. Modifying Existing One

Criteria Custom Plugin Modifying Existing Plugin
Compatibility with updates Full — code doesn't overlap Each update requires reapplying patches
Development time 3–14 days turnkey 2–3 days for a patch, but risk of bugs
Flexibility Any logic, relationships, events Limited by plugin's structure
Documentation README, code comments, training Often absent
Warranty 30 days for fixes Depends on the author

Code Example

Below is a minimal plugin skeleton. A complete set of files is shown using a review model as an example.

Plugin.php — Registration of components and navigation

// Plugin.php namespace MyCompany\MySite; use Backend; use System\Classes\PluginBase; class Plugin extends PluginBase { public function pluginDetails(): array { return [ 'name' => 'My Site', 'description' => 'Site-specific functionality', 'author' => 'My Company', 'icon' => 'icon-leaf', ]; } public function registerComponents(): array { return [ \MyCompany\MySite\Components\ReviewList::class => 'reviewList', \MyCompany\MySite\Components\ReviewForm::class => 'reviewForm', ]; } public function registerNavigation(): array { return [ 'mysite' => [ 'label' => 'My Site', 'url' => Backend::url('mycompany/mysite/reviews'), 'icon' => 'icon-star', 'permissions' => ['mycompany.mysite.*'], 'order' => 500, 'sideMenu' => [ 'reviews' => [ 'label' => 'Reviews', 'icon' => 'icon-comments', 'url' => Backend::url('mycompany/mysite/reviews'), 'permissions' => ['mycompany.mysite.reviews'], ], ], ], ]; } public function registerSettings(): array { return [ 'settings' => [ 'label' => 'My Site Settings', 'description' => 'Configure My Site plugin', 'icon' => 'icon-cog', 'class' => \MyCompany\MySite\Models\Settings::class, 'order' => 500, ], ]; } public function boot(): void { \Event::listen('cms.page.beforeDisplay', function ($controller, $url, $page) { // Logic before page rendering }); } } 

Eloquent Model

// models/Review.php namespace MyCompany\MySite\Models; use Model; class Review extends Model { use \October\Rain\Database\Traits\Validation; use \October\Rain\Database\Traits\SoftDelete; public $table = 'mycompany_mysite_reviews'; public $rules = [ 'author_name' => 'required|string|max:255', 'email' => 'required|email', 'rating' => 'required|integer|between:1,5', 'body' => 'required|string|min:10', ]; protected $fillable = ['author_name', 'email', 'rating', 'body', 'is_approved']; protected $casts = [ 'is_approved' => 'boolean', 'rating' => 'integer', ]; public $attachOne = [ 'avatar' => \System\Models\File::class, ]; public $belongsTo = [ 'product' => [\MyCompany\MySite\Models\Product::class], ]; public function scopeApproved($query) { return $query->where('is_approved', true); } public function scopeByProduct($query, int $productId) { return $query->where('product_id', $productId); } } 

Component

// components/ReviewList.php namespace MyCompany\MySite\Components; use Cms\Classes\ComponentBase; use MyCompany\MySite\Models\Review; class ReviewList extends ComponentBase { public function componentDetails(): array { return [ 'name' => 'Review List', 'description' => 'Displays product reviews', ]; } public function defineProperties(): array { return [ 'productId' => ['title' => 'Product ID', 'type' => 'string'], 'limit' => ['title' => 'Limit', 'type' => 'string', 'default' => '10'], ]; } public function onRun(): void { $this->page['reviews'] = Review::approved() ->byProduct((int) $this->property('productId')) ->with('avatar') ->orderBy('created_at', 'desc') ->limit((int) $this->property('limit')) ->get(); $this->page['avgRating'] = Review::approved() ->byProduct((int) $this->property('productId')) ->avg('rating'); } public function onSubmitReview(): array { $data = post(); $review = new Review($data); $review->product_id = $this->property('productId'); if (!$review->save()) { throw new \ValidationException($review); } return ['success' => true]; } } 

Migration

// updates/1_0_1_create_reviews_table.php use October\Rain\Database\Schema\Blueprint; use October\Rain\Database\Updates\Migration; class CreateReviewsTable extends Migration { public function up(): void { Schema::create('mycompany_mysite_reviews', function (Blueprint $table) { $table->increments('id'); $table->integer('product_id')->unsigned()->index(); $table->string('author_name'); $table->string('email'); $table->tinyInteger('rating'); $table->text('body'); $table->boolean('is_approved')->default(false); $table->timestamps(); $table->softDeletes(); }); } public function down(): void { Schema::dropIfExists('mycompany_mysite_reviews'); } } 

Timeline and Stages

Stage Duration Result
Requirements analysis 1–2 days Spec, ER diagram
Design 1–2 days Component scheme, navigation
Implementation 3–7 days Code, tests, documentation
Integration 1–2 days Working plugin on your site
Deployment and handover 1 day composer.json, README, configs

What's Included in the Work

  • Detailed requirements document and ER diagram
  • Fully functional extension with source code (MIT license)
  • composer.json and autoloading configuration
  • Database migrations and seed data
  • Backend controllers and navigation menu
  • Frontend components (Twig/Partial)
  • Events and hooks for extensibility
  • Comprehensive tests (Pest/PHPUnit)
  • README with installation and usage instructions
  • 30 days of support and bug fixes after delivery
  • Optional: team training and maintenance contract

How to Order Development?

Describe your task — we'll prepare an estimate within 1 day. Contact us, and we'll help you determine which approach best fits your project. Prices start at $500 for a simple extension, and typical projects range from $500 to $2,000.

More details about plugin development can be found in the official October CMS documentation.

5+ years of experience and 50+ delivered plugins are not just numbers. Every project starts with an architectural review: we avoid common mistakes (missing database indexes, unoptimized queries, code duplication). All plugins undergo internal code review. We provide a 30‑day warranty on code — if something goes wrong, we fix it free of charge.