meniam/typograph-bundle
Symfony bundle that adds a Twig filter for typographing text using E. Muravjev's Typograph. Install via Composer, register the bundle, then apply {{ content | typograph }} in templates. Supports multiple named configs so different content types, like articles or news, can use their own typography se...
Architecture fit. The single most important finding is that this is not a Laravel package — it is a Symfony bundle whose registration model (new TypographBundle\FenrizbesTypographBundle() in AppKernel.php) predates Symfony Flex and has no Laravel equivalent. There is no TypographServiceProvider, no facade, no package auto-discovery. Architecturally, the bundle is a thin adapter: a Twig extension plus a DependencyInjection/Configuration.php tree that forwards options to E. Muravjev's Typograph algorithm. That means roughly 90% of the package's value lives in the underlying meniam/typograph library and the algorithm it wraps; the bundle layer is the part that does not fit.
For a Laravel codebase, the correct framing is: we are evaluating an algorithm plus a reference implementation, not a dependency we install. The bundle is a readable, MIT-licensed spec for how to wire the typographer and what options it accepts. That is a meaningful asset, but it changes the integration cost model from "composer require" to "extract and adapt," and it changes the ownership model from "upstream maintains this" to "we maintain this."
Integration feasibility. High, and bounded. The work decomposes cleanly: read vendor/meniam/typograph-bundle/src to identify the service class and config keys, translate Configuration.php into config/typograph.php, bind a singleton, expose a Blade directive or typograph() helper, and apply it at the presentation layer. The reference assessment estimates ~30 minutes of vendor reading; a realistic end-to-end estimate including fixture tests and one production surface is 1–3 engineer-days. Because the transformation is a pure, stateless string → string function with no I/O, no schema, and no external service, the blast radius is cosmetic: if it fails, content still renders, just with straight quotes and spaced dashes. This is one of the rare integrations where a failed pilot costs almost nothing to reverse.
Technical risk. The risk is concentrated in supply chain and silent failure, not in the algorithm:
it-blaster/typograph-bundle → meniam/...). The Packagist metadata and badges still reference the old name. This is a vendor-or-fork candidate, not a platform dependency. The mitigation is cheap and must be mandatory: pin an exact version, commit composer.lock, and mirror to internal VCS or a private Satis registry so a repo deletion cannot break our build.'"Привет" - мир' → «Привет» — мир), plus negative fixtures for code blocks, URLs, and emails.alt text, and code samples. This is a design constraint the product must absorb: typography applies to source text, before Markdown/HTML rendering, on a whitelist of fields — never as a response-level middleware.Key questions for the decision meeting.
meniam/typograph directly, fork the bundle, or reimplement the rules? Note that the algorithm itself (mdash.ru) is a third-party asset whose rules are essentially frozen — which lowers churn risk but also means no future improvements.Stack fit. Poor at the packaging layer, good at the domain layer. The bundle's Twig filter ({{ content | typograph }}) is incompatible with Blade — Blade has no pipe syntax, so copy-pasting the README produces a syntax error, not a typography bug. The Laravel-native equivalents are a global typograph() helper, a @typograph($text) directive, or a facade with @method annotations for IDE support. The bundle's AppKernel registration must be dropped entirely; there is no shim worth building.
Migration path. Do not install the bundle and try to make it behave like a Laravel package. Instead:
src/ and DependencyInjection/Configuration.php, and treat those as the specification.meniam/typograph directly (preferred — fewer layers, fewer abandoned layers) or to vendor the bundle source into app/Services/ under our own namespace. Forking into our namespace is defensible here precisely because the upstream is dormant; we will be maintaining it regardless.config/typograph.php, preserving the named-config concept (default, articles, news) since per-content-type rules are the one genuinely product-relevant feature.TypographService singleton, then layer on the helper/directive, the Eloquent accessor, and the queued bulk pass for retrofitting existing content.Compatibility. Three compatibility surfaces need explicit verification before committing: PHP version against the 2021-era codebase (expect older type-hint conventions), charset/locale end-to-end (MySQL charset, request encoding, and the typographer's configured charset must agree — a mismatch surfaces as mojibake that reads like a typography bug and will burn support time), and the HTML/Markdown boundary. Explicitly set locale and charset; unset values default to something we did not choose and the wrapper may silently pass text through unchanged. Confirm the exact FQCN of the typographer class in vendor/ before writing the service — do not trust the README.
Sequencing. Because the cost of reversal is low and the blast radius is cosmetic, sequence for fastest signal:
text_formatted column plus a queued bulk pass before expanding.--> and straight quotes inside code samples, JSON, URLs, and email addresses.Maintenance. Assume we own this. The package is dormant (last release December 2021, zero dependents, renamed repo), so there will be no upstream security patches, no PHP 8.x compatibility fixes, and no rule updates. The offsetting factor is that the underlying algorithm is essentially frozen — Muravjev's rules do not change — so the realistic maintenance burden is low-frequency compatibility work (PHP upgrades, framework upgrades) rather than active development. Concretely: mirror the package to internal VCS, pin the version, commit the lock file, and record in the ADR that a fork exists and who owns it. Budget a few hours per major PHP or Laravel upgrade. The larger ongoing cost is not code maintenance but rule governance — someone must own the YAML config, because typography settings are an editorial policy decision that will otherwise drift between content types.
Support. This is the underappreciated operational cost. Typography defects are invisible (a missing non-breaking space), subjective (which quote style is "correct"), and intermittent (locale- or encoding-dependent). Tier-1 support cannot triage "the dash looks wrong" reports. Two mitigations: (a) route typography issues to the editorial/content owner rather than engineering, and (b) keep the fixture suite as the contract — if the fixtures pass, the reported issue is a rule-configuration request, not a bug. Expect a small but persistent trickle of these in the first quarter after launch, tapering as the rule config stabilizes. Also expect the English-content question to come back: someone will ask why the marketing pages are not typographed, and the answer needs to be a documented scope decision, not an ad-hoc one.
Scaling. CPU cost is the scaling axis, and it is per-render, not per-user. On detail pages the cost is invisible; on list pages rendering 50 excerpts it is the difference between a ~40 ms and a ~4 ms rendering path. The mitigation is standard and cheap: cache formatted output per model (Cache::remember("article:{$id}:typographed", ...)), bust on saved, and for retrofits use a queued chunked bulk pass into an indexed text_formatted column. There is no horizontal-scaling concern — the transformation is stateless, so it scales trivially with app workers once caching is in place. Do not put this in API response middleware; walking JSON bodies to format string leaves will hit slugs, emails, and URLs and will be a recurring incident source.
Failure modes. Ranked by likelihood and cost:
None of these take the site down. That is precisely why this is a trial-and-instrument decision rather than a risk-committee decision — but it is also why it needs a named owner and a fixture suite, because cosmetic failures do not page anyone.
Ramp-up. Engineering ramp-up is genuinely low: a mid-level developer can read the vendor source and have a working singleton in half a day, and the pattern is well-trodden (helper, accessor, queued bulk pass). The real ramp-up is organizational: the editorial team needs to review typographed fixtures and own the rule configuration, and support needs to know this class of ticket exists and where to route it. Budget for a short editorial review session and a one-page internal note on scope (which locales, which fields, which exclusions) — that document, more than the code, is what prevents a year of low-grade confusion about why some pages are typographed and some are not.
How can I help you explore Laravel packages today?