<?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>DEV Community: Wolf</title>
    <description>The latest articles on DEV Community by Wolf (@serotoninja).</description>
    <link>https://dev.to/serotoninja</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1591551%2F561a4062-87b5-4d9e-9a46-6875a3e526de.jpg</url>
      <title>DEV Community: Wolf</title>
      <link>https://dev.to/serotoninja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/serotoninja"/>
    <language>en</language>
    <item>
      <title>The rule behind every Symfinity package</title>
      <dc:creator>Wolf</dc:creator>
      <pubDate>Wed, 24 Jun 2026 20:00:14 +0000</pubDate>
      <link>https://dev.to/symfinity/the-rule-behind-every-symfinity-package-gkh</link>
      <guid>https://dev.to/symfinity/the-rule-behind-every-symfinity-package-gkh</guid>
      <description>&lt;p&gt;Whenever I start a new package, I try to follow a simple rule.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a package does not improve developer experience, it probably should not exist.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sounds obvious. But it has become the guiding principle behind Symfinity.&lt;/p&gt;




&lt;h2&gt;
  
  
  A package must solve a real&amp;nbsp;problem
&lt;/h2&gt;

&lt;p&gt;The first question is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Would I actually use this package in my next project?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is no, it probably belongs in an experiment repository instead.&lt;/p&gt;

&lt;p&gt;That is how &lt;a href="https://github.com/symfinity/symfinity" rel="noopener noreferrer"&gt;symfinity/font-manager&lt;/a&gt; and &lt;a href="https://github.com/symfinity/symfinity" rel="noopener noreferrer"&gt;symfinity/omnia-ipsum&lt;/a&gt; started: I needed fonts and placeholder content on the next greenfield, not another abstract slot in a roadmap slide.&lt;/p&gt;




&lt;h2&gt;
  
  
  A package must be Symfony-native
&lt;/h2&gt;

&lt;p&gt;I do not want packages that fight Symfony. I want packages that feel like they belong there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symfony-native&lt;/strong&gt;, for Symfinity, means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Composer-first&lt;/strong&gt; — install with &lt;code&gt;composer require&lt;/code&gt;, not a parallel plugin manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flex recipes where they earn their keep&lt;/strong&gt; — sensible defaults, manifest-driven wiring, overrides in the usual Symfony config paths&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standard bundle shape&lt;/strong&gt; — Extension, Configuration, services tagged the Symfony way; no hidden bootstrap magic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks you already know&lt;/strong&gt; — Twig, Console, AssetMapper, and HTTP integration that follow Symfony docs, not a second framework inside the framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictable integration&lt;/strong&gt; — if you know Symfony, you know where to look&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Minimal surprises. No ecosystem lock-in dressed up as convenience.&lt;/p&gt;




&lt;h2&gt;
  
  
  A package must require little configuration
&lt;/h2&gt;

&lt;p&gt;Configuration is sometimes necessary.&lt;/p&gt;

&lt;p&gt;Excessive configuration is usually a sign that something can be improved.&lt;/p&gt;

&lt;p&gt;The best configuration is often the one users never have to write.&lt;/p&gt;




&lt;h2&gt;
  
  
  A package must work&amp;nbsp;alone
&lt;/h2&gt;

&lt;p&gt;Every Symfinity package should provide value on its own.&lt;/p&gt;

&lt;p&gt;If somebody installs only one package, the experience should still be worthwhile.&lt;/p&gt;

&lt;p&gt;No ecosystem lock-in. No artificial dependencies.&lt;/p&gt;

&lt;p&gt;Install only &lt;a href="https://github.com/symfinity/font-manager" rel="noopener noreferrer"&gt;symfinity/font-manager&lt;/a&gt; or only &lt;a href="https://github.com/symfinity/omnia-ipsum" rel="noopener noreferrer"&gt;symfinity/omnia-ipsum&lt;/a&gt; and you should still get a complete answer to that one problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  A package should work better&amp;nbsp;together
&lt;/h2&gt;

&lt;p&gt;At the same time, packages should share conventions.&lt;/p&gt;

&lt;p&gt;The more packages you combine, the more benefits you should get.&lt;/p&gt;

&lt;p&gt;Not because they are tightly coupled.&lt;/p&gt;

&lt;p&gt;Because they speak the same language.&lt;/p&gt;




&lt;h2&gt;
  
  
  The principle
&lt;/h2&gt;

&lt;p&gt;If I had to summarize the philosophy behind Symfinity in a single sentence, it would be this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Independent packages. Shared conventions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That idea influences every design decision.&lt;/p&gt;

&lt;p&gt;And it will continue to guide the project as it grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This article is the third part of a short introduction series to Symfinity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/serotoninja/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1"&gt;Why building Symfony-native packages instead of doing infrastructure again and again&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/serotoninja/why-symfony-projects-feel-more-fragmented-than-ever-4g6c"&gt;Why Symfony projects feel more fragmented than ever&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For package-level deep dives already published:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/font-manager-multi-format-font-export-for-symfony-41le"&gt;Font Manager: Multi-Format Font Export for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/omnia-ipsum-unified-placeholder-content-for-symfony-4oid"&gt;Omnia Ipsum: Unified Placeholder Content for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles on further Symfinity package tiers are planned, this is just the beginning.&lt;/p&gt;

&lt;p&gt;Explore packages and source at &lt;a href="https://github.com/symfinity/" rel="noopener noreferrer"&gt;github.com/symfinity&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>php</category>
      <category>symfony</category>
      <category>softwaredevelopment</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why Symfony projects feel more fragmented than ever</title>
      <dc:creator>Wolf</dc:creator>
      <pubDate>Wed, 24 Jun 2026 19:49:28 +0000</pubDate>
      <link>https://dev.to/symfinity/why-symfony-projects-feel-more-fragmented-than-ever-4g6c</link>
      <guid>https://dev.to/symfinity/why-symfony-projects-feel-more-fragmented-than-ever-4g6c</guid>
      <description>&lt;p&gt;Let me start with something important.&lt;/p&gt;

&lt;h2&gt;
  
  
  I love Symfony
&lt;/h2&gt;

&lt;p&gt;In my opinion, Symfony remains one of the best foundations for serious PHP applications.&lt;/p&gt;

&lt;p&gt;So this is not criticism of Symfony. It is an observation about modern projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Symfony Is Great at Solving Individual Problems
&lt;/h2&gt;

&lt;p&gt;Symfony gives us excellent building blocks—routing, dependency injection, security, forms, Messenger, Twig, the UX initiative, AssetMapper, Flex recipes, and more.&lt;/p&gt;

&lt;p&gt;The ecosystem is huge and mature. That is a strength.&lt;/p&gt;

&lt;p&gt;And Symfony keeps improving the glue: Flex recipes wire bundles in predictably, AssetMapper reduces frontend build-tool sprawl for many apps, and the UX packages give us shared patterns for live components and Stimulus.&lt;/p&gt;

&lt;p&gt;Those tools genuinely reduce fragmentation &lt;strong&gt;within&lt;/strong&gt; Symfony.&lt;/p&gt;




&lt;h2&gt;
  
  
  The side effect of&amp;nbsp;success
&lt;/h2&gt;

&lt;p&gt;Even with better defaults, modern Symfony projects often still stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Twig Components and UX packages from different vendors&lt;/li&gt;
&lt;li&gt;Asset management and font handling from different ecosystems&lt;/li&gt;
&lt;li&gt;Design systems and documentation tooling with their own conventions&lt;/li&gt;
&lt;li&gt;Frontend build tooling where AssetMapper is not enough&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each piece solves a legitimate problem. But the overall picture becomes harder to understand. The project starts to feel like a collection of systems rather than a single system.&lt;/p&gt;

&lt;p&gt;Placeholder content might come from one package, fonts from a workflow that still touches npm, UI primitives from a third library—each fine on its own, none sharing install steps or naming.&lt;/p&gt;




&lt;h2&gt;
  
  
  Death by configuration
&lt;/h2&gt;

&lt;p&gt;The challenge is rarely one specific configuration file. The challenge is understanding where everything lives.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which configuration belongs to which package?&lt;/li&gt;
&lt;li&gt;What is a default?&lt;/li&gt;
&lt;li&gt;What is overridden?&lt;/li&gt;
&lt;li&gt;What came from a recipe?&lt;/li&gt;
&lt;li&gt;What came from a bundle?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more moving parts a project has, the more difficult those questions become.&lt;/p&gt;




&lt;h2&gt;
  
  
  Looking for Consistency
&lt;/h2&gt;

&lt;p&gt;What I wanted was not less flexibility. I wanted more consistency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same conventions.&lt;/li&gt;
&lt;li&gt;The same installation experience.&lt;/li&gt;
&lt;li&gt;The same developer experience.&lt;/li&gt;
&lt;li&gt;The same language across multiple concerns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Symfony supplies the building blocks and much of the integration machinery.&lt;/p&gt;

&lt;p&gt;What was still missing for me was a &lt;strong&gt;cross-cutting layer&lt;/strong&gt;: packages that solve recurring app needs — fonts, placeholders, UI foundations — while agreeing on how they install, configure, and compose.&lt;/p&gt;

&lt;p&gt;That is a different job from replacing Flex or AssetMapper.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Symfinity Perspective
&lt;/h2&gt;

&lt;p&gt;Symfinity is my attempt to create that consistency layer.&lt;/p&gt;

&lt;p&gt;Not by replacing Symfony. Not by hiding Symfony.&lt;/p&gt;

&lt;p&gt;But by building packages that share common conventions and integrate naturally with each other — and with the Symfony tools you already use.&lt;/p&gt;

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

&lt;p&gt;Symfony's flexibility is one of its greatest strengths.&lt;/p&gt;

&lt;p&gt;But flexibility also creates opportunities for fragmentation—especially &lt;strong&gt;across&lt;/strong&gt; packages from different authors and eras.&lt;/p&gt;

&lt;p&gt;The goal of Symfinity is not to remove flexibility.&lt;/p&gt;

&lt;p&gt;The goal is to reduce friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This article is the second part of a short introduction series to Symfinity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/serotoninja/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1"&gt;Why building Symfony-native packages instead of doing infrastructure again and again&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3: &lt;a href="https://dev.to/serotoninja/the-rule-behind-every-symfinity-package-gkh"&gt;The rule behind every Symfinity package&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For package-level deep dives already published:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/font-manager-multi-format-font-export-for-symfony-41le"&gt;Font Manager: Multi-Format Font Export for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/omnia-ipsum-unified-placeholder-content-for-symfony-4oid"&gt;Omnia Ipsum: Unified Placeholder Content for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles on UI Kernel and the &lt;code&gt;ux-blocks-*&lt;/code&gt; component tiers are planned.&lt;/p&gt;

&lt;p&gt;Explore packages and source at &lt;a href="https://github.com/symfinity/" rel="noopener noreferrer"&gt;github.com/symfinity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was previously published on &lt;a href="https://medium.com/@serotoninja/why-symfony-projects-feel-more-fragmented-than-ever-eec6f7573e33" rel="noopener noreferrer"&gt;medium.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>symfony</category>
      <category>softwaredevelopment</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why building Symfony-native packages instead of doing infrastructure again and again</title>
      <dc:creator>Wolf</dc:creator>
      <pubDate>Wed, 24 Jun 2026 18:58:50 +0000</pubDate>
      <link>https://dev.to/symfinity/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1</link>
      <guid>https://dev.to/symfinity/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1</guid>
      <description>&lt;p&gt;For years, I did what many Symfony developers do. Whenever I needed a feature, I searched for a package:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Need fonts? Go to Google Fonts and wire it up in the assets.&lt;/li&gt;
&lt;li&gt;Need placeholder content? Add a package, implement helpers, call in Twig.&lt;/li&gt;
&lt;li&gt;Need a frontend toolkit? Make a choice and wire it up in the assets and in Twig.&lt;/li&gt;
&lt;li&gt;Need documentation tooling? Add another package and implement again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these decisions were wrong. Most of the tools were excellent. But after building project after project, I noticed a pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The same infrastructure, again and&amp;nbsp;again
&lt;/h2&gt;

&lt;p&gt;Every new project started with roughly the same checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fonts&lt;/li&gt;
&lt;li&gt;Placeholder content&lt;/li&gt;
&lt;li&gt;Assets&lt;/li&gt;
&lt;li&gt;UI helpers&lt;/li&gt;
&lt;li&gt;Documentation tooling&lt;/li&gt;
&lt;li&gt;Project conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The business logic was always different. The infrastructure was usually the same. Yet I kept rebuilding or reconfiguring it.&lt;/p&gt;

&lt;p&gt;Fonts often meant a separate frontend toolchain on top of PHP. Placeholder content meant yet another API shape and Twig integration to wire up. Each choice was reasonable; together they ate the first days of every greenfield.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Symfony stops being the whole story
&lt;/h2&gt;

&lt;p&gt;Symfony itself is fantastic.&lt;/p&gt;

&lt;p&gt;Routing, Dependency Injection, Security, Messenger, Twig, Console, Events — these are not the problem.&lt;/p&gt;

&lt;p&gt;The problem starts when a project grows.&lt;/p&gt;

&lt;p&gt;Soon there is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composer&lt;/li&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;Build tools&lt;/li&gt;
&lt;li&gt;Frontend frameworks&lt;/li&gt;
&lt;li&gt;Asset pipelines&lt;/li&gt;
&lt;li&gt;Configuration files everywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing is broken.&lt;/p&gt;

&lt;p&gt;But the cognitive load keeps growing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A different idea
&lt;/h2&gt;

&lt;p&gt;At some point I stopped asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Which dependency should I add next?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And started asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Why am I solving the same infrastructure problem for the tenth time?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question eventually became Symfinity. Not as a framework. Not as a Symfony replacement. Just as a collection of Symfony-native solutions for recurring problems.&lt;/p&gt;

&lt;p&gt;The first packages I packaged for real use were practical ones: &lt;a href="https://github.com/symfinity/symfinity" rel="noopener noreferrer"&gt;symfinity/font-manager&lt;/a&gt; for multi-format font export without leaving Composer and AssetMapper, and &lt;a href="https://github.com/symfinity/symfinity" rel="noopener noreferrer"&gt;symfinity/omnia-ipsum&lt;/a&gt; for placeholder content with one Twig-facing API instead of ad hoc fixtures.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal
&lt;/h2&gt;

&lt;p&gt;Every package should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solve a real problem&lt;/li&gt;
&lt;li&gt;Feel native to Symfony&lt;/li&gt;
&lt;li&gt;Require minimal configuration&lt;/li&gt;
&lt;li&gt;Work independently&lt;/li&gt;
&lt;li&gt;Integrate naturally with other Symfinity packages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A package should be useful even if it is the only Symfinity package in a project.&lt;/p&gt;

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

&lt;p&gt;Symfinity did not start with a grand vision of building an ecosystem. It started with a simple observation: I was rebuilding the same infrastructure over and over again. Eventually, packaging those solutions became the more sensible option.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This article is the first part of a short introduction series to Symfinity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/serotoninja/why-symfony-projects-feel-more-fragmented-than-ever-4g6c"&gt;Why Symfony projects feel more fragmented than ever&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3: &lt;a href="https://dev.to/serotoninja/the-rule-behind-every-symfinity-package-gkh"&gt;The rule behind every Symfinity package&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For package-level deep dives already published:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/font-manager-multi-format-font-export-for-symfony-41le"&gt;Font Manager: Multi-Format Font Export for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/omnia-ipsum-unified-placeholder-content-for-symfony-4oid"&gt;Omnia Ipsum: Unified Placeholder Content for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles on further Symfinity package tiers are planned, this is just the beginning.&lt;/p&gt;

&lt;p&gt;Explore packages and source at &lt;a href="https://github.com/symfinity/" rel="noopener noreferrer"&gt;github.com/symfinity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was previously published on &lt;a href="https://medium.com/@serotoninja/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-6f5c7e9f425d" rel="noopener noreferrer"&gt;medium.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>php</category>
      <category>opensource</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Omnia Ipsum: Unified placeholder content for Symfony</title>
      <dc:creator>Wolf</dc:creator>
      <pubDate>Wed, 24 Jun 2026 18:16:39 +0000</pubDate>
      <link>https://dev.to/symfinity/omnia-ipsum-unified-placeholder-content-for-symfony-4oid</link>
      <guid>https://dev.to/symfinity/omnia-ipsum-unified-placeholder-content-for-symfony-4oid</guid>
      <description>&lt;h2&gt;
  
  
  Rethinking fake content in Symfony&amp;nbsp;projects
&lt;/h2&gt;

&lt;p&gt;A prototype web page displaying pure placeholder content&lt;br&gt;
When building early UI prototypes or shaping design systems in Symfony, placeholder content becomes a constant companion. Lorem ipsum text. Dummy profile photos. Placeholder videos. Silent audio. Temporary avatars. Realistic fake user data. Every project needs them — and yet most setups rely on a patchwork of libraries, links and hardcoded values.&lt;/p&gt;

&lt;p&gt;Omnia Ipsum aims to fix that by giving Symfony developers a single, elegant toolkit for placeholder content of all kinds.&lt;/p&gt;

&lt;p&gt;In this article, I will walk you through the motivation behind the project, the conceptual patterns it follows, and its most advanced features — all designed to make your prototyping workflow faster, cleaner and more maintainable.&lt;/p&gt;


&lt;h2&gt;
  
  
  Motivation: Why a placeholder library?
&lt;/h2&gt;

&lt;p&gt;Most Symfony projects start the same way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You add lorem ipsum text manually into Twig templates.&lt;/li&gt;
&lt;li&gt;You grab placeholder images from an external service.&lt;/li&gt;
&lt;li&gt;You generate avatars using yet another site.&lt;/li&gt;
&lt;li&gt;You paste in temporary YouTube or stock video URLs.&lt;/li&gt;
&lt;li&gt;You install Faker separately whenever realistic data is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is inconsistent, fragmented and difficult to maintain.&lt;br&gt;
And even worse: placeholder content often leaks into production unless guarded carefully.&lt;/p&gt;

&lt;p&gt;The idea behind Omnia Ipsum was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“If your UI needs placeholder content, it should come from one place — predictable, configurable, and accessible directly from Twig.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This cuts down on boilerplate, cognitive overhead, and the "temporary chaos" of early-stage templates.&lt;/p&gt;


&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Prerequisite
&lt;/h3&gt;

&lt;p&gt;Go to &lt;a href="https://github.com/symfinity/recipes" rel="noopener noreferrer"&gt;github.com/symfinity/recipes&lt;/a&gt; and follow the instructions to add the required recipe repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; symfinity/omnia-ipsum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Usage
&lt;/h3&gt;

&lt;p&gt;Use the Twig functions immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;400&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Placeholder"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_avatar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'John Doe'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Avatar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;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 twig"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_video&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;1920&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;1080&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;audio&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_audio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/audio&amp;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 twig"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;lorem_title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;lorem_paragraphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;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 twig"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt; – &lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Everything is a Twig function
&lt;/h2&gt;

&lt;p&gt;Omnia Ipsum provides a set of expressive Twig helpers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;omnia_image(width, height)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;omnia_avatar(name, size)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;omnia_video(width, height)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;omnia_audio(seconds)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lorem_paragraphs(count)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fake('email')&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fake_text(200)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Advanced Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multiple Image Providers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'picsum'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'dummy'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'dummyimage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;background&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'#3355ff'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Automatic Avatar Generation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;omnia_avatar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Alice Johnson'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Placeholder Video &amp;amp; Audio
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;video&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{ omnia_video(1920, 1080) }}"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/video&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;audio&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{{ omnia_audio(5) }}"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/audio&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrated Lorem Ipsum Utilities
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;lorem_title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;lorem_sentences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;lorem_paragraphs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Faker Integration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'email'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'address'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;fake_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Extensible Architecture
&lt;/h2&gt;

&lt;p&gt;Developers can add custom providers or extend generator logic via Symfony services.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use Omnia Ipsum
&lt;/h2&gt;

&lt;p&gt;Ideal for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design systems&lt;/li&gt;
&lt;li&gt;Component libraries&lt;/li&gt;
&lt;li&gt;Prototyping complex UIs&lt;/li&gt;
&lt;li&gt;Responsive layout testing&lt;/li&gt;
&lt;li&gt;Admin dashboards&lt;/li&gt;
&lt;li&gt;Workshops and trainings&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Omnia Ipsum provides a unified, elegant API for all placeholder content commonly needed in Symfony projects. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want cleaner templates, faster prototyping, and a more structured workflow, Omnia Ipsum is a strong addition to your toolbox.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try it now: &lt;a href="https://github.com/symfinity/omnia-ipsum" rel="noopener noreferrer"&gt;symfinity/omnia-ipsum&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, star the repository and share it with your Symfony community.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Don't miss the introduction series to Symfinity:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/serotoninja/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1"&gt;Why building Symfony-native packages instead of doing infrastructure again and again&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/serotoninja/why-symfony-projects-feel-more-fragmented-than-ever-4g6c"&gt;Why Symfony projects feel more fragmented than ever&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3: &lt;a href="https://dev.to/serotoninja/the-rule-behind-every-symfinity-package-gkh"&gt;The rule behind every Symfinity package&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Another package-level deep dive:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/font-manager-multi-format-font-export-for-symfony-41le"&gt;Font Manager: Multi-Format Font Export for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles on further Symfinity package tiers are planned, this is just the beginning.&lt;/p&gt;

&lt;p&gt;Explore packages and source at &lt;a href="https://github.com/symfinity/" rel="noopener noreferrer"&gt;github.com/symfinity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was previously published on &lt;a href="https://medium.com/@serotoninja/omnia-ipsum-unified-placeholder-content-for-symfony-f8dfb1a89a6b" rel="noopener noreferrer"&gt;medium.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>php</category>
      <category>softwaredevelopment</category>
      <category>dev</category>
    </item>
    <item>
      <title>Font Manager: Multi-format Font export for Symfony</title>
      <dc:creator>Wolf</dc:creator>
      <pubDate>Wed, 24 Jun 2026 18:15:42 +0000</pubDate>
      <link>https://dev.to/symfinity/font-manager-multi-format-font-export-for-symfony-41le</link>
      <guid>https://dev.to/symfinity/font-manager-multi-format-font-export-for-symfony-41le</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Typography should be one of the simplest parts of a project.&lt;/p&gt;

&lt;p&gt;In reality, it often ends up scattered across multiple layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bootstrap: &lt;code&gt;$font-family-base&lt;/code&gt; variables&lt;/li&gt;
&lt;li&gt;Tailwind: JavaScript configuration&lt;/li&gt;
&lt;li&gt;TypeScript: type definitions&lt;/li&gt;
&lt;li&gt;Design systems: W3C Design Tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same font information gets copied and maintained in several places. Every update means touching multiple files, hoping everything stays in sync.&lt;/p&gt;

&lt;p&gt;It's repetitive, error-prone, and easy to get wrong.&lt;/p&gt;

&lt;p&gt;So I built Font Manager.&lt;/p&gt;

&lt;p&gt;Define your fonts once and export them in whatever format your project needs — CSS, Bootstrap variables, Tailwind configuration, TypeScript definitions, design tokens, and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;A simple Twig function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jinja"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;font_manager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ubuntu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'400 700'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;scss_bootstrap&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tailwind_config&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;typescript_definitions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One lock command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/console fonts:lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every format, automatically generated. Perfectly synced.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bootstrap Example
&lt;/h3&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Manually copy font name&lt;/span&gt;
&lt;span class="nv"&gt;$font-family-base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Ubuntu'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// ❌ Duplication&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'bootstrap/scss/bootstrap'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;scss_bootstrap&lt;/span&gt;&lt;span class="pi"&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 shell"&gt;&lt;code&gt;php bin/console fonts:lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app.scss&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'./assets/styles/fonts-bootstrap'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// ← Auto-generated&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'bootstrap/scss/bootstrap'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bootstrap uses your fonts automatically. No manual mapping. No duplication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tailwind Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;tailwind_config&lt;/span&gt;&lt;span class="pi"&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 javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// tailwind.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fonts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/fonts-tailwind.config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// ← Auto-generated&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fontFamily&lt;/span&gt; &lt;span class="p"&gt;}&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 html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-sans"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Your custom font, via Tailwind.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TypeScript Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;typescript_definitions&lt;/span&gt;&lt;span class="pi"&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 typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;FontFamily&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/fonts&lt;/span&gt;&lt;span class="dl"&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 typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;applyFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sans&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// ✓ Valid&lt;/span&gt;
&lt;span class="nf"&gt;applyFont&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// ✗ TypeScript error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typos caught at compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 12 Formats
&lt;/h2&gt;

&lt;p&gt;CSS, SCSS, JavaScript, Design Tokens — pick what you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/console fonts:formats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS: Variables, Modules, @layer&lt;br&gt;
SCSS: Variables, Bootstrap, Mixins&lt;br&gt;
JavaScript: ESM, Tailwind, TypeScript&lt;br&gt;
Design System: JSON, W3C Tokens, Figma, Style Dictionary&lt;/p&gt;
&lt;h2&gt;
  
  
  Build Tools
&lt;/h2&gt;

&lt;p&gt;AssetMapper, Webpack, or Vite? Auto-detected.&lt;/p&gt;

&lt;p&gt;Output paths adjust automatically. No config needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Design Systems
&lt;/h2&gt;

&lt;p&gt;Export to Figma Tokens, Style Dictionary, or W3C Design Tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;design_tokens&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;figma_tokens&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx style-dictionary build  &lt;span class="c"&gt;# CSS, iOS, Android from one source&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Design once. Ship everywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy Options
&lt;/h2&gt;

&lt;p&gt;Not just Google — choose your provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;default_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bunny'&lt;/span&gt;  &lt;span class="c1"&gt;# GDPR-compliant, zero tracking&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Google, Bunny, Fontsource, or Local. Same API. Your choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Architecture: Strategy pattern. Each format is a separate exporter.&lt;/p&gt;

&lt;p&gt;Dependency resolution: Automatic. css_modules needs css_variables? Handled.&lt;/p&gt;

&lt;p&gt;Build detection: Scans for webpack.config.js, vite.config.js, asset_mapper.yaml.&lt;/p&gt;

&lt;p&gt;Output paths: Adjusted per build tool. AssetMapper → assets/styles/. Webpack → assets/.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/console fonts:formats           &lt;span class="c"&gt;# List all formats&lt;/span&gt;
php bin/console fonts:format:info scss  &lt;span class="c"&gt;# Usage instructions&lt;/span&gt;
php bin/console fonts:export            &lt;span class="c"&gt;# Export manually&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Migrating from google-fonts
&lt;/h3&gt;

&lt;p&gt;One command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/console fonts:migrate-from-google-fonts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Config, templates, manifest — all updated automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://github.com/symfinity/recipes" rel="noopener noreferrer"&gt;github.com/symfinity/recipes&lt;/a&gt; and follow the instructions to add the required recipe repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require symfinity/font-manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. Symfony Flex does the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight twig"&gt;&lt;code&gt;&lt;span class="cp"&gt;{{&lt;/span&gt; &lt;span class="nv"&gt;font_manager&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ubuntu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'400 700'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dev: CDN&lt;br&gt;
Prod: Self-hosted (after fonts:lock)&lt;/p&gt;

&lt;p&gt;Add exports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;symfinity_font_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;export&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;formats&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;scss_bootstrap&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;tailwind_config&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php bin/console fonts:lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'./fonts-bootstrap'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="s1"&gt;'bootstrap/scss/bootstrap'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done.&lt;/p&gt;

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

&lt;p&gt;Typography shouldn’t waste your time or violate privacy law.&lt;br&gt;
With &lt;em&gt;font-manager&lt;/em&gt;, you can design freely in development, ship safely in production, and forget about fonts altogether.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One Twig function. Multiple providers. Twelve export formats. Zero manual mapping.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s Font Manager.&lt;/p&gt;

&lt;p&gt;Try it now: &lt;a href="https://github.com/symfinity/font-manager" rel="noopener noreferrer"&gt;symfinity/font-manager&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, star the repository and share it with your Symfony community.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Don't miss the introduction series to Symfinity:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Part 1: &lt;a href="https://dev.to/serotoninja/why-i-started-building-symfony-native-packages-instead-of-doing-infrastructure-again-and-again-4nc1"&gt;Why building Symfony-native packages instead of doing infrastructure again and again&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 2: &lt;a href="https://dev.to/serotoninja/why-symfony-projects-feel-more-fragmented-than-ever-4g6c"&gt;Why Symfony projects feel more fragmented than ever&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Part 3: &lt;a href="https://dev.to/serotoninja/the-rule-behind-every-symfinity-package-gkh"&gt;The rule behind every Symfinity package&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Another package-level deep dive:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/serotoninja/omnia-ipsum-unified-placeholder-content-for-symfony-4oid"&gt;Omnia Ipsum: Unified Placeholder Content for Symfony&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Articles on further Symfinity package tiers are planned, this is just the beginning.&lt;/p&gt;

&lt;p&gt;Explore packages and source at &lt;a href="https://github.com/symfinity/" rel="noopener noreferrer"&gt;github.com/symfinity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article was previously published on &lt;a href="https://medium.com/@serotoninja/beyond-css-multi-format-font-export-for-symfony-cabc2692734a" rel="noopener noreferrer"&gt;medium.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>symfony</category>
      <category>php</category>
      <category>softwaredevelopment</category>
    </item>
  </channel>
</rss>
