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

Lin Codex Laravel Package

finity-labs/lin-codex

A Laravel/PHP package from Finity Labs that provides a structured codex for organizing, storing, and referencing definitions or documentation within your application, with a simple, configurable API for lookups and management.

View on GitHub
Deep Wiki
Context7

Getting Started

Clear the version floor before anything else. The documented failure mode in this package's history is a security bug, not an exception, so "it installed fine" tells you nothing:

php artisan --version                                              # >= 11.27.1
composer show illuminate/contracts | grep versions                 # >= 11.28 on the 11.x line
composer show spatie/laravel-settings | grep versions              # >= 3.7.2

On spatie/laravel-settings 3.7.0/3.7.1 the ShouldBeEncrypted attribute was unknown to the package, so an AI key saved through the settings page landed in settings.payload in plaintext. Pin it explicitly — composer require spatie/laravel-settings:^3.7.2 — rather than letting a transitive resolution decide for you.

Install, pinned:

composer require finity-labs/lin-codex:0.4.4 spatie/laravel-settings:^3.7.2
php artisan vendor:publish --tag=codex-config
php artisan vendor:publish --tag=codex-migrations
php artisan migrate

Confirm the publish tags and command namespace against the provider source — see Gotchas. After publishing, open the migrations directory and verify encrypt_codex_ai_api_key is present alongside the articles/settings tables. If it isn't, you published a stale set and you'll be inheriting the plaintext problem.

Read these four things, in this order, before writing a line of integration code:

  1. config/codex.php — content source (Markdown path vs. database), search options, and any Livewire alias registration.
  2. The service provider — how the drawer component is aliased and whether the Markdown loader is container-bound (matters for testing and for swapping sources).
  3. The Livewire component's mount() signature — this defines what "context" actually is. Route name? Arbitrary string? Model? Everything downstream depends on that answer, and the docs are not precise about it.
  4. The article model / Markdown parser — it tells you how keys, locales, and slugs map to files.

First use case: one screen, five articles, internal users. Do not start with a content migration or a CMS. Put five Markdown files in the configured directory — one for the screen generating the most tickets, four adjacent tasks — mount the drawer once in the authenticated layout behind a flag, and click through it:

{{-- resources/views/layouts/app.blade.php --}}
@auth
    <livewire:codex-help-drawer :context="request()->route()?->getName()" />
@endauth

Treat that attribute name as a guess until you've read mount(). An afternoon gets you a working end-to-end loop and surfaces the real questions — context keying, locale fallback, drawer styling — before you have a content strategy to defend.

Implementation Patterns

Choose a content source deliberately; they are not interchangeable day to day. Markdown ties help content to the release process: articles ship in the same PR that changes behavior, review happens in code review, and there's no authoring surface to build or secure. The cost is that a support lead cannot fix a typo without a deploy. Database rows invert that trade: editorial workflow, but you now own seeding, backup, and whatever UI sits on top — the package does not document a full CMS. The path most teams take: Markdown at launch, migrate to DB only when a named content owner exists and is blocked by deploy cadence. Design article keys so the migration is mechanical rather than a rewrite.

Key articles to screens, not URLs. Route names survive URL restructures and A/B tests; paths do not. Establish a convention on day one (billing.invoices.index, onboarding.step-2) and enforce it in review. A drawer that shows the wrong article is worse than no drawer — users stop trusting it after one bad hit and never come back.

Mount once, at the layout root. Per-page mounting gives you N components, N sets of listeners, and silent inconsistency when someone forgets. One mount driven by a context prop makes the feature flag a one-line change and gives you one place to instrument.

Gate it yourself. There is no documented per-role, per-plan, or per-tenant scoping. Anything in the articles table is visible to anyone who can mount the component. If you have internal runbooks or enterprise-only features in your help corpus:

@can('view-help')
    <livewire:codex-help-drawer :context="$context" />
@endcan

For per-tenant content, filter at the source — separate Markdown directories per tenant, or a scoped query — rather than assuming the package handles it.

Locale workflow. Translations are a first-class feature, so decide early whether your article keys are locale-namespaced (billing.invoices.index.de) or whether locale is a column. The namespaced approach makes search results separable if the package ends up mixing locales in a result set; the column approach is cleaner if search does respect the active locale. Verify which by seeding two locales of the same article and searching.

Budget your search before you scale content. Search is database-backed with no dedicated index. At a few hundred articles it's fine. Before committing to thousands × N locales, seed realistic data and measure query count and latency. This is the untested edge most likely to degrade in production rather than staging.

Test with a real corpus, not three fixtures. A factory plus a seeder that loads your actual Markdown directory lets you assert search relevance, locale fallback, and drawer render time in CI. Add a Livewire test that asserts the component resolves the expected article for a given context string — that single test catches the two most common regressions (context key drift and broken file paths). Do this before 200 articles exist, not after.

Keep AI out of the runtime path. If you're not using the AI capability — most teams won't be — install without --ai, leave api_key null, and give the SDK its key through config/ai.php as the README advises. The secret never reaching the database removes the entire encryption surface from your threat model and from your upgrade checklist.

Instrument the funnel. Drawer opens, searches, article opens, and zero-result searches are the metrics that justify the dependency. Without them you cannot answer "did this reduce tickets," and you'll be defending the package on vibes at the next planning cycle.

Gotchas and Tips

The plaintext key is the one that matters. If you inherit an install on spatie/laravel-settings 3.7.0/3.7.1, a key saved through the settings page is sitting in settings.payload unencrypted right now. The fix requires both publishing the new migrations and running migrate: encrypt_codex_ai_api_key encrypts in place and leaves an already-encrypted row byte-for-byte untouched, so it is safe and cheap to run everywhere. Run it on local and staging too — staging keys leak into screenshots and shared logs.

Publish migrations before you ever run migrate, and force-republish on upgrade. The settings migration ships with the others, but a stale published set will not pick up encrypt_codex_ai_api_key on its own. If you installed pre-0.4.4, vendor:publish --force on the migrations tag is required.

Expect doc drift; verify against the source. The installer appears as fin-codex:install in the README and codex:install in the release notes. Run php artisan list | grep -i codex and use whatever is actually registered. More broadly, the package's registry description (config-driven reference data, Eloquent/validation helpers, cache refresh commands) does not describe the shipped feature set in its release notes (Markdown/DB help articles, search, translations, a Livewire drawer, AI settings). Read the provider and the component before you plan around either description.

Pin exact versions and commit the lock. Pre-1.0, zero stars, zero dependents, single-maintainer footprint — breaking changes can land adjacent to patch releases. composer require finity-labs/lin-codex:0.4.4 is the responsible form in production; ^0.4 is only acceptable if you're prepared to read every diff.

Search has collation and locale sharp edges. There's no dedicated index; look at the generated SQL before concluding the content is bad. On SQLite, LIKE is case-insensitive only for ASCII; on MySQL the collation decides. Locale-aware ranking is not documented as a guarantee, and multi-locale result sets may mix languages. If they do, filter at the query level if exposed, or namespace keys per locale.

Two Livewire failure modes. Mounting inside a @guest layout (component mounts, auth-scoped queries fail silently) and mounting inside a nested Livewire component (event listeners don't reach the parent). Keep the drawer at the layout root.

Markdown + config/route caching = stale help. If your deploy caches config or views and articles are read at boot, a content-only deploy can serve the old article. Either don't cache the article index or add the cache clear to your deploy script. The symptom — "it's right in the repo but wrong in the app" — burns an hour every time it happens.

Debug in this order: (1) is the component mounted at all (Livewire devtools), (2) log the exact context string passed into mount(), (3) does an article with that key exist in the configured source, (4) is the locale resolving to the one you think it is. Nearly every "help isn't showing" report is step 2 or step 3.

Write down the exit path now. A drawer component, an article model, and a Markdown loader are not much code, and MIT licensing makes a fork realistic. Decide who owns that fork and under what trigger while you're calm — and note that a plaintext-key cleanup you didn't write is a bad thing to inherit blind.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle