API / SPA Starter Kit
About
This starter-kit repository provides a Vue SPA (Single Page Application) that connects to a Laravel API backend, authenticated with Laravel Sanctum. The project provides the same authentication and profile pages/features as the Inertia starter-kit.
WARNING
Development time/resources are primary allocated to the main Inertia starter kit, this version will not receive any additional features beyond the standard User authentication and profile pages.
Vue SPA Setup
Clone from source repository:
bash
git clone https://github.com/connorabbas/laravel-api-primevue-starter-kit.git
bash
git clone git@github.com:connorabbas/laravel-api-primevue-starter-kit.git
Alternatively:
- Create a new repository using the public template on GitHub.
- Create a new fork on GitHub.
- Download the ZIP from GitHub.
Laravel API Setup
Create a new Laravel application
Install Laravel Breeze using the API Stack option
Setup necessary
.env
configuration values in the Laravel API project# Example implementation # Remember, your SPA and API must share the same top-level domain APP_URL=http://api.vue-spa.localhost # Match this value with VITE_API_BASE_URL in the Vue app FRONTEND_URL=http://vue-spa.localhost # Add app.frontend_url config entry as needed SANCTUM_STATEFUL_DOMAINS="vue-spa.localhost" SESSION_DOMAIN="vue-spa.localhost"
Create controllers
bashphp artisan make:controller ProfileController
bashphp artisan make:controller PasswordController
Copy Controller code
php<?php namespace App\Http\Controllers; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Auth; use Illuminate\Validation\Rule; use Illuminate\View\View; class ProfileController extends Controller { /** * Update the user's profile information. */ public function update(Request $request): Response { $validated = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'email' => [ 'required', 'string', 'lowercase', 'email', 'max:255', Rule::unique(User::class)->ignore($request->user()->id), ], ]); $request->user()->fill($validated); if ($request->user()->isDirty('email')) { $request->user()->email_verified_at = null; } $request->user()->save(); return response()->noContent(); } /** * Delete the user's account. */ public function destroy(Request $request): Response { $request->validate([ 'password' => ['required', 'current_password'], ]); $user = $request->user(); Auth::logout(); $user->delete(); $request->session()->invalidate(); $request->session()->regenerateToken(); return response()->noContent(); } }
php<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\Rules\Password; class PasswordController extends Controller { /** * Update the user's password. */ public function update(Request $request): Response { $validated = $request->validate([ 'current_password' => ['required', 'current_password'], 'password' => ['required', Password::defaults(), 'confirmed'], ]); $request->user()->update([ 'password' => Hash::make($validated['password']), ]); if ($request->session()->has('password_hash_web')) { $user = Auth::user(); $request->session()->forget('password_hash_web'); Auth::login($user); } return response()->noContent(); } }
Setup routes
phpRoute::controller(App\Http\Controllers\ProfileController::class) ->middleware('auth') ->group(function () { Route::patch('/profile', 'update')->name('profile.update'); Route::delete('/profile', 'destroy')->name('profile.destroy'); }); Route::put('password', [App\Http\Controllers\Auth\PasswordController::class, 'update']) ->middleware('auth') ->name('password.update');