Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Deck Laravel Package

promptphp/deck

Deck (formerly Prompt Deck) brings versioned AI prompt management to Laravel and PHP: store prompts as files, interpolate variables, track performance, run A/B tests, and activate versions across your app with Laravel AI SDK integration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Disposition: conditional adopt — pilot on a non-critical AI path, wrapped behind an internal adapter, with tracking enabled only after the tables are verified. The package is cheap to try and cheap to abandon, but it is pre-1.0, single-maintainer, and its own changelog shows production-affecting defects shipping in patch releases.

Architecture fit

  • Prompts live in resources/prompts/<name>/ as markdown plus metadata.json, versioned in the same repo as the code that calls them. This is the correct fit for teams that want prompt changes under code review, PR gates, and deploy-time reproducibility — no second CMS, no credential sprawl, no sync problem between prompt store and app.
  • The facade is transport-agnostic: Deck::get() → $prompt->system($vars) / $prompt->toMessages($vars) returns a plain chat-completion messages array, so it works with the Laravel AI SDK or any other client. Vendor lock-in is genuinely low.
  • Explicit non-fit: non-engineers authoring or editing prompts (no UI, requires PR + deploy), and per-tenant/dynamic prompt variants (structure is one directory per prompt; no scoping mechanism is documented — see questions). If the roadmap includes "marketing owns the tone-of-voice prompt," this package blocks it.

Integration feasibility

  • Surface area is small and conventional: composer require, publish config, php artisan migrate, four Artisan commands (make:prompt, prompt:list, prompt:activate, plus test/diff), one facade, one optional trait. A mid-level Laravel developer is productive inside a day.
  • Exit cost is the strongest argument for adopting: the artifacts are markdown and JSON on disk. If the package is abandoned, an internal loader replaces Deck::get() in an afternoon. This should be treated as the primary risk mitigation, and it argues for an internal PromptRepository adapter now rather than calling the facade directly in dozens of call sites.

Technical risk

  • 0.x with breaking minors. 0.4.0 renamed the package (veeqtoh/prompt-deck → promptphp/deck) and the entire public namespace (Veeqtoh\PromptDeck → PromptPHP\Deck), with the old namespace removed. Any further rename is a find-and-replace across the codebase plus a lockfile change.
  • The 0.4.6 changelog is the most informative document in the repo. It fixes a path-traversal read via unvalidated prompt names, a version regex (/v(\d+)$/, unanchored) that reported rev2/dev3/archive-v9 as legitimate versions, a make:prompt name kebab-caser that could scaffold unloadable prompts, Deck::activate() never actually inserting rows so runtime activation silently no-op'd, and tracking defaulting on whenever APP_DEBUG was false — which made the natural production install throw no such table: prompt_versions on the first Deck::get(). Each is individually fixable; collectively they show hardening arriving after release rather than before. Assume more of this and read every changelog before bumping.
  • "A/B testing" is not experimentation. As described, it is global version activation plus outcome tracking: activate v2, compare tracked metrics over a time window. That is a sequential comparison with no traffic split, no cohort assignment, no holdout, and no significance testing. Time-of-day, weekday, and upstream model changes all confound it. Do not let this feature name into a roadmap slide without that qualifier.
  • Two sources of truth after tracking is enabled. Once a version has been activated with tracking on, the database takes precedence over metadata.json, so editing active_version in a file and deploying no longer changes what is served. This is documented and arguably correct, but it breaks the "prod is git HEAD" guarantee that justified the file-based design in the first place.

Key questions

  1. What is the exact PHP constraint, and is Laravel 12/13 the full supported matrix? (The 0.2.0 change added Laravel 13; the PHP floor is only shown as a Packagist badge.)
  2. Is prompt_versions an audit trail? Does activate() record who activated and why, or only timestamps? Without an actor, rollback forensics mean correlating deploys by hand.
  3. Can Deck::get() names ever be derived from user input? InvalidPromptNameException is thrown — where is it caught, and does it become a 500 on a paid inference path?
  4. Does {{ $variable }} escape or sanitise? If user-supplied text can be interpolated into a system.md role, that is a prompt-injection surface and a support-escalation path, not just a rendering detail.
  5. Is active-version resolution cached, and does the tracking path issue a query per render? The 0.4.6 note that "caching gave no protection, because the active version is resolved before the cache is consulted" implies resolution sits on the hot path.
  6. Is there any multi-tenant or per-customer prompt variant mechanism, or is one directory per prompt absolute?
  7. Who is the second maintainer? Bus factor is currently one (Victor Ukam), funded via sponsorship, with no commercial support tier.

Integration Approach

Stack fit Laravel 12/13 with an optional, removable coupling to the Laravel AI SDK via the HasPromptTemplate trait (which supplies instructions() and promptMessages() so agents don't hand-define them). Because toMessages() emits a standard messages array, the package is usable with any chat-completion client and is not a decision that couples to your model vendor. Config includes a toggle for auto-scaffolding prompt directories on make:agent.

Migration path

  • Greenfield: install with DECK_TRACKING_ENABLED=false explicitly set. Confirm rendering, prompt:list, and activation work end-to-end before enabling tracking in a non-production environment.
  • From veeqtoh/prompt-deck 0.3.x: follow UPGRADE.md; the namespace rewrite is mandatory and the old namespace is gone, so there is no compat shim. If tracking was already on, tables must be re-published and migrated because prompt_versions.user_prompt became nullable in 0.4.6.
  • Prompt content: the on-disk layout appears unchanged across the rename, so existing prompt directories should carry over, but this is worth verifying on a copy rather than assuming.

Compatibility and coexistence

  • Do not rely on Deck's activation for experiments. The recommended pattern is: Deck owns versioned storage and rendering; your feature-flag or experimentation system owns assignment. Pin the version explicitly — Deck::get('order-summary', $assignedVersion) accepts 'v2' or 2 — and let the flag system decide who gets which. This gives real splitting without waiting for the package to grow a capability it may never build.
  • Pinning policy: exact-version constraints on 0.x. A ^0.4 range will pull minors that have historically included security fixes and behavioural changes in the same release.

Sequencing

Phase Scope Exit criteria
1. Spike (1–2 days) Install in a sandbox branch, tracking off, one low-risk prompt (e.g. summarisation), called through an internal PromptRepository adapter Rendering and activation work; adapter is the only place the facade is referenced
2. Pilot (1 sprint) One production feature, tracking on in staging only, prompt:list --all in the deploy checklist No tracking-related incidents; drift check between git and DB is documented
3. Tracking in prod Enable tracking, add monitoring on write count A/B comparison is interpretable, or explicitly scoped down to "version history + rollback"
4. Scale out Migrate remaining ad-hoc prompt strings; add AI SDK trait to agents Prompt changes are reviewable in PRs and rollback is a one-command runbook

Hold at phase 2 if the pilot surfaces drift between file and DB state that the team cannot detect automatically, or if anyone outside engineering needs to edit prompts.

Operational Impact

Maintenance

  • Treat as a pinned dependency with a read-the-changelog ritual, not a set-and-forget utility. Budget roughly one to two days per minor bump for review and regression testing, based on the 0.4.x cadence.
  • Single maintainer. Mitigations: the internal adapter, a fork-and-patch capability on the team (MIT licence permits it), and the fact that the data format is simple enough to reimplement. Do not add this to a regulated or revenue-critical path without naming an internal owner who has read the source.

Support

  • GitHub issues plus a maintainer email address for security disclosures; no SLA, no paid support tier, 0 dependents and 117 stars means a thin community to lean on when something breaks. Response time is a personal courtesy, not a commitment. Plan the escalation path as "we patch our fork" rather than "we file a ticket."

Scaling

  • Prompt assembly cost is file reads plus string interpolation, negligible against token spend — until the active-version lookup and tracking insert land on the hot path. With tracking enabled, expect an extra read and write per render.
  • Verify active-version caching behaviour before high-volume rollout; the changelog's own note suggests version resolution bypasses the cache. If so, put a request-scoped memo in the adapter.
  • The real scaling constraint is organisational, not technical: every prompt variant is a directory and a PR. At dozens of prompts across teams, you need a naming convention and a CODEOWNERS entry, or prompt:list --all becomes unreadable.

Failure modes

Failure Symptom Control
Tracking tables absent/not migrated 0.4.6+ degrades to metadata.json with a single logged warning instead of throwing Alert on tracking write count dropping to zero; a silent degrade means empty experiment data, not a visible error
DB vs file drift on active version Prod serves a version that isn't what metadata.json in git says Scheduled prompt:list --all diff against git; runbook entry that activation is environment state
Invalid prompt name InvalidPromptNameException → 500 on the inference path Only ever pass literal, validated names; catch and fall back at the adapter boundary
Missing prompt or version at render time Exception after the user has waited, on a paid call Fallback prompt constant in the adapter; render-failure metric
User text interpolated into system.md Prompt injection, tone/style escapes Route untrusted text into a user role only; review every system.md that takes a $variable from request input
Package rename / breaking minor Fatal on deploy, dependency audit noise Exact version pins, adapter isolation, upgrade guide in the runbook
make:prompt overwrite of a live version Prior content replaced in place Prefer new-version workflow; git is the recovery path, so never run it on an uncommitted tree

Ramp-up

  • Engineering: under a day for the facade and Artisan commands; the Mintlify docs site has dedicated pages for installation, commands, tracking, testing, and the API reference, which is better than most 0.x packages.
  • Non-engineering authors: the honest answer is they cannot self-serve. If PMs or support leads will own prompt copy, you must build the PR-and-review convention and pair them with an engineer, or budget for a lightweight internal editor that writes the same files. That cost is real and should be weighed against the "free" install.
  • Add three operational habits from day one: prompt:list --all in the pre-deploy checklist, monitoring on tracking writes, and exception alerting on prompt-name and prompt-not-found failures.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode