<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Serhii</title>
    <description>The latest articles on Forem by Serhii (@serhii_fedorenko).</description>
    <link>https://forem.com/serhii_fedorenko</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1048851%2Fa995e468-0ad1-45e7-9479-c3e9ffc971bb.jpeg</url>
      <title>Forem: Serhii</title>
      <link>https://forem.com/serhii_fedorenko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/serhii_fedorenko"/>
    <language>en</language>
    <item>
      <title>Building multilingual runtime collections in a Filament plugin</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Wed, 15 Apr 2026 20:46:01 +0000</pubDate>
      <link>https://forem.com/serhii_fedorenko/building-multilingual-runtime-collections-in-a-filament-plugin-27cm</link>
      <guid>https://forem.com/serhii_fedorenko/building-multilingual-runtime-collections-in-a-filament-plugin-27cm</guid>
      <description>&lt;h1&gt;
  
  
  Building multilingual runtime collections in a Filament plugin
&lt;/h1&gt;

&lt;p&gt;I just released &lt;code&gt;v1.2.0&lt;/code&gt; of &lt;strong&gt;Filament Studio&lt;/strong&gt;, a Filament v5 plugin I am building for runtime collections, custom fields, dashboards, filters, and APIs.&lt;/p&gt;

&lt;p&gt;The short version: this release adds multilingual support.&lt;/p&gt;

&lt;p&gt;The longer version: adding multilingual support to a runtime data model is not the same as adding a &lt;code&gt;translations&lt;/code&gt; JSON column and moving on.&lt;/p&gt;

&lt;p&gt;Filament Studio is built for admin panels where the data model changes after the app is already running. A user can create a collection, add fields, manage records, build dashboards, and expose API endpoints without writing a new migration and Filament resource for each new content type.&lt;/p&gt;

&lt;p&gt;That flexibility creates a specific problem for translations.&lt;/p&gt;

&lt;p&gt;If the fields are defined at runtime, translation behavior also has to be defined at runtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;In real admin systems, multilingual content is rarely all-or-nothing.&lt;/p&gt;

&lt;p&gt;A collection might support English and French.&lt;/p&gt;

&lt;p&gt;Inside that collection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;title&lt;/code&gt; should be translated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; should be translated&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;price&lt;/code&gt; should stay shared&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;published_at&lt;/code&gt; should stay shared&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is_featured&lt;/code&gt; should stay shared&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That means translation behavior belongs at the field level, not only at the record or collection level.&lt;/p&gt;

&lt;p&gt;I also wanted the feature to work across the whole plugin:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;generated Filament forms&lt;/li&gt;
&lt;li&gt;EAV storage&lt;/li&gt;
&lt;li&gt;query builder reads and writes&lt;/li&gt;
&lt;li&gt;REST API responses&lt;/li&gt;
&lt;li&gt;OpenAPI documentation&lt;/li&gt;
&lt;li&gt;fallback behavior&lt;/li&gt;
&lt;li&gt;version snapshots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise it would feel like a partial feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Global and collection config
&lt;/h2&gt;

&lt;p&gt;Multilingual support is opt-in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/filament-studio.php&lt;/span&gt;
&lt;span class="s1"&gt;'locales'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'enabled'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'available'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'de'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'default'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also enable it through the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STUDIO_LOCALES_ENABLED=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each collection can then define its own supported locales and default locale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;'supported_locales'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'default_locale'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'en'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a collection does not define supported locales, it uses the global list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Per-field translation
&lt;/h2&gt;

&lt;p&gt;Each field now has a translatable flag.&lt;/p&gt;

&lt;p&gt;That lets a collection mix localized and shared data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;title        translatable
description  translatable
price        shared
published_at shared
is_featured  shared
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the part of the design I care about most. In multilingual admin work, not every value is content. Some values are facts, flags, prices, dates, or relationships. Treating all of them as translatable creates noise and sometimes bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage model
&lt;/h2&gt;

&lt;p&gt;Filament Studio uses an EAV model because fields are created at runtime.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;v1.2.0&lt;/code&gt;, the &lt;code&gt;studio_values&lt;/code&gt; table now includes a &lt;code&gt;locale&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;For translatable fields, values are stored per locale.&lt;/p&gt;

&lt;p&gt;For shared fields, one value is used regardless of active locale.&lt;/p&gt;

&lt;p&gt;The uniqueness boundary is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;record_id + field_id + locale
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That allows a record to have different localized values for the same runtime field without creating new database columns for every translated field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Locale resolution
&lt;/h2&gt;

&lt;p&gt;I added a dedicated &lt;code&gt;LocaleResolver&lt;/code&gt; service so the rules live in one place.&lt;/p&gt;

&lt;p&gt;The active locale is resolved in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;?locale=&lt;/code&gt; query parameter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Locale&lt;/code&gt; header&lt;/li&gt;
&lt;li&gt;session&lt;/li&gt;
&lt;li&gt;collection default&lt;/li&gt;
&lt;li&gt;global default&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That gives API consumers a direct way to request a locale, while the admin panel can remember the selected locale in the session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Query builder API
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;EavQueryBuilder&lt;/code&gt; now supports a &lt;code&gt;locale()&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EavQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRecordData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create and update operations can also target a locale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EavQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Mon Titre'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;EavQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Titre mis a jour'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is also &lt;code&gt;getAllLocaleData()&lt;/code&gt; for retrieving every translation at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$allData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EavQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getAllLocaleData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'en'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'My Title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'fr'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Mon Titre'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'price'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translatable fields return locale maps. Shared fields stay plain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fallback metadata
&lt;/h2&gt;

&lt;p&gt;I did not want fallback behavior to be silent.&lt;/p&gt;

&lt;p&gt;If an API client asks for French and a field falls back to English, the client should be able to detect that.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;getRecordDataWithMeta()&lt;/code&gt; returns fallback information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EavQueryBuilder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'fr'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRecordDataWithMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'data'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Mon Titre'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'slug'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'my-slug'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s1"&gt;'fallbacks'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'slug'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells the caller that &lt;code&gt;slug&lt;/code&gt; came from the default locale.&lt;/p&gt;

&lt;h2&gt;
  
  
  REST API support
&lt;/h2&gt;

&lt;p&gt;API endpoints now accept locale selection through query params:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Api-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="s2"&gt;"https://your-app.com/api/studio/posts?locale=fr"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or through headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Api-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Locale: fr"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="s2"&gt;"https://your-app.com/api/studio/posts"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Responses include metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"uuid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"550e8400-e29b-41d4-a716-446655440000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mon Titre"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-slug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_meta"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"locale"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fallbacks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For single-record reads, &lt;code&gt;all_locales=true&lt;/code&gt; returns every locale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Api-Key: your-key"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="s2"&gt;"https://your-app.com/api/studio/posts/550e8400?all_locales=true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  OpenAPI docs
&lt;/h2&gt;

&lt;p&gt;When multilingual support is enabled, the generated OpenAPI docs include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;locale&lt;/code&gt; query parameter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;X-Locale&lt;/code&gt; header parameter&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;all_locales&lt;/code&gt; query parameter&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_meta.locale&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_meta.fallbacks&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This felt worth doing because API features are easy to misunderstand when the docs do not show the request and response shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  Admin UI and versioning
&lt;/h2&gt;

&lt;p&gt;In the Filament admin, multilingual collections now get a locale switcher on record pages.&lt;/p&gt;

&lt;p&gt;Editors can switch locale and edit only the fields that should change for that locale.&lt;/p&gt;

&lt;p&gt;Version snapshots also store all locale values for translatable fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mon Titre"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-slug"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way restoring a version does not only restore whichever locale happened to be active at the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I am sharing this
&lt;/h2&gt;

&lt;p&gt;This was one of those updates that made the package feel more practical.&lt;/p&gt;

&lt;p&gt;The first version of a dynamic admin builder can look good with just runtime fields and generated forms.&lt;/p&gt;

&lt;p&gt;But real projects keep asking for the less glamorous pieces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;permissions&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;versioning&lt;/li&gt;
&lt;li&gt;tenancy&lt;/li&gt;
&lt;li&gt;filtering&lt;/li&gt;
&lt;li&gt;multilingual content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the direction I am trying to push Filament Studio.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;code&gt;https://github.com/flexpik/filament-studio&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Packagist: &lt;code&gt;https://packagist.org/packages/flexpik/filament-studio&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you have built multilingual admin panels in Laravel, I would like feedback on the model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;should translation behavior live per field?&lt;/li&gt;
&lt;li&gt;is fallback metadata useful in practice?&lt;/li&gt;
&lt;li&gt;would &lt;code&gt;all_locales=true&lt;/code&gt; work for your API use cases?&lt;/li&gt;
&lt;li&gt;what edge cases am I missing?&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravel</category>
      <category>filament</category>
      <category>opensource</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>I built a Filament plugin for runtime collections, custom fields, dashboards, and APIs</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Mon, 06 Apr 2026 10:54:30 +0000</pubDate>
      <link>https://forem.com/serhii_fedorenko/i-built-a-filament-plugin-for-runtime-collections-custom-fields-dashboards-and-apis-3g5f</link>
      <guid>https://forem.com/serhii_fedorenko/i-built-a-filament-plugin-for-runtime-collections-custom-fields-dashboards-and-apis-3g5f</guid>
      <description>&lt;h1&gt;
  
  
  I built a Filament plugin for runtime collections, custom fields, dashboards, and APIs
&lt;/h1&gt;

&lt;p&gt;I built &lt;strong&gt;Filament Studio&lt;/strong&gt; because I got tired of the same cycle in Laravel projects.&lt;/p&gt;

&lt;p&gt;The admin panel starts simple.&lt;/p&gt;

&lt;p&gt;Then requirements change.&lt;/p&gt;

&lt;p&gt;A client wants a new content type.&lt;br&gt;&lt;br&gt;
Then custom fields.&lt;br&gt;&lt;br&gt;
Then better filtering.&lt;br&gt;&lt;br&gt;
Then dashboards.&lt;br&gt;&lt;br&gt;
Then API access.&lt;br&gt;&lt;br&gt;
Then tenant-specific data.&lt;br&gt;&lt;br&gt;
Then version history.&lt;br&gt;&lt;br&gt;
Then another special case nobody planned for.&lt;/p&gt;

&lt;p&gt;At that point, what looked like a straightforward Filament setup turns into more migrations, more models, more resources, more filters, and more maintenance.&lt;/p&gt;

&lt;p&gt;That gets old fast.&lt;/p&gt;

&lt;p&gt;So I built a plugin for &lt;strong&gt;Filament v5&lt;/strong&gt; that lets you create and manage data collections at runtime, define fields through the UI, manage records, build dashboards, and expose API endpoints without creating a new table and Filament resource every time the model changes.&lt;/p&gt;

&lt;p&gt;The plugin is called &lt;strong&gt;Filament Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;Filament is excellent when the data model is already clear and relatively stable.&lt;/p&gt;

&lt;p&gt;But some projects are not like that at all.&lt;/p&gt;

&lt;p&gt;You might be building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a flexible internal CMS&lt;/li&gt;
&lt;li&gt;a client-specific admin panel&lt;/li&gt;
&lt;li&gt;an operations dashboard&lt;/li&gt;
&lt;li&gt;a multi-tenant back office&lt;/li&gt;
&lt;li&gt;a content platform where structure changes over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In those projects, the data model is usually the part that keeps moving.&lt;/p&gt;

&lt;p&gt;And every change has a cost.&lt;/p&gt;

&lt;p&gt;A new content type is not just "add a few fields."&lt;br&gt;&lt;br&gt;
It usually means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;another migration&lt;/li&gt;
&lt;li&gt;another model&lt;/li&gt;
&lt;li&gt;another Filament resource&lt;/li&gt;
&lt;li&gt;another set of forms and table columns&lt;/li&gt;
&lt;li&gt;another round of filters and policies&lt;/li&gt;
&lt;li&gt;another layer of maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted a way to stay inside Filament while making the admin side much more flexible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Filament Studio does
&lt;/h2&gt;

&lt;p&gt;Filament Studio turns Filament into a runtime-configurable data platform.&lt;/p&gt;

&lt;p&gt;With it, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create collections from the admin UI&lt;/li&gt;
&lt;li&gt;define custom fields without writing migrations for each collection&lt;/li&gt;
&lt;li&gt;manage records with generated forms, tables, and filters&lt;/li&gt;
&lt;li&gt;build dashboards with metrics and chart panels&lt;/li&gt;
&lt;li&gt;expose REST API endpoints with API key authentication&lt;/li&gt;
&lt;li&gt;enable versioning and soft deletes&lt;/li&gt;
&lt;li&gt;scope everything by tenant&lt;/li&gt;
&lt;li&gt;control access with policies and permissions&lt;/li&gt;
&lt;li&gt;extend the system with custom field types, panel types, hooks, and schema modifiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was not trying to build a toy form builder.&lt;/p&gt;

&lt;p&gt;I wanted something that still feels useful when the project becomes real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I chose an EAV-based approach
&lt;/h2&gt;

&lt;p&gt;The core of Filament Studio is an &lt;strong&gt;EAV storage model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of creating a new database table for every collection, the plugin stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;collection definitions&lt;/li&gt;
&lt;li&gt;field definitions&lt;/li&gt;
&lt;li&gt;records&lt;/li&gt;
&lt;li&gt;typed values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That gives the plugin room to support runtime schema changes without forcing a migration every time someone adds or edits a field.&lt;/p&gt;

&lt;p&gt;I know EAV has a reputation.&lt;/p&gt;

&lt;p&gt;Sometimes that reputation is deserved.&lt;/p&gt;

&lt;p&gt;But in this case, the tradeoff made sense because I was not trying to model one stable domain perfectly.&lt;br&gt;&lt;br&gt;
I was trying to give teams a flexible way to build evolving admin-managed data systems inside Filament.&lt;/p&gt;

&lt;p&gt;The important part was making it practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typed storage columns&lt;/li&gt;
&lt;li&gt;generated Filament components&lt;/li&gt;
&lt;li&gt;useful filtering&lt;/li&gt;
&lt;li&gt;dashboards&lt;/li&gt;
&lt;li&gt;API support&lt;/li&gt;
&lt;li&gt;extensibility hooks&lt;/li&gt;
&lt;li&gt;production-oriented features like tenancy and authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's built in
&lt;/h2&gt;

&lt;p&gt;Filament Studio already includes a lot of what I usually end up rebuilding by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dynamic collections
&lt;/h3&gt;

&lt;p&gt;You can create collections in the admin panel and define fields visually.&lt;/p&gt;

&lt;p&gt;The plugin currently includes &lt;strong&gt;33 built-in field types&lt;/strong&gt; across categories like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;text&lt;/li&gt;
&lt;li&gt;numeric&lt;/li&gt;
&lt;li&gt;boolean&lt;/li&gt;
&lt;li&gt;selection&lt;/li&gt;
&lt;li&gt;date and time&lt;/li&gt;
&lt;li&gt;file&lt;/li&gt;
&lt;li&gt;relational&lt;/li&gt;
&lt;li&gt;structured&lt;/li&gt;
&lt;li&gt;presentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it useful for more than simple text-entry forms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dashboard builder
&lt;/h3&gt;

&lt;p&gt;There is also a dashboard builder with &lt;strong&gt;9 panel types&lt;/strong&gt;, including metrics, lists, time-series charts, bar charts, pie charts, and more.&lt;/p&gt;

&lt;p&gt;That matters because once teams have data, the next thing they ask for is visibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advanced filtering
&lt;/h3&gt;

&lt;p&gt;I also wanted filtering to be good enough for real admin use, not just "search one text column."&lt;/p&gt;

&lt;p&gt;So the plugin includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a visual filter builder&lt;/li&gt;
&lt;li&gt;nested AND/OR logic&lt;/li&gt;
&lt;li&gt;dynamic variables&lt;/li&gt;
&lt;li&gt;saved presets&lt;/li&gt;
&lt;li&gt;type-aware operators&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  REST API
&lt;/h3&gt;

&lt;p&gt;Filament Studio can generate REST API endpoints with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API key authentication&lt;/li&gt;
&lt;li&gt;per-collection permissions&lt;/li&gt;
&lt;li&gt;rate limiting&lt;/li&gt;
&lt;li&gt;OpenAPI documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Production-oriented features
&lt;/h3&gt;

&lt;p&gt;A lot of packages stop at the demo layer.&lt;/p&gt;

&lt;p&gt;I wanted this one to go further, so it also supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multi-tenancy&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;record versioning&lt;/li&gt;
&lt;li&gt;soft deletes&lt;/li&gt;
&lt;li&gt;lifecycle hooks&lt;/li&gt;
&lt;li&gt;schema modification callbacks&lt;/li&gt;
&lt;li&gt;custom field and panel extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who I think this is useful for
&lt;/h2&gt;

&lt;p&gt;I think Filament Studio is most useful for three groups.&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel and Filament developers
&lt;/h3&gt;

&lt;p&gt;If you like building with Filament but do not want every new admin requirement to trigger another round of scaffolding, this gives you a more flexible starting point.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agencies
&lt;/h3&gt;

&lt;p&gt;If you build custom admin panels for clients, this can reduce the amount of repetitive work involved in creating content structures, dashboards, and internal workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Startup teams
&lt;/h3&gt;

&lt;p&gt;If your internal systems and content models are still evolving, runtime collections can be easier to live with than constantly reshaping your app around new admin requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I wanted the plugin to feel like
&lt;/h2&gt;

&lt;p&gt;I did not want this to feel like a disconnected "builder product" bolted onto Laravel.&lt;/p&gt;

&lt;p&gt;I wanted it to still feel like it belongs in a Filament application.&lt;/p&gt;

&lt;p&gt;That meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;native-looking forms and tables&lt;/li&gt;
&lt;li&gt;sensible extension points&lt;/li&gt;
&lt;li&gt;support for real authorization models&lt;/li&gt;
&lt;li&gt;room for custom field types and custom panels&lt;/li&gt;
&lt;li&gt;documentation good enough that people can actually adopt it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also spent time on screenshots and docs because I think open-source packages need to earn trust quickly.&lt;/p&gt;

&lt;p&gt;If someone lands on the repository, they should immediately understand what the plugin does, what it looks like, and whether it is serious.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm sharing it now
&lt;/h2&gt;

&lt;p&gt;I am sharing Filament Studio because I think it fills a real gap in a certain kind of Laravel project.&lt;/p&gt;

&lt;p&gt;Not every app needs runtime-defined collections.&lt;/p&gt;

&lt;p&gt;But when a project does need flexibility, the usual alternatives are messy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep hardcoding every change&lt;/li&gt;
&lt;li&gt;overbuild a custom internal CMS&lt;/li&gt;
&lt;li&gt;stitch together several tools&lt;/li&gt;
&lt;li&gt;give up on having a clean workflow inside Filament&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted a better option.&lt;/p&gt;

&lt;h2&gt;
  
  
  If this sounds useful, I'd love feedback
&lt;/h2&gt;

&lt;p&gt;If you work with Laravel and Filament and this solves a problem you've run into, take a look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;code&gt;https://github.com/flexpik/filament-studio&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Packagist: &lt;code&gt;https://packagist.org/packages/flexpik/filament-studio&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it looks useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;star the repo&lt;/li&gt;
&lt;li&gt;try it in a project&lt;/li&gt;
&lt;li&gt;tell me what you'd build with it&lt;/li&gt;
&lt;li&gt;tell me what feels missing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most useful feedback at this stage is not just "looks nice."&lt;/p&gt;

&lt;p&gt;It is "this would help me build X" or "I would need Y before using it."&lt;/p&gt;

&lt;p&gt;That kind of feedback is what makes open-source tools better.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filament</category>
      <category>opensource</category>
    </item>
    <item>
      <title>10 Reasons Why PrestaShop Is the Best E-commerce Platform for Your Business</title>
      <dc:creator>Serhii</dc:creator>
      <pubDate>Tue, 21 Mar 2023 10:01:02 +0000</pubDate>
      <link>https://forem.com/serhii_fedorenko/10-reasons-why-prestashop-is-the-best-e-commerce-platform-for-your-business-51j5</link>
      <guid>https://forem.com/serhii_fedorenko/10-reasons-why-prestashop-is-the-best-e-commerce-platform-for-your-business-51j5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QbgjcFRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbyut6ptuxhxydtg9pqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QbgjcFRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbyut6ptuxhxydtg9pqa.png" alt="PrestaShop" width="880" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Are you looking to start or expand your e-commerce business? With so many platforms available, it can be challenging to determine which one is the best fit for your specific needs. In this article, we will delve into 10 reasons why PrestaShop is the best e-commerce platform for your business, and why it should be at the top of your list.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. User-friendly Interface
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Intuitive dashboard&lt;/strong&gt;&lt;br&gt;
PrestaShop boasts a user-friendly interface with an intuitive dashboard that even beginners can easily navigate. The admin panel is designed with simplicity in mind, making it easy to manage your online store with minimal effort.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Easy customization&lt;/strong&gt;&lt;br&gt;
With PrestaShop, customizing your online store is a breeze. You can easily modify the look and feel of your site, add new features, and make changes to your store's layout without any coding knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Wide Range of Features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Built-in SEO tools&lt;/strong&gt;&lt;br&gt;
PrestaShop comes with a set of built-in SEO tools that help you optimize your online store for search engines. These tools include customizable meta titles, descriptions, and URLs, making it easy to improve your store's search engine rankings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Powerful analytics&lt;/strong&gt;&lt;br&gt;
The platform offers robust analytics features that allow you to track your store's performance and make data-driven decisions. You can monitor sales, visitor behavior, and other key metrics with ease, helping you optimize your business strategy and grow your revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Extensive Theme Selection
&lt;/h2&gt;

&lt;p&gt;PrestaShop offers a vast selection of professionally designed themes, ensuring that your online store looks attractive and engaging. You can choose from a wide variety of free and premium themes, making it easy to find one that matches your brand identity and appeals to your target audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scalability
&lt;/h2&gt;

&lt;p&gt;PrestaShop is a highly scalable e-commerce platform, making it an ideal choice for businesses of all sizes. As your business grows, you can easily add new features, products, and categories without experiencing any significant slowdowns or performance issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Multilingual and Multi-currency Support
&lt;/h2&gt;

&lt;p&gt;Operating an international e-commerce business? PrestaShop has you covered with its multilingual and multi-currency support. The platform allows you to offer your products in multiple languages and accept payments in various currencies, making it easier for you to cater to a global audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Large Community and Support Network
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Active forums&lt;/strong&gt;&lt;br&gt;
PrestaShop has a large and active community of users, developers, and experts who are always ready to help. The platform's forums are filled with knowledgeable individuals who can offer advice, tips,and troubleshooting assistance whenever you need it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation and tutorials&lt;/strong&gt;&lt;br&gt;
PrestaShop also provides extensive documentation and tutorials, ensuring that you have all the resources you need to manage your online store effectively. These resources cover a wide range of topics, from basic setup to advanced customization and optimization techniques.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Cost-effective Solution
&lt;/h2&gt;

&lt;p&gt;PrestaShop is an open-source platform, which means it's free to download and use. This makes it an attractive option for small businesses and startups on a tight budget. While there are some premium features and themes available for purchase, the core functionality of the platform is available at no cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. High-level Security
&lt;/h2&gt;

&lt;p&gt;Security is a top priority for any e-commerce business. PrestaShop takes this concern seriously by providing a secure platform that is regularly updated to address potential vulnerabilities. The platform also offers features like SSL support and PCI compliance, ensuring that your customers' sensitive data is protected.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Seamless Third-party Integrations
&lt;/h2&gt;

&lt;p&gt;PrestaShop is highly compatible with various third-party services and applications, making it easy to integrate your online store with other tools and platforms. From payment gateways to shipping providers and marketing tools, PrestaShop's extensive ecosystem allows you to build a comprehensive e-commerce solution tailored to your specific needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Mobile-friendliness
&lt;/h2&gt;

&lt;p&gt;With the ever-increasing importance of mobile commerce, having a mobile-friendly online store is essential. PrestaShop's responsive design ensures that your website looks great and functions smoothly on all devices, providing a seamless shopping experience for your customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, PrestaShop is an excellent e-commerce platform that offers a wide range of features, scalability, and a user-friendly interface, making it an ideal choice for businesses of all sizes. By choosing PrestaShop, you can build a powerful online store that is easy to manage, secure, and ready to scale as your business grows.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q1: Can I migrate my existing online store to PrestaShop?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, PrestaShop offers tools and resources to help you migrate your existing online store from another platform to PrestaShop. You can also seek assistance from the community or hire a professional to handle the migration process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q2: Does PrestaShop offer hosting services?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PrestaShop does not provide hosting services directly. However, the platform is compatible with various hosting providers, allowing you to choose the best hosting solution for your specific needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q3: How customizable is PrestaShop?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PrestaShop is highly customizable, allowing you to tailor the appearance and functionality of your online store to suit your preferences. With a wide range of themes and modules available, you can create a unique shopping experience for your customers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q4: Is PrestaShop suitable for large-scale e-commerce businesses?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, PrestaShop is designed to accommodate businesses of all sizes, including large-scale enterprises. Its scalability and extensive feature set make it an excellent choice for businesses with a large product catalog and high sales volume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q5: Can I use my own domain name with PrestaShop?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, you can use your own domain name with PrestaShop. The platform allows you to connect your custom domain to your online store, ensuring that your branding remains consistent across all channels.&lt;/p&gt;

</description>
      <category>prestashop</category>
      <category>shop</category>
      <category>cms</category>
      <category>ecommerce</category>
    </item>
  </channel>
</rss>
