Building Relaticle: A Free & Open Source CRM with Laravel 12 & Filament 3

After months of coding late into the night, I'm excited to share Relaticle - a modern, completely free and open source CRM built with Laravel 12 and Filament 3. Why I Built This Most CRMs are either too expensive, too bloated, or too restrictive. I wanted something that was: Powerful enough for real businesses Flexible enough to customize without a CS degree Open enough that you own your data Simple enough that you don't need a consultant to use it So I built Relaticle as the CRM I wish existed when I started my first business. The Tech Stack Relaticle is built on modern technologies that prioritize developer experience and performance: Laravel 12 - The latest version with all its goodies Filament 3 - For beautiful admin panels with minimal effort Livewire 3 - For dynamic components without writing JS Alpine.js - For lightweight interactivity Tailwind CSS - For responsive, utility-first styling PostgreSQL - For robust data storage (though SQLite works too) Key Features Here's what makes Relaticle special from a technical perspective: 1. Multi-tenancy with Team Workspaces Using Laravel Jetstream's team features, combined with Filament's tenant system: // app/Providers/Filament/AppPanelProvider.php $panel ->tenant(Team::class) ->tenantRegistration(CreateTeam::class) ->tenantProfile(EditTeam::class); 2. Custom Fields System A flexible custom fields architecture that allows for schema-less data modeling without sacrificing query performance: // Defining a custom field for tasks enum Task: string { use CustomFieldTrait; case STATUS = 'status'; case PRIORITY = 'priority'; public function getFieldType(): CustomFieldType { return match ($this) { self::STATUS, self::PRIORITY => CustomFieldType::SELECT, // other cases... }; } } 3. Kanban Boards for Visual Management Built a drag-and-drop Kanban system for both tasks and opportunities: final class TasksBoard extends KanbanBoardPage { public function mount(): void { $this->titleField('title') ->columnField('status') ->descriptionField('description') ->orderField('order_column') ->columns($this->statuses()->pluck('name', 'id')->toArray()) ->columnColors() ->cardLabel('Task'); } // Other methods... } 4. Smart Avatars and UI Components Created a service that dynamically generates avatars with appropriate contrast: // A simple system that generates personalized SVG avatars public function generateAuto(string $name, int $size = 64): string { // Analyze name characteristics to choose colors $nameAnalysis = $this->analyzeNameCharacteristics($name); // Generate a deterministic hue based on the name $hue = $this->getHueFromName($name); // Adjust saturation and lightness based on name $saturation = 65 + $nameAnalysis['adjustment']; $lightness = 85 - ($nameAnalysis['adjustment'] / 2); // Create the SVG with the person's initials // ... } Architecture Decisions When building Relaticle, I made a few important architecture decisions: Heavy use of PHP 8.3 features like readonly properties, enums, and the #[\Override] attribute Strict architecture enforcement using Pest's architecture tests to enforce coding standards: arch('strict types') ->expect('App') ->toUseStrictTypes(); arch('avoid open for extension') ->expect('App') ->classes() ->toBeFinal(); arch('avoid mutation') ->expect('App') ->classes() ->toBeReadonly(); Application panels segregation - Admin vs App panels to clearly separate concerns Observer pattern for model events to keep controllers lean: #[ObservedBy(CompanyObserver::class)] final class Company extends Model implements HasCustomFields, HasMedia { // ... } Development Journey Building Relaticle wasn't a straight path. Some lessons learned: Laravel 12's new features made testing much easier with the improved Pest integration Filament 3 is amazing but requires some learning, especially when extending core components Database performance needed optimization for the custom fields system Balancing flexibility vs simplicity is an ongoing challenge Getting Started Want to try it out? Here's how to get started: # Clone the repository git clone https://github.com/Relaticle/relaticle.git # Install dependencies cd relaticle composer install npm install # Set up your environment cp .env.example .env php artisan key:generate # Run migrations php artisan migrate # Compile assets npm run dev # Start the server php artisan serve Future Plans This is just the beginning. Here's what's coming: Email integration for tracking correspondence API for custom integrations More visualization reports Mobile app (eventually

Apr 26, 2025 - 10:25
 0
Building Relaticle: A Free & Open Source CRM with Laravel 12 & Filament 3

After months of coding late into the night, I'm excited to share Relaticle - a modern, completely free and open source CRM built with Laravel 12 and Filament 3.

Why I Built This

Most CRMs are either too expensive, too bloated, or too restrictive. I wanted something that was:

  • Powerful enough for real businesses
  • Flexible enough to customize without a CS degree
  • Open enough that you own your data
  • Simple enough that you don't need a consultant to use it

So I built Relaticle as the CRM I wish existed when I started my first business.

The Tech Stack

Relaticle is built on modern technologies that prioritize developer experience and performance:

  • Laravel 12 - The latest version with all its goodies
  • Filament 3 - For beautiful admin panels with minimal effort
  • Livewire 3 - For dynamic components without writing JS
  • Alpine.js - For lightweight interactivity
  • Tailwind CSS - For responsive, utility-first styling
  • PostgreSQL - For robust data storage (though SQLite works too)

Key Features

Here's what makes Relaticle special from a technical perspective:

1. Multi-tenancy with Team Workspaces

Using Laravel Jetstream's team features, combined with Filament's tenant system:

// app/Providers/Filament/AppPanelProvider.php

$panel
    ->tenant(Team::class)
    ->tenantRegistration(CreateTeam::class)
    ->tenantProfile(EditTeam::class);

2. Custom Fields System

A flexible custom fields architecture that allows for schema-less data modeling without sacrificing query performance:

// Defining a custom field for tasks
enum Task: string
{
    use CustomFieldTrait;

    case STATUS = 'status';
    case PRIORITY = 'priority';

    public function getFieldType(): CustomFieldType
    {
        return match ($this) {
            self::STATUS, self::PRIORITY => CustomFieldType::SELECT,
            // other cases...
        };
    }
}

3. Kanban Boards for Visual Management

Built a drag-and-drop Kanban system for both tasks and opportunities:

final class TasksBoard extends KanbanBoardPage
{
    public function mount(): void
    {
        $this->titleField('title')
            ->columnField('status')
            ->descriptionField('description')
            ->orderField('order_column')
            ->columns($this->statuses()->pluck('name', 'id')->toArray())
            ->columnColors()
            ->cardLabel('Task');
    }

    // Other methods...
}

4. Smart Avatars and UI Components

Created a service that dynamically generates avatars with appropriate contrast:

// A simple system that generates personalized SVG avatars
public function generateAuto(string $name, int $size = 64): string
{
    // Analyze name characteristics to choose colors
    $nameAnalysis = $this->analyzeNameCharacteristics($name);

    // Generate a deterministic hue based on the name
    $hue = $this->getHueFromName($name);

    // Adjust saturation and lightness based on name
    $saturation = 65 + $nameAnalysis['adjustment'];
    $lightness = 85 - ($nameAnalysis['adjustment'] / 2);

    // Create the SVG with the person's initials
    // ...
}

Architecture Decisions

When building Relaticle, I made a few important architecture decisions:

  1. Heavy use of PHP 8.3 features like readonly properties, enums, and the #[\Override] attribute

  2. Strict architecture enforcement using Pest's architecture tests to enforce coding standards:

arch('strict types')
    ->expect('App')
    ->toUseStrictTypes();

arch('avoid open for extension')
    ->expect('App')
    ->classes()
    ->toBeFinal();

arch('avoid mutation')
    ->expect('App')
    ->classes()
    ->toBeReadonly();
  1. Application panels segregation - Admin vs App panels to clearly separate concerns

  2. Observer pattern for model events to keep controllers lean:

#[ObservedBy(CompanyObserver::class)]
final class Company extends Model implements HasCustomFields, HasMedia
{
    // ...
}

Development Journey

Building Relaticle wasn't a straight path. Some lessons learned:

  • Laravel 12's new features made testing much easier with the improved Pest integration
  • Filament 3 is amazing but requires some learning, especially when extending core components
  • Database performance needed optimization for the custom fields system
  • Balancing flexibility vs simplicity is an ongoing challenge

Getting Started

Want to try it out? Here's how to get started:

# Clone the repository
git clone https://github.com/Relaticle/relaticle.git

# Install dependencies
cd relaticle
composer install
npm install

# Set up your environment
cp .env.example .env
php artisan key:generate

# Run migrations
php artisan migrate

# Compile assets
npm run dev

# Start the server
php artisan serve

Future Plans

This is just the beginning. Here's what's coming:

  • Email integration for tracking correspondence
  • API for custom integrations
  • More visualization reports
  • Mobile app (eventually)

Join Me!

I'd love to have more developers join this project. It's completely free and open source - no premium tiers, no locked features.

If you're interested in contributing, check out the repository on GitHub: Relaticle/relaticle

Or, if you just want to try it out, star the repo and follow along as we build something awesome together.

Let me know what you think in the comments!