Skip to content

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:

Laravel API Setup

  1. Create a new Laravel application

  2. Install Laravel Breeze using the API Stack option

  3. 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"
  4. Create controllers

    bash
    php artisan make:controller ProfileController
    bash
    php artisan make:controller PasswordController
  5. 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();
        }
    }
  6. Setup routes

    php
    Route::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');