mziraki/nova-persian-date-field
A Laravel Nova field for Persian (Jalali) dates, letting you pick and display dates in the Persian calendar while storing standard Gregorian values. Drop it into your Nova resources for a localized date experience.
Architecture fit. A pure presentation-layer Nova field: a PHP Field subclass plus a pre-compiled Vue component registered through Nova's asset pipeline and dropped into a Resource's fields() method. No Eloquent models, migrations, routes, or domain services are touched, so the architectural blast radius is confined to the admin UI — it can be adopted, swapped, or removed without a stored-record migration. For a TPM this is the important property: the package is a low-commitment ergonomic improvement, not an architecture decision. The one architectural question it forces is a data-model policy — Gregorian/UTC stays the storage of record, Jalali is display-only — and that should be written into the spike's acceptance criteria, not discovered in QA. If the field writes Jalali strings, it stops being a UX convenience and becomes a schema-and-index decision with downstream reporting consequences.
Integration feasibility. Mechanically trivial: composer require, register the field, exercise it on one Resource. The real gates are environmental. (1) Nova license in place and an actually supported Nova major — Nova 4 is Vue 2-based, Nova 5 moved to Vue 3/Inertia, and field components do not port automatically. The December 2024 release is contemporaneous with Nova 4, so Nova 5 support cannot be assumed. (2) PHP/Laravel constraint overlap verified explicitly rather than inferred from the README. (3) The conversion library identified — whether the field implements Jalali math itself or delegates to a vetted library (morilog/jalali, hekmatinasser/verta, or ICU fa-IR@calendar=persian) materially changes the risk profile. With 5 stars, 0 dependents, and a single maintainer there is no production evidence base, so feasibility must be established by a time-boxed spike with a named exit criterion, not by reading the docs.
Technical risk.
sortable(), range filters, and indexes to string comparisons — the one risk with irreversible cost.Key questions. Which Nova majors does it support — 4 only, or 5 as well? Does it write a Gregorian datetime, and in which timezone? Does it bundle a conversion library, and which one, and is that a pinnable transitive dependency rather than vendored source? Does it honor APP_TIMEZONE and per-user preferences, or hardcode Tehran? Are sortable(), filterable(), nullable values, and Nova validation supported? What is the license, and is forking permissible? Are dist/ assets committed and reproducible from source, or do we inherit a Node build step? Which exact Nova/Laravel/PHP versions were validated?
Stack fit. Best fit is a Laravel + Nova application serving Persian-speaking administrators, on Nova 4. Applications on Nova 5, or without a Nova license, should not pursue this — and if the product isn't on Nova at all, the package is simply out of scope (Filament Jalali plugins, or a Blade/Inertia form plus a mature JS Jalali datepicker, become the alternatives). Crucially, frame the value as error reduction and operator speed, not new capability: every Jalali date can already be entered as Gregorian today. That framing is what keeps the investment proportionate and the "do nothing" baseline honest.
Migration path. Do not reference the vendor class directly across many Resources. Introduce an internal field class — App\Nova\Fields\JalaliDateTime extending or composing Mziraki\PersianDateTime — and expose only that. This creates a single swap point for a fork, a patch, or full replacement with an in-house field backed by a vetted conversion library, and one place to enforce the storage contract and attach our own tests. Vendor or fork at the outset: that converts an unquantified external dependency into a known internal one.
Compatibility. Pin the Nova major in composer.json and treat any Nova upgrade as a gated change requiring field regression tests. Verify PHP/Laravel constraint overlap explicitly. Confirm whether dist/ is committed — if not, we inherit a front-end build step and its maintenance. Confirm the conversion library is a dependency we can pin and patch.
Sequencing.
sortable() and filterable() exercised explicitly rather than assumed.Stakeholder framing. To executives: a small, low-cost enabler for Persian-market entry with contained downside — an isolated UI field we can swap or remove without touching stored records, provided we hold the Gregorian-storage discipline. To engineering: one wrapper, one fork, one spike, one pilot, non-negotiable conversion and timezone tests. This package answers one narrow roadmap question concretely — can an in-region operator enter a date in the calendar they actually think in, without us building calendar infrastructure? — and should be sequenced as an input to the localization decision, not as the localization strategy itself.
Maintenance. Assume we own this on day one. The realistic ongoing cost is a few days per Nova major upgrade plus ad-hoc patches when upstream goes quiet — which, given a single maintainer and a December 2024 release, is the base case rather than a tail risk. Budget a named owner (an engineer, not a team), a pinned version, and a documented fork policy. The wrapper class is what makes this tractable: without it, every consuming Resource becomes a migration site. Document the storage and timezone contract internally, because that knowledge does not exist anywhere upstream and will not survive staff turnover unless written down.
Support. There is no vendor and no SLA — there is a maintainer. Internal support burden is bounded by the wrapper: one place to debug, one place to patch. In-region operators will file "the date is wrong" tickets, and the resolution path (is it conversion, timezone, or display?) needs to be documented before rollout, not reverse-engineered after. Any customer-facing surface raises this materially; the blast radius of a silently wrong date is far larger than 5 stars justifies.
Scaling. Technical scaling is a non-issue — it is a per-field UI component with no server-side computational footprint. The scaling risk is organizational: the number of Resources consuming the field, and the number of operators depending on it, both grow adoption of an unmaintained dependency. Counter that by keeping consumption behind the wrapper and by treating the dependency as a candidate for in-housing once the Persian surface becomes material — at which point the wrapper is the migration seam and the fork is the fallback.
Failure modes. Rank them by cost, not likelihood. (1) Silent Jalali-in-database — the only irreversible failure; ordering, range filters, and reporting quietly degrade. Mitigated by the storage gate before data exists. (2) Off-by-one-day at DST or midnight boundaries — plausible-looking, expensive to catch after the fact, surfaces as billing or delivery corrections. Mitigated by an explicit timezone contract and round-trip tests. (3) Nova upgrade breakage — noisy and contained if the wrapper and regression tests exist; silent if they don't. (4) Upstream abandonment — absorbed by the fork policy. (5) Year-boundary conversion errors — caught by the spike corpus or not at all. Note the common thread: every high-cost failure is caught by a cheap, front-loaded control.
Ramp-up. Low for engineers already fluent in Nova — a day of integration, a one-to-two-day correctness spike, a pilot. The non-obvious ramp-up cost is domain: Jalali conversion edge cases, Iran's 2022 DST abolition, and the fiscal-year boundary (Farvardin 1) are not knowledge the team has today. Budget for someone to own that understanding explicitly, validate against a reference implementation, and record it. Then hold the line on scope: this solves Persian date entry and display in the admin. It does not deliver RTL layout, translated validation messages, Persian numeral formatting, locale-aware sorting, or server-side Jalali date math — pair it with a PHP conversion library for anything beyond the field, and say so out loud so the package isn't mistaken for a localization program.
How can I help you explore Laravel packages today?