PHP code example of finity-labs / lin-codex

1. Go to this page and download the library: Download finity-labs/lin-codex library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

finity-labs / lin-codex example snippets


use FinityLabs\LinCodex\Enums\ArticleFormat;
use FinityLabs\LinCodex\Rendering\ArticleRenderer;

$article = app(ArticleRenderer::class)->render($body, ArticleFormat::Markdown, 'en', 'users/roles');
$article->html;       // safe HTML with codex-* classes
$article->toc;        // [['level' => 2, 'text' => 'Reset a password', 'id' => 'reset-a-password'], ...]
$article->plainText;  // search text

use FinityLabs\LinCodex\Contracts\ContentSource;
use FinityLabs\LinCodex\Enums\ContextType;

$source = app(ContentSource::class);
$source->findBySlug('users/roles');                          // ArticleData or null
$source->findByContext(ContextType::Route, 'users.index');   // ArticleData[] for that page
$source->tree();                                             // TreeNode[] roots
$source->allForSearch();                                     // SearchDocument[], one per language; the searcher builds its index from these
$source->warnings();                                         // SourceWarning[]

use FinityLabs\LinCodex\Auth\ViewerResolver;
use FinityLabs\LinCodex\Contexts\ContextResolver;
use FinityLabs\LinCodex\Contexts\PageContext;
use FinityLabs\LinCodex\Reading\ArticleReader;
use FinityLabs\LinCodex\Reading\TreeBuilder;

$viewer = app(ViewerResolver::class)->resolve();          // guest in Tinker unless you Auth::login() first

app(ContextResolver::class)->resolve(new PageContext('users.index', '/users'), $viewer);   // ArticleData[] for that page, best first
app(ArticleReader::class)->read('users/roles', $viewer, 'de');                            // ReadArticle or null
app(TreeBuilder::class)->build($viewer);                                                   // TreeNode[] with translated labels

use FinityLabs\LinCodex\Settings\CodexSettings;

$settings = app(CodexSettings::class);
$settings->revisions_enabled = true;
$settings->revisions_keep = 10;      // the default
$settings->save();

use FinityLabs\LinCodex\Enums\RevisionReason;
use FinityLabs\LinCodex\Revisions\RevisionManager;

app(RevisionManager::class)->attributing(RevisionReason::AiRewrite, $userId, fn () => $translation->save());
app(RevisionManager::class)->withoutRevisions(fn () => $translation->save());   // bulk fixes, migrations

app(RevisionManager::class)->restore($revision, $userId);

use FinityLabs\LinCodex\Settings\CodexAiSettings;
use FinityLabs\LinCodex\Translation\DefaultInstructions;

$settings = app(CodexAiSettings::class);
$settings->enabled = true;
$settings->provider = 'anthropic';
$settings->model = null;                                            // the provider's default text model
$settings->api_key = 'sk-...';                                      // stored encrypted
$settings->timeout = 120;                                           // seconds; the default
$settings->translation_instructions = DefaultInstructions::TEXT;    // the editable half of the prompt, below
$settings->save();

use FinityLabs\LinCodex\Ai\Contracts\AiClient;

$client = app(AiClient::class);
$client->providers();                 // ['anthropic' => 'Anthropic', 'xai' => 'xAI', ...]
$client->tierModels('anthropic');     // ['default' => ..., 'cheapest' => ..., 'smartest' => ...]
$client->testConnection('anthropic', null, 'sk-...');   // null on success, else a reason key

use FinityLabs\LinCodex\Ai\AiAvailabilityCheck;

$state = app(AiAvailabilityCheck::class)->check();
$state->available;   // bool
$state->reason;      // null, or one of the four keys below
$state->label();     // that key in the current locale, '' when available

use FinityLabs\LinCodex\Translation\ArticleTranslator;

$result = app(ArticleTranslator::class)->translate($article, 'de');

$result->ok;                // bool
$result->title;             // string on success
$result->excerpt;           // string, or null when the source excerpt was blank
$result->body;              // string on success
$result->promptTokens;
$result->completionTokens;
$result->reason;            // an Ai\AiReason key on failure
$result->reasonLabel();     // that key in the current locale

use FinityLabs\LinCodex\Translation\MissingTranslations;

$missing = app(MissingTranslations::class);
$missing->for($article);               // ['de', 'hu']
$missing->isMissing($article, 'de');   // bool
$missing->candidates();                // every configured language except the default

use FinityLabs\LinCodex\Jobs\TranslateArticle;

TranslateArticle::dispatch($article->id, ['de', 'hu'], $userId);

use FinityLabs\LinCodex\Events\ArticleTranslated;
use Illuminate\Support\Facades\Event;

Event::listen(function (ArticleTranslated $event) {
    $event->report->toArray();
    // ['de' => ['status' => 'translated', 'reason' => null, 'prompt_tokens' => 812, 'completion_tokens' => 1104],
    //  'hu' => ['status' => 'failed', 'reason' => 'rate_limited', 'prompt_tokens' => 0, 'completion_tokens' => 0]]
});

use FinityLabs\LinCodex\Auth\ViewerResolver;
use FinityLabs\LinCodex\Search\Searcher;

$viewer = app(ViewerResolver::class)->resolve();
$result = app(Searcher::class)->search('passwort zurück', $viewer, 'de', 10);   // SearchResult

$result->hits;                // SearchHit[]: slug, title, sectionPath, snippet, matchedField, score, isFallback
$result->total;               // number of hits returned (no pagination)
$result->rateLimited;         // true when the viewer is over the limit; hits is empty then
$result->retryAfterSeconds;   // seconds until the next allowed search, or null

use FinityLabs\LinCodex\Contexts\RequestContextDetector;

public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'codex' => [
            'prefix' => config('lin-codex.routes.api'),
            'context' => app(RequestContextDetector::class)->detect($request)->toArray(),
        ],
    ];
}

Schema::table('codex_articles', function (Blueprint $table) {
    $table->dropConstrainedForeignId('created_by');
    $table->dropConstrainedForeignId('updated_by');
    $table->foreignIdFor(User::class, 'created_by')->nullable()->constrained()->nullOnDelete();
    $table->foreignIdFor(User::class, 'updated_by')->nullable()->constrained()->nullOnDelete();
});

Schema::table('codex_article_revisions', function (Blueprint $table) {
    $table->dropConstrainedForeignId('user_id');
    $table->foreignIdFor(User::class, 'user_id')->nullable()->constrained()->nullOnDelete();
});

Schema::table('codex_media', function (Blueprint $table) {
    $table->dropConstrainedForeignId('uploaded_by');
    $table->foreignIdFor(User::class, 'uploaded_by')->nullable()->constrained()->nullOnDelete();
});

$ php artisan codex:revisions:prune --keep=5
Removed 42 revisions from 7 articles (keeping 5 per language).

$ php artisan codex:revisions:restore 118 --user=1
Restored revision 118 (de) of users/roles.
bash
php artisan vendor:publish --tag=lin-codex-migrations
php artisan migrate
bash
php artisan vendor:publish --tag=lin-codex-react
php artisan vendor:publish --tag=lin-codex-vue
bash
php artisan vendor:publish --tag=lin-codex-assets

$ php artisan codex:install
Installing lin-codex...

Publishing the config...
  Config published to config/lin-codex.php
Publishing the migrations...
  Migrations published
Running the package migrations...
  2026_09_05_000001_create_codex_articles_table ........ DONE
  ...
  Migrations complete
  Settings seeded (lin-codex group, 10 revisions kept per language)
  AI settings seeded (lin-codex-ai group, AI translation off)
Re-indexing translations...
  0 translations indexed
  In-memory index rebuilt with 0 documents

lin-codex installed.

+-------------------------------+------------------------------------------------------------------------------------------+
| Next steps                    | Details                                                                                  |
+-------------------------------+------------------------------------------------------------------------------------------+
| Add the styles                | <x-lin-codex::styles /> in <head>                                                        |
| Add the button and the drawer | <x-lin-codex::help-button /> anywhere, <x-lin-codex::help-drawer /> once before </body>  |
| Write the first article       | php artisan codex:make intro --title="Introduction" (resources/codex/en/ is created for you) |
| Translate with AI             | composer 

$ php artisan codex:export --path=/tmp/codex-export
+--------+---------+---------+---------+--------+
| Locale | Created | Updated | Skipped | Failed |
+--------+---------+---------+---------+--------+
| de     | 3       | 0       | 0       | 0      |
| en     | 6       | 0       | 0       | 0      |
+--------+---------+---------+---------+--------+

$ php artisan codex:reindex
Re-indexing translations...
  14 translations indexed
  In-memory index rebuilt with 6 documents