Laravel NavigationLightweight Ctrl+Hover preview + Ctrl+Click (Go to Definition) for Laravel projects in VS Code / Cursor. No PHP process. No Artisan. No background indexing. No file watchers.
ScreenshotsHover preview card with brand (laravel-navigation 1.0.1) and a feedback link:
Table of contents
1. Why this extensionMany Laravel helpers ( Heavy extensions (e.g. Laravel Extra Intellisense) boot your app via PHP in the background and can freeze the machine. laravel-navigation solves navigation with:
2. InstallFrom Marketplace (recommended)
Or from the command line:
After install: From VSIX
Then Extensions →
From source (Extension Development Host)
Press F5 → open a Laravel app in the new window. Disable conflicting heavy toolsIf the IDE hangs, disable Laravel Extra Intellisense (it spawns PHP against your app). Keep PHP Intelephense for generic PHP / vendor IntelliSense; this extension focuses on Laravel string + convention navigation. 3. Quick start
4. Hover cardEach successful resolve shows a hover card:
Click the filename in the card → opens the target in a new editor tab at the right line. 5. Supported navigation (full list)5.1 Models
5.2 Views / Blade
5.3 Config
Hover: shows resolved Value (literal, or value of 5.4 Env
Hover: shows Value: from 5.5 Routes (named / reverse)
Find All References (Shift+F12) on a route name: finds usages in 5.6 Controllers
5.7 Classes, services, traits, Illuminate
5.8 Laravel conventions
5.9 Methods on
|
| You write | Opens |
|---|---|
$this->filters() |
function filters in same class (or parent extends, 1 level) |
self::foo() / static::bar() |
same |
$request->keywordsList() when StoreRuleRequest $request |
method on that class |
5.10 Eloquent relations
| You write | Opens |
|---|---|
$user->posts / $user->posts() when $user is typed as a Model |
Related model (e.g. Post) by reading posts() body for hasMany(Post::class) etc. |
| If related class not found | Falls back to the relation method on the owner model |
Supported relation helpers (parsed):
belongsTo, belongsToMany, hasOne, hasMany, hasManyThrough, hasOneThrough, morphTo, morphOne, morphMany, morphToMany, morphedByMany, …
5.11 Assets, Vite, translations
| You write | Opens |
|---|---|
asset('js/app.js') / secure_asset('…') |
public/js/app.js (fallbacks: public/build/…, resources/…) |
@vite('resources/js/app.js') |
that path under project root |
@vite([..., 'resources/css/app.css']) |
hover the string → that entry file |
__('messages.welcome') / trans() / @lang() / Lang::get() |
lang/{locale}/messages.php or resources/lang/... |
JSON lang __('Hello') |
lang/en.json (best-effort) |
Locale is taken from config('app.locale') / fallback_locale when readable; otherwise en.
6. Behaviour details
Laravel root detection
Walks up from the current file (max depth 12) looking for:
artisan, orcomposer.json+app/+config/
Result is cached per directory.
use import expansion
Short names like MetaWebhookService are expanded via top-of-file use App\Services\MetaWebhookService; (first ~120 lines) before path resolve.
Env / config values
.envparsed with size cap; comments / quotes handled simply.- Config nested keys use bracket-scope walking so
services.stripe.keydoes not match the wrong'key'. - If config value is
env('X')orenv('X', 'default'), hover shows the.envvalue (or default).
Route index
Scans routes/**/*.php (max 40 files), indexes ->name('…'), group name/prefix, and Route::resource / apiResource actions; caches by file mtimes.
7. Architecture
VS Code / Cursor
│ Hover / Ctrl+Click / Find References
▼
extension.ts
├── DefinitionProvider
├── HoverProvider (preview + value + feedback button)
└── ReferenceProvider (named routes only)
│
▼
detect/symbolDetector.ts → kind + value (+ member)
│
▼
resolve/resolveSymbol.ts → Location (+ displayValue)
│
├── resolvers/* (view, config, env, route, class, …)
├── laravel/psr4.ts, routeIndex.ts, project.ts
└── utils/* (cache, preview, fileFinder, phpHelpers)
Principle: detect cheaply on the current line → resolve with convention paths → only then optional capped reads.
8. Performance / lightweight rules
| Rule | Detail |
|---|---|
| Idle | No work (no watchers, no indexers, no PHP) |
| Trigger | Only hover / definition / references |
| No PHP spawn | Never runs php, artisan, or Composer CLI |
| Caches | LRU for locations, roots, .env, routes, PSR-4, previews |
| Caps | .env ≤ 256KB; config ≤ 128KB; route files ≤ 40; reference scan ≤ ~80 files; preview ≤ 8KB / 35 lines; controller walk ≤ 40 dirs / 200 files |
If the machine still hangs, check other extensions (Extra Intellisense, SonarLint) — not this one’s idle path.
9. Limitations
- Not a full PHP language server — complex type inference, generics, macros: use Intelephense.
$obj->method()only when$objtype is clear nearby (param hint /@var/new).- Relations need a real
function posts()body with*Many(*::class)etc.; magic attributes without methods may miss. - Config values that are multi-line arrays / complex expressions may not display a simple Value.
- Vendor resolve depends on
vendor/being installed (composer install). - Find References is only for named routes (not every symbol).
- Env / config hover shows the live value from
.env/ config. Treat that as local-only; do not share screenshots that include secrets.
10. Develop locally
npm install
npm run compile # tsc → out/
npm run watch # optional
npm run package # → laravel-navigation-1.0.1.vsix
Debug: F5 (launch config in .vscode/launch.json).
Requirements: Node 18+, VS Code / Cursor engines ^1.80.0.
11. Project structure
extension/
├── package.json
├── tsconfig.json
├── README.md ← this file
├── LICENSE
├── src/
│ ├── extension.ts # activate providers + commands
│ ├── detect/
│ │ └── symbolDetector.ts
│ ├── resolve/
│ │ └── resolveSymbol.ts
│ ├── providers/
│ │ ├── definitionProvider.ts
│ │ ├── hoverProvider.ts
│ │ └── referenceProvider.ts
│ ├── resolvers/
│ │ ├── modelResolver.ts
│ │ ├── viewResolver.ts
│ │ ├── configResolver.ts
│ │ ├── envResolver.ts
│ │ ├── routeResolver.ts
│ │ ├── controllerResolver.ts
│ │ ├── classResolver.ts
│ │ ├── localMethodResolver.ts
│ │ ├── relationResolver.ts
│ │ └── assetLangResolver.ts
│ ├── laravel/
│ │ ├── project.ts # find artisan root
│ │ ├── paths.ts
│ │ ├── psr4.ts # app + vendor Illuminate
│ │ └── routeIndex.ts
│ └── utils/
│ ├── cache.ts # LRU
│ ├── fileFinder.ts
│ ├── phpHelpers.ts
│ └── preview.ts
└── out/ # compiled JS
12. Troubleshooting
| Problem | What to try |
|---|---|
| Nothing on hover | Confirm extension enabled; file language is php or blade; Reload Window |
| Env value missing | .env exists at Laravel root; key spelling matches |
| Illuminate classes miss | Run composer install; check vendor/laravel/framework |
| Wrong jump | Check use import / FQCN; nested modules may need path conventions |
| High CPU | Disable Laravel Extra Intellisense; this extension does not spawn PHP |
| Old behaviour | Reinstall VSIX with --force and Reload Window |
13. Roadmap
Possible later (still lightweight):
- More Blade directives (
@push,@error, …) - Livewire / Volt component jump
- Policy method ↔ model ability mapping
- Optional mask for secret env values in hover


