Example of API with Vue.js in iluminar/goodwork

File app/Office/Controllers/OfficeController.php (link to Github)
use App\Office\Models\Office;

class OfficeController extends Controller
{
    //
    public function show(Office $office)
    {
        if ($office->notOpenForPublic()) {
            return redirect('login');
        } elseif (auth()->user()) {
            $this->authorize('view', $office);
            auth()->user()->setAppends(['unread_direct_messages']);
        }
        $office->load('members:user_id,username,avatar,name', 'settings', 'tags:tag_id,label');

        if (request()->expectsJson()) {
            return response()->json([
                'status'        => 'success',
                'office'        => $office,
                'current_cycle' => $office->current_cycle,
            ]);
        }

        return $this->formatRedirect();
    }
    //
}
File resources/assets/js/store/office.js (link to Github)
export default {
  state: {
    loading: false,
    office: null
  },
  //
  actions: {
    async getOffice ({ dispatch, commit }, officeId) {
      commit('toggleLoading', true)
      await axios.get(
        'offices/' + officeId
      )
        .then((response) => {
          if (response.data.status === 'success') {
            commit('getOffice', response.data.office)
            commit('setResourceName', response.data.office.name)
            dispatch('getMembers', response.data.office.members)
            dispatch('selectCycle', response.data.current_cycle)
            commit('toggleLoading', false)
          }
        })
        .catch((error) => {
          commit('toggleLoading', false)
          this.dispatch('showNotification', { type: error.response.data.status, message: error.response.data.message })
        })

      dispatch('setCurrentView', 'office')
    },
    //
  }
}
File app/Office/routes.php (link to Github)
use Illuminate\Support\Facades\Route;

Route::middleware('web')->group(function () {
    Route::get('offices/{office}', [OfficeController::class, 'show']);
    //
}
//
File resources/assets/js/components/home/offices.vue (link to Github)
<template>
<div>
        //
        <p class="py-2">
          <label for="title" class="text-sm text-gray-700">{{ 'Title' | localize }}</label>
          <input name="title" ref="focusInput" class="w-full appearance-none border rounded mt-2 py-2 px-3 text-gray-800" type="text" v-model="name">
          <span class="hidden"></span>
        </p>
        <p class="py-2">
          <label for="description" class="text-sm text-gray-700">{{ 'Description' | localize }}</label>
          <textarea name="description" id="" cols="30" rows="2" v-model="description" class="w-full appearance-none resize-none border rounded mt-2 py-2 px-3 text-gray-800"></textarea>
          <span class="hidden"></span>
        </p>
        //
</div>
</template>

<script>
//
  created () {
    this.getAllOffices()
  },
  computed: mapState({
    offices: state => state.offices
  }),
  methods: {
    ...mapActions([
      'getOffices',
      'addOffice'
    ]),
    getAllOffices () {
      if (this.offices.length < 1) {
        this.getOffices()
      }
    },
    //
  }
}
</script>

Additional resources on API with Vue.js: