Views & Templating
Larastvel uses Tera for templating with Blade-style convenience directives.
Configuration
Configure the view engine in config/view.toml:
engine = "tera"
paths = ["resources/views"]Rendering Views
use larastvel_core::view::ViewFactory;
let factory = ViewFactory::new(&config);
let html = factory.render("welcome", &ctx).await?;Or use the view shorthand on routes:
router.view("/welcome", "welcome");Blade-Style Directives
Tera templates support Blade-inspired directives:
<!-- resources/views/layouts/app.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}Larastvel{% endblock %}</title>
</head>
<body>
@auth
<p>Welcome, {{ user.name }}</p>
@endauth
@guest
<p>Please <a href="/login">log in</a></p>
@endguest
@csrf
@method('PUT')
{% block content %}{% endblock %}
@error('email')
<p>{{ message }}</p>
@enderror
</body>
</html>Supported directives: @auth, @endauth, @guest, @endguest, @csrf, @method, @error, @enderror.
Components & Slots
Laravel-style components with named slots (Laravel's x-slot). Three syntaxes are equivalent:
<!-- resources/views/components/card.html -->
<section>
<h1>{{ title }}</h1>
<aside>{{ header }}</aside>
<p>{{ slot }}</p>
</section><!-- x-component syntax -->
<x-card title="Stats">
<x-slot:header>Welcome {{ user.name }}</x-slot>
Body content
</x-card>
<!-- classic @component syntax -->
@component('components/card.html', { title: "Stats" })
@slot('header') Welcome {{ user.name }} @endslot
Body content
@endcomponentBoth render components/card.html with title, header, and slot (the default, unnamed body) variables available. Slot content is compiled and rendered with the page context before being passed to the component — so {{ user.name }} inside a slot works.
Self-closing components are supported: <x-icon name="heart" />.
Class-style components implement the Component trait:
use larastvel_core::{Component, ViewFactory};
use std::collections::HashMap;
struct Alert { title: String }
impl Component for Alert {
fn view(&self) -> &str {
"components/alert.html"
}
fn data(&self) -> HashMap<String, serde_json::Value> {
HashMap::from([("title".into(), serde_json::json!(self.title))])
}
}
let html = factory.render_component(&alert, ctx).await?;Components are non-nested: slot/component blocks end at the first closing tag (same linear limitation as the directive compiler).
Vite Asset Bundling
Larastvel integrates with Vite via the manifest file:
use larastvel_core::support::Vite;
let tags = Vite::asset("resources/js/app.js");
// Generates <script> and <link> tags from manifestConfigure Vite in your project root with a vite.config.js.