Viewi Laravel integration
You can find all files here:
github.com/ivanvoitovych/viewi-laravel-example
Create Laravel project
composer create-project laravel/laravel app
Install viewi
composer require viewi/viewi -W
Please notice -W
here to resolve some versions conflicts.
Create Viewi app
Use -a
parameter.
vendor/bin/viewi new -a
Run web-server
php -S localhost:8000 -t public/
Run NPM watch
In another terminal.
cd viewi-app/js
npm run watch
Implementation details
Viewi routing
routes\web.php
Integrates Viewi routing.
You must remove a default /
route and allow Viewi to handle your home page.
<?php

use App\ViewiLaravel\ViewiLaravelBridge;
use Illuminate\Support\Facades\Route;
use Viewi\App;
use Viewi\Router\ComponentRoute;
use Illuminate\Http\Request;
use Viewi\Bridge\IViewiBridge;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

function setUpViewi()
{
 /**
 * @var App
 */
 $app = require __DIR__ . '/../viewi-app/viewi.php';
 require __DIR__ . '/../viewi-app/routes.php';
 $viewiRouter = $app->router();
 $bridge = new ViewiLaravelBridge($app);
 $app->factory()->add(IViewiBridge::class, function () use ($bridge) {
 return $bridge;
 });

 Route::fallback(static function (Request $request) use ($app, $viewiRouter) {
 $urlPath = $request->path();
 $requestMethod = $request->method();
 $match = $viewiRouter->resolve($urlPath, $requestMethod);
 if ($match === null) {
 throw new Exception('No route was matched!');
 }
 /** @var RouteItem */
 $routeItem = $match['item'];
 $action = $routeItem->action;

 if ($action instanceof ComponentRoute) {
 $viewiRequest = new Viewi\Components\Http\Message\Request($urlPath, strtolower($requestMethod));
 $viewiResponse = $app->engine()->render($action->component, $match['params'], $viewiRequest);
 if ($routeItem->transformCallback !== null && $viewiResponse instanceof Viewi\Components\Http\Message\Response) {
 $viewiResponse = ($routeItem->transformCallback)($viewiResponse);
 }
 $laravelResponse = response($viewiResponse->body, isset($viewiResponse->headers['Location']) ? 302 : $viewiResponse->status, $viewiResponse->headers);
 return $laravelResponse;
 } else {
 throw new Exception('Unknown action type.');
 }
 });
}

setUpViewi();
API routes
routes\api.php
You should use JsonResponse
in order to supply typed response to Viewi component.
You must use Viewi model classes defined within Viewi application, use mapping if necessary.
<?php

use Components\Models\PostModel;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
 return $request->user();
});

Route::get('posts/{id}', function (string $id) {
 $postModel = new PostModel();
 $postModel->Id = (int) $id;
 $postModel->Name = 'Laravel ft. Viewi';
 $postModel->Version = 1;
 return new JsonResponse($postModel);
});
Laravel bridge
app\ViewiLaravel\ViewiLaravelBridge.php
This allows you to handle internal requests during server-side rendering (SSR).
<?php

namespace App\ViewiLaravel;

use Illuminate\Http\JsonResponse;
use Viewi\Bridge\DefaultBridge;
use Illuminate\Http\Request;
use App\Http\Kernel;

class ViewiLaravelBridge extends DefaultBridge
{
 public function request(\Viewi\Components\Http\Message\Request $request): mixed
 {
 if ($request->isExternal) {
 return parent::request($request);
 }
 $laravelRequest = Request::create($request->url, strtoupper($request->method), [], $_COOKIE, [], $_SERVER, $request->body);
 $kernel = resolve(Kernel::class);
 $response = $kernel->handle($laravelRequest);
 if ($response instanceof JsonResponse) {
 return $response->original;
 } else {
 /** @var Response $response */
 return $response->getContent();
 }
 }
}
Now, when you navigate to the localhost:8000
, you will see your Viewi application.
Thanks and feel free to review, ask questions, contribute in any way.