Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e0eb9c5
feat: unit tests (#231)
blt950 Apr 26, 2026
28d390c
refactor: laravel cleanup (#232)
blt950 May 29, 2026
f3b5fda
fix: airbase aria-label
blt950 May 29, 2026
62405c6
feat: Navigraph link
blt950 May 29, 2026
a462d2a
fix: feedback nudge
blt950 May 30, 2026
0e37f78
fix: select multiple issue
blt950 Jun 19, 2026
cda98bd
refactor: bootstrap hacks
blt950 Jun 19, 2026
18d0eb9
chore(deps): sass and building
blt950 Jun 19, 2026
e059822
chore(deps): vite v8
blt950 Jun 19, 2026
af7f880
fix: package-lock.json
blt950 Jun 19, 2026
dd1ad25
fix: action.yaml
blt950 Jun 20, 2026
1298a24
feat: react 19 and cluster improvements (#239)
blt950 Jun 21, 2026
8e7d4a2
feat: updated theme (#240)
blt950 Jul 3, 2026
ca2ceb7
fix: packages
blt950 Jul 3, 2026
55c0dd9
Update .gitignore
blt950 Jul 3, 2026
64e6426
feat: claude groundwork
blt950 Jul 3, 2026
81267c5
feat: predictions (#241)
blt950 Jul 5, 2026
08af81c
fix: permission errors
blt950 Jul 7, 2026
262b596
feat: optimizations (#242)
blt950 Jul 8, 2026
46543e5
feat: distance filtering
blt950 Jul 8, 2026
831253e
fix: test
blt950 Jul 8, 2026
e0822fa
feat: close airport card
blt950 Jul 8, 2026
1e7b3e9
feat: aircraft filter in toplist
blt950 Jul 8, 2026
7612bd8
feat: distance, airport card and toplist (#243)
blt950 Jul 8, 2026
6dd1484
feat: graphify
blt950 Jul 8, 2026
c10483a
refactor: Countries, Score & AircraftHelper
blt950 Jul 8, 2026
07b00a1
feat: graphify
blt950 Jul 8, 2026
1cf1b12
refactor: score icon
blt950 Jul 8, 2026
7904c0a
Merge pull request #245 from blt950/v3
blt950 Jul 8, 2026
7646959
refactor: more native functions
blt950 Jul 8, 2026
3c3e4e7
fix: i don't know really, but doesnt make sense
blt950 Jul 8, 2026
19276df
refactor: useless use of moment.js
blt950 Jul 8, 2026
9bf52dc
feat: arrays to Umami 3.2.0
blt950 Jul 8, 2026
1f49e60
feat: umami slider reporting
blt950 Jul 8, 2026
e8aa31f
fix: uncomment breaking code
blt950 Jul 8, 2026
c25acca
feat: ping when click on airport
blt950 Jul 8, 2026
17e9d10
feat: scroll to selected airport
blt950 Jul 8, 2026
f615f4d
fix: ICAO not showing on route
blt950 Jul 8, 2026
94b888b
fix: clicking airport opens fold if needed
blt950 Jul 8, 2026
f5d0aa9
Merge pull request #244 from blt950/refactor/diet
blt950 Jul 8, 2026
54d45e4
fix: darkmode on feedback page
blt950 Jul 8, 2026
b296b36
fix: ignores
blt950 Jul 9, 2026
4b5445f
fix: line draw when airport card closed
blt950 Jul 9, 2026
bac7796
fix: dockerfile
blt950 Jul 10, 2026
49c5070
chore(deps): docker dependencies
blt950 Jul 10, 2026
c56e435
refactor: changed expanded form based on usage
blt950 Jul 13, 2026
cf98cf0
feat: TAF TEMPO/PROB weights less
blt950 Jul 15, 2026
5b79a4f
fix: show only unique bookings
blt950 Jul 15, 2026
114ce42
fix: stuck tooltips
blt950 Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"permissions": {
"allow": [
"Bash(graphify query *)",
"Bash(php artisan *)",
"Bash(node driver.mjs)",
"Bash(nohup php artisan serve --host=0.0.0.0 --port=8000)",
"Bash(timeout 20 bash -c 'until curl -sf http://127.0.0.1:8000/ >/dev/null; do sleep 1; done')",
"Bash(curl -s http://127.0.0.1:8000/)",
"Bash(npm run *)",
"Bash(php artisan tinker '--execute= *)"
]
}
}
177 changes: 177 additions & 0 deletions .claude/skills/laravel-13/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
---
name: laravel-13
description: This skill should be used when writing, reviewing, or upgrading PHP/Laravel backend code in a Laravel 13.x application. It should be used for Eloquent models, migrations, query builder code, routing/controllers, and when upgrading a Laravel 12 app to Laravel 13. Laravel 13 released March 17, 2026, after this model's training cutoff, so this skill's references/ files and live web-fetches to laravel.com/docs/13.x/* should be treated as ground truth over training-data memory of Laravel 12 or earlier.
---

# Laravel 13

Laravel 13 (released March 17, 2026) is an intentionally low-breakage major
release — most Laravel 12 apps upgrade with minimal code changes. It requires
**PHP 8.3+** and continues Laravel's shift toward first-party PHP attributes
for declarative configuration, alongside a new AI SDK, JSON:API resources,
and native vector search.

**Do not default to Laravel 12 patterns.** Where this skill's `references/`
files don't cover something, `web_fetch` the live docs at
`https://laravel.com/docs/13.x/<page>` (e.g. `/docs/13.x/eloquent`,
`/docs/13.x/validation`, `/docs/13.x/sanctum`) rather than guessing from
training data. The 13.x docs are the only ground truth for anything
attribute-related, AI SDK–related, or vector-search–related — these are new
enough that pre-2026 training data will be wrong or silently absent.

## Stack context

This is a PHP/Laravel-primary stack: Laravel handles routing, Eloquent
models, controllers, and Blade where server-rendered views are still used.
**React** is used for interactive frontend pieces (mounted into Blade via
Vite), and **SCSS** for styling. When editing frontend code inside a Laravel
app, keep API boundaries clean — Eloquent API resources (including the new
JSON:API resources, see below) are the contract React components consume.
Practically, that means: put data-shaping logic in a Resource class rather
than serializing models ad hoc in a controller, and treat a controller
method's return type as the actual frontend contract, not an implementation
detail — a React component and a Laravel resource should be able to change
independently as long as that contract holds. SCSS changes are orthogonal to
anything in this skill — Vite's asset pipeline doesn't change with the
framework's major version.

## What changed from Laravel 12 to 13

Full detail lives in `references/upgrade-12-to-13.md`. Highlights:

- **PHP 8.3 minimum** (was 8.2 in Laravel 12). Supported range is PHP 8.3–8.5.
- **CSRF middleware renamed**: `VerifyCsrfToken` → `PreventRequestForgery`,
now with origin-aware verification via the `Sec-Fetch-Site` header. Old
class names remain as deprecated aliases — update direct references
(`->withoutMiddleware([...])`, tests) to the new name.
- **`serializable_classes` cache hardening** (medium impact): `config/cache.php`
now defaults to blocking arbitrary PHP object unserialization from cache
unless explicitly allow-listed. If you cache PHP objects (not just arrays),
you must list those classes explicitly or you'll get silent deserialization
failures.
- **MySQL/MariaDB `upsert` validation**: an empty `uniqueBy` now throws
`InvalidArgumentException` instead of generating broken SQL.
- Several **low-impact renames**: `JobAttempted::$exceptionOccurred` →
`$exception` (now the actual exception object or `null`);
`QueueBusy::$connection` → `$connectionName`; pagination Bootstrap-3 view
names became explicit (`pagination::bootstrap-3`).
- Laravel Boost (`^2.0`) can drive the upgrade itself — the
`/upgrade-laravel-v13` slash command automates most of the mechanical work
if Boost is installed in the app.

For a real upgrade, don't stop at this summary — read
`references/upgrade-12-to-13.md` in full before touching `composer.json`.
It also lists a dozen low/very-low-impact contract additions and renames
(queue events, HTTP client method signatures, pagination view names, a
`symfony/polyfill-php85` global-function collision) that rarely bite but
are cheap to check for in a large codebase.

### New capabilities worth knowing about

- **Expanded PHP attributes across the framework.** Models can now be
configured with `#[Table]`, `#[Fillable]`, `#[Guarded]`, `#[Unguarded]`,
`#[Connection]`, `#[DateFormat]`, `#[WithoutTimestamps]`,
`#[WithoutIncrementing]`, `#[ScopedBy]` instead of (or alongside) the
traditional `protected $table`, `protected $fillable`, etc. properties.
Local query scopes now use `#[Scope]` on a `protected` method instead of a
`scopeXxx()`-prefixed public method. Controllers gained `#[Middleware(...)]`
and `#[Authorize(...)]` attributes as declarative alternatives to
route-file `->middleware()` calls and `can` middleware strings. See
`references/eloquent.md` and `references/routing.md` — **both the
attribute style and the older property/method style still work**, and
existing Laravel 12 code using the old style needs no changes.
- **`Queue::route(JobClass::class, connection: ..., queue: ...)`** — central,
class-based queue/connection routing instead of setting `$queue`/
`$connection` on every job or calling `->onQueue()` at every dispatch site.
- **`Cache::touch($key, $seconds)`** — extend a cache entry's TTL without
re-fetching and re-storing its value. Custom cache store implementations
must add a `touch` method to satisfy the `Store` contract.
- **`PreventRequestForgery`** (see upgrade notes above) — also exposes a
`preventRequestForgery(...)` method in the middleware configuration API.
- **JSON:API resources** — first-party support for the JSON:API spec
(resource objects, relationship inclusion, sparse fieldsets, links,
compliant headers) alongside existing Eloquent API resources. Fetch
`/docs/13.x/eloquent-resources#jsonapi-resources` for the exact class/method
names when building one — not covered in `references/` here since usage is
narrow and spec-driven.
- **Vector search** — `DB::table(...)->whereVectorSimilarTo('embedding', $vector, minSimilarity: 0.4)`
and related methods (`selectVectorDistance`, `whereVectorDistanceLessThan`,
`orderByVectorDistance`) for cosine-similarity search, PostgreSQL +
`pgvector` only. The vector argument can be a raw embedding array *or* a
plain string — Laravel will generate the embedding via the AI SDK
automatically. See `references/database.md`.
- **Laravel AI SDK** (`laravel/ai`, stable in 13) — provider-agnostic text
generation, tool-calling agents, image/audio generation, and embeddings
(`Str::of($text)->toEmbeddings()`). Fetch `/docs/13.x/ai-sdk` for anything
beyond the one-liner examples in the release notes — this is an entirely
new package, not an incremental change, so there's no prior-version
knowledge to fall back on.

### A quick taste of the attribute style

Since this is the single biggest day-to-day change, here's the shape before
diving into `references/eloquent.md` for the full attribute list. Both of
these are equivalent and both are valid Laravel 13 code — attributes don't
replace the property style, they're an alternative for models where
declaring config at the top of the class reads better than scattering it
across several `protected` properties:

```php
// Attribute style (new option in 13)
#[Table('flights', key: 'flight_id')]
#[Fillable(['name', 'destination'])]
class Flight extends Model {}

// Property style (still fully supported, what most 12.x code already has)
class Flight extends Model
{
protected $table = 'flights';
protected $primaryKey = 'flight_id';
protected $fillable = ['name', 'destination'];
}
```

Don't churn through an existing codebase converting property style to
attribute style — that's a cosmetic diff with no behavioral upside. Use
attributes for *new* models where they read more cleanly, and leave
existing 12.x-style models alone unless the user asks for a conversion.

## Where to look

| Need | File |
|---|---|
| Concrete upgrade diffs (12→13), what breaks / what's deprecated | `references/upgrade-12-to-13.md` |
| Model definitions (attribute vs. property style), relationships, scopes, casts, factories | `references/eloquent.md` |
| Query builder basics, migrations, transactions, vector search | `references/database.md` |
| Route definitions, controller attributes, route model binding, resources | `references/routing.md` |
| `Str`, `Arr`, `collect()`, `Http`, `Validator` quick reference | `references/common-helpers.md` |

If a task touches something not in this table (JSON:API resources, the AI
SDK, Sanctum, broadcasting, queues in depth, testing, etc.), `web_fetch` the
matching `https://laravel.com/docs/13.x/<topic>` page directly rather than
improvising from memory of Laravel 10/11/12 docs — the URL slugs are usually
the same as prior versions (`/docs/13.x/queues`, `/docs/13.x/validation`,
`/docs/13.x/sanctum`, `/docs/13.x/eloquent-relationships`, etc.).

## A note on confidence

Everything in the five `references/` files was pulled directly from the live
`laravel.com/docs/13.x/*` pages (plus the release notes and upgrade guide)
during this skill's creation, not reconstructed from training data. Code
examples in those files are the framework's own examples, not invented ones
— if a snippet looks slightly unusual (e.g. `now()->minus(months: 1)` instead
of the more familiar `now()->subMonth()`), that's very likely a genuine 13.x
API detail worth double-checking rather than a transcription slip, since
Laravel has been known to introduce named-argument-friendly method variants
across major versions.

That said, these five files are a curated subset — Eloquent relationships,
factories, custom cast classes, migrations column types, validation rules,
queues, broadcasting, testing, and the AI SDK/JSON:API resources were
deliberately **not** fully inlined here to keep `SKILL.md` and its
references lean and because their APIs are either unchanged from Laravel 12
(safe to reason about from memory, but verify anything unusual) or entirely
new (no safe memory to fall back on at all — must fetch). When a task needs
one of those, prefer a fresh `web_fetch` over confidence born from general
Laravel familiarity. It costs one tool call and eliminates an entire class
of "this was true in Laravel 11" mistakes.
143 changes: 143 additions & 0 deletions .claude/skills/laravel-13/references/common-helpers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Common Helpers & Facades Quick Reference (Laravel 13.x)

These APIs are stable across recent Laravel major versions — nothing here
is 13.x-specific except where noted (`Str::uuid7()`, `Str::of()->toEmbeddings()`).
Fetch `/docs/13.x/strings`, `/docs/13.x/helpers`, `/docs/13.x/collections`,
`/docs/13.x/http-client`, or `/docs/13.x/validation` directly for anything
not listed.

## `Str` (`Illuminate\Support\Str`)

| Method | Purpose |
|---|---|
| `Str::slug($title)` | URL-friendly slug |
| `Str::limit($str, 20)` | Truncate to length |
| `Str::random(32)` | Random string |
| `Str::uuid()` | UUIDv4 |
| `Str::uuid7()` | UUIDv7 (time-ordered, sortable — used by `HasUuids` by default) |
| `Str::ulid()` | ULID (compact, time-ordered) |
| `Str::plural($word)` / `Str::singular($word)` | Pluralize / singularize |
| `Str::camel($str)` / `Str::snake($str)` / `Str::kebab($str)` / `Str::studly($str)` | Case conversion |
| `Str::headline($str)` / `Str::title($str)` / `Str::apa($str)` | Title-casing variants |
| `Str::contains($haystack, $needle)` / `startsWith()` / `endsWith()` | Substring checks |
| `Str::replace($search, $replace, $subject)` | Replace |
| `Str::upper()` / `Str::lower()` | Case |
| `Str::password(32)` | Secure random password |
| `Str::isJson()` / `isUrl()` / `isUuid()` / `isUlid()` | Validity checks |
| `Str::after($subject, $search)` / `before()` / `between()` | Substring extraction |
| `Str::of($string)` | Fluent `Stringable` instance — chain `->trim()->slug()->limit(20)` etc. |

**New in 13 — AI SDK integration:**
`Str::of($text)->toEmbeddings()` generates vector embeddings directly from
a string via the Laravel AI SDK — pairs with `whereVectorSimilarTo` in
`references/database.md`. Fetch `/docs/13.x/ai-sdk#embeddings` for
provider/config details before using this in application code.

## `Arr` (`Illuminate\Support\Arr`)

Prefer `Arr::` methods over legacy global `array_*()` helpers, especially
`Arr::first()`/`Arr::last()` — Laravel 13 ships a PHP 8.5 polyfill
(`symfony/polyfill-php85`) that can define global `array_first()`/
`array_last()` with different (callback-less) semantics than
`laravel/helpers`' historical versions. See
`references/upgrade-12-to-13.md`.

```php
use Illuminate\Support\Arr;

Arr::get($array, 'products.desk.price', 0); // dot-notation get w/ default
Arr::set($array, 'products.desk.price', 200); // dot-notation set
Arr::has($array, 'products.desk');
Arr::only($array, ['name', 'email']);
Arr::except($array, ['password']);
Arr::first($array, fn ($value) => $value > 100); // callback supported
Arr::last($array);
Arr::flatten($array);
Arr::collapse($arrayOfArrays);
Arr::pluck($array, 'name');
```

## `collect()` / `Illuminate\Support\Collection`

```php
$collection = collect([1, 2, 3, 4]);

$collection->map(fn ($n) => $n * 2);
$collection->filter(fn ($n) => $n > 2);
$collection->reject(fn ($n) => $n > 2); // inverse of filter
$collection->reduce(fn ($carry, $n) => $carry + $n, 0);
$collection->groupBy('type');
$collection->pluck('name');
$collection->sortBy('name');
$collection->chunk(200);
$collection->each(fn ($item) => /* ... */ null);
```

Eloquent's `Collection` (returned by `->get()`, `::all()`) extends this
base class and adds model-specific helpers (`modelKeys()`, `load()`, etc.)
— see `references/eloquent.md`.

## `Http` (`Illuminate\Support\Facades\Http`)

```php
use Illuminate\Support\Facades\Http;

$response = Http::get('https://api.example.com/users');
$response = Http::post('https://api.example.com/users', ['name' => 'Steve']);

$response = Http::withToken($token)
->withHeaders(['X-Custom' => 'value'])
->timeout(10)
->retry(3, 100)
->post(/* ... */);

$response->json();
$response->status();
$response->successful();
$response->throw(); // throws on 4xx/5xx — signature is explicit in 13.x
```

## `Validator` / form validation

```php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
'title' => 'required|max:255',
'body' => 'required',
'email' => 'required|email|unique:users,email',
]);

if ($validator->fails()) {
return redirect('/create')
->withErrors($validator)
->withInput();
}
```

Controller-level convenience (throws `ValidationException` automatically,
302-redirects with errors on failure in a web context):

```php
$validated = $request->validate([
'title' => 'required|max:255',
'body' => 'required',
]);
```

For Form Request classes (`php artisan make:request StoreFlightRequest`)
and custom validation rule objects, fetch `/docs/13.x/validation` directly
— the class shape (`authorize()`, `rules()`) is unchanged from Laravel 12.

## React + SCSS stack notes

- Laravel API resources (`php artisan make:resource`) are the typical
contract between Eloquent models and React components — return
`SomeResource::collection($models)` or `new SomeResource($model)` from
controllers consumed by the frontend. New JSON:API resources (see
`SKILL.md`) are an alternative when the frontend needs JSON:API-shaped
responses specifically (sparse fieldsets, `included`, etc.) — not needed
for a plain internal API.
- SCSS compiles through Vite (`resources/sass` → `laravel-vite-plugin`),
unrelated to any Laravel 13 change — Vite/asset-pipeline config is
independent of the framework major version.
Loading
Loading