nette/neon
NEON is a human-friendly, YAML-like data serialization format used for Nette configuration files. This package provides a fast, strict parser and dumper for PHP, with support for comments, inheritance, entities and includes, plus detailed error reporting.
Architecture fit
Laravel's configuration layer is opinionated: config/*.php files returning arrays, loaded by Illuminate\Foundation\Bootstrap\LoadConfiguration, flattened into a dot-notation repository, and frozen into a single PHP file by config:cache. nette/neon provides none of those hooks — it is a pure codec (Neon::decode(), Neon::decodeFile(), Neon::encode()) plus an AST/traverser layer added in v3.3.0. Adopting NEON therefore means inserting a parallel format into a pipeline that assumes PHP arrays at load time. That is architecturally possible but it is additive architecture, not a fit: we would be maintaining a translation layer whose only job is to convert a format Laravel does not speak into one it does. The v3.4.x phpDoc and static-analysis improvements remain genuinely useful for the adapter code we would write, and v3.4.9 extends the supported runtime to PHP 8.6 — but none of this changes the equation. They improve the ergonomics of the wrapper and the lifespan of the dependency, not the fit of the package.
Integration feasibility
Moderate effort, well-bounded. The realistic shape is ~150–300 LOC: a NeonConfigServiceProvider or bootstrap hook that globs config/*.neon, decodes each with Neon::decodeFile() (atomic since v3.3.4 — meaningful here, since config reads happen concurrently during deploy), and merges into the repository ahead of LoadConfiguration's PHP pass. The non-obvious work is not decoding; it is:
config:cache will silently ignore NEON files unless we override ConfigCacheCommand or pre-merge before the cache is written. This is the single most common way this integration breaks in production. Unchanged by v3.4.9.env() overrides must be defined and documented, or we get divergent behaviour between cached and uncached environments.DateTimeImmutable, and INF/NAN throw (v3.4.1). v3.4.9 adds a subtler rule: a date-shaped literal that is not a valid date (2024-02-30, 2024-13-01) now decodes as a plain string rather than failing. That converts an obvious parse error into a plausible-looking string value, which is a worse failure signature for config. Every one of these is a config-value surprise, and the set is still growing in minor versions.Also note: the package is not Laravel-discoverable in any meaningful sense — no facade, no config stub, no published provider. Every integration is bespoke and therefore every integration is a snowflake.
Technical risk Elevated, and concentrated in four places:
NOASSERTION. Nette components are conventionally BSD-3-Clause, but a TPM cannot approve a production dependency on convention. Legal sign-off is a hard gate before any code is written. This alone can stall the initiative for weeks. Nothing in v3.4.9 touches this.on/off syntax and raised the floor to PHP 8.0, and v3.4.9 reserves the !!chain entity name and rejects it in input. These are disciplined, well-documented breaks, but they are breaks, and a config loader sits on the critical boot path. Any of them becomes an outage class for us. The v3.4.9 item is low-probability for our own configs; the pattern is the risk, not the specific keyword.nette/di, nette/bootstrap, and the wider Nette framework. I would not use the dependent count from this dataset as an adoption signal in either direction, and I would flag the opportunity score of 47 as low-confidence.Key questions
!!chain, or rely on invalid dates raising an error? Both behaviours changed in v3.4.9 and both should be grepped before any upgrade.Stack fit
Poor-to-neutral. There is no first-party Laravel or Symfony bridge; NEON's natural home is Nette's DI container, where NEON is the native config syntax. In Laravel we would be a guest in someone else's house in both directions: NEON is foreign to Laravel, and Laravel's config conventions are foreign to NEON's ecosystem. The compensating factor is that the package is small, dependency-light, and has a clean, stable public surface (Neon::decode/decodeFile/encode plus the AST classes) — so the adapter surface we must pin is narrow. v3.4.9 does not change the public surface; it changes decode behaviour at the edges.
Migration path Incremental and reversible, which is the main argument for proceeding at all:
2024-02-30, 2024-13-01) alongside the big-int and INF/NAN cases.config/app.php or config/database.php first.Compatibility
config:cache is the compatibility hotspot. Treat cache-aware loading as a first-class requirement, not a follow-up ticket.neon-lint (v3.3.1+) in CI so malformed NEON fails in the pipeline rather than at boot. Pin the linter to the same version as the runtime, and re-lint on every bump — v3.4.9's !!chain reservation is exactly the class of change a linter catches and a code review does not.Sequencing
Legal/license clearance → spike (2–3 days: loader + config:cache interaction + parity harness) → go/no-go on the spike → pilot domain behind a flag → parity in CI → per-domain promotion → deprecate PHP equivalent once a domain has run clean for a full release cycle. The spike must explicitly prove the config:cache path before any production commitment; that is the decisive experiment and it is cheap to run. Add one task to the spike: audit any candidate NEON corpus for !!chain usage and for invalid-date literals that previously failed loudly.
Maintenance The package itself is low-maintenance — it is mature, actively released (v3.4.8 shipped 2026-05-11 and v3.4.9 has already followed with PHP 8.6 support), and has a well-kept changelog. The release cadence is a mild negative: two releases inside the review window, one of which is a behavioural BC break, which means our pinned-version bump is not a trivial chore. The maintenance cost sits almost entirely on our adapter, which is bespoke, has no upstream, and must track the package's minor-version BC breaks. Budget realistically: a few days per year for version bumps plus whatever the adapter's owner costs — and treat each bump as a code change requiring the parity suite, not a lockfile edit. If no team will own it, that is a stronger signal against adoption than any technical concern here.
Support Support surface is a public GitHub repository plus documentation and release notes — no commercial backing, no SLA. That is normal and acceptable for a library of this size and stability, but it means boot-path questions get answered by us, not by a vendor. Internal runbook (what a NEON parse failure looks like, how to triage, how to roll back a domain) is a prerequisite, not documentation debt.
Scaling
Effectively free. Decoding is per-request only if we decode per-request — and we should not: decode once at boot and rely on config:cache, exactly as Laravel does for PHP configs. The package is designed for speed with minimal dependencies; parse cost is not a scaling concern. The scaling concern is cognitive: every engineer who touches config must now know two formats, and every new hire must learn NEON's block-array and multiline-string syntax to read a config file. That is a permanent, compounding tax across the team in exchange for a one-time readability gain on the files themselves.
Failure modes
!!chain usage that v3.4.9 rejects), or an invalid UTF-8 byte (encoder replaces these with U+FFFD as of v3.4.7; the decoder is strict) takes the app down before logging is reliable. Wrap and degrade.DateTimeImmutable, and as of v3.4.9 invalid dates arriving as ordinary strings, breaking downstream consumers that expect exact types or that previously depended on the parse error as a guardrail. The parity harness, extended with date-shaped fixtures, is the control. This is the failure mode v3.4.9 most affects.on/off, and v3.4.9 did with !!chain). Mitigate with neon-lint in CI pinned to the target version, upgraded deliberately rather than automatically.NOASSERTION flag discovered after code is in production is the most expensive failure mode on this list and the cheapest to avoid.Ramp-up
Small but non-zero. Engineers need perhaps an hour with the syntax and the docs to read and edit NEON confidently; the block-array and """ multiline conventions are the only genuinely unfamiliar parts. The larger ramp-up cost is organisational: reviewing config PRs now requires a second mental parser, and the "just read config/database.php" reflex no longer works uniformly.
TPM recommendation
Conditional no-go, with a narrow yes — unchanged in direction by v3.4.9. Absent a concrete forcing function — an existing NEON corpus, a Nette-based partner system, or an acquired codebase — the value is readability on configs most engineers already read fine, purchased with a bespoke boot-path component, a permanent two-format tax, and an unresolved license question. Do not adopt for greenfield. The v3.4.9 release does not create a forcing function; it marginally improves the dependency's lifespan (PHP 8.6) while marginally worsening the failure characteristics (invalid dates degrade silently, another minor-version input break). If a forcing function exists, run the 2–3 day spike against config:cache and the parity harness, clear legal first, audit the corpus for !!chain and date-shaped literals, and scope the rollout to the domains that actually need NEON rather than the whole config/ directory.
How can I help you explore Laravel packages today?