Create components. Use them as HTML tags.
Make a Blog component by creating HTML and PHP files with the same name.
That pair of files would be your <Blog /> component.
Combine components to build pages and applications.
Make a package and share with others.
class Blog extends BaseComponent
{
 public BlogModel $blog;
}
Blog.php
<div>
 <Thumbnail blog="$blog" />
 <a href="{$blog->url}">
 <h3>{$blog->title}</h3>
 <p>{$blog->description}</p>
 </a>
 <LikeButton blog="$blog" />
</div>Blog.html
Templates are fluent and easy to use.
The syntax is a mix of HTML and PHP expressions. The component's properties are available as variables.
Special tags allow you to build lists and conditions, for example, "foreach" or "if".
Use methods as functions to render computed expressions. Like "heading()".
class BlogsSection extends BaseComponent
{
 public array $blogs;
 public string $emptyHeading = 'No posts in here';

 public function heading()
 {
 $heading = $this->emptyHeading;
 $total = count($this->blogs);
 if ($total > 0) {
 $noun = $total > 1 ? 'Posts' : 'Post';
 $heading = "$total $noun";
 }
 return $heading;
 }
}
BlogList.php
<section>
 <h2>{heading()}</h2>
 <Blog foreach="$blogs as $blog" blog="$blog" />
</section>BlogList.php
Your components are reactive automatically.
Interactivity is an important part of any modern application.
Use event binders to respond to the user's actions. And Viewi will update the page with new data.
For example, (change)="search" will call the "search" method every time the user types something in the field.
class SearchableBlogList extends BaseComponent
{
 public string $title = "News and articles";
 public array $blogs;
 public array $foundBlogs = [];
 public string $searchText = '';

 public function __construct(
 private BlogService $blogService
 ) {}

 public function init()
 {
 $this->watch('blogs', function () {
 $this->searchText = '';
 $this->search();
 });
 }

 public function mounted()
 {
 $this->search();
 }

 public function search()
 {
 $this->foundBlogs = $this->blogService->filter(
 $this->blogs,
 $this->searchText
 );
 }
}
SearchableBlogList.php
<h3>$title</h3>
<p>Here is something that might interest you.</p>
<SearchInput model="$searchText" (change)="search" />
<BlogsSection 
 blogs="$foundBlogs" 
 emptyHeading="{"No matches for '$searchText'"}" 
/>SearchableBlogList.php
News and articles
Here is something that might interest you.
5 Posts
Integrate with API or backend.
Use HTTP client to get the data.
Assign your page to a specific URL using a built-in router.
Framework agnostic. Make integration with the backend framework of your choice.
class PopularBlogs extends BaseComponent
{
 public ?array $blogs = null;
 public string $category = 'today';

 public function __construct(
 private HttpClient $http
 ) {}

 public function init()
 {
 $this->getPosts();
 }

 public function getPosts()
 {
 $this->blogs = null;
 $this->http
 ->get("/api/blogs/{$this->category}")
 ->then(fn($blogs) => $this->blogs = $blogs);
 }

 public function open(string $category)
 {
 $this->category = $category;
 $this->getPosts();
 }

 public function getTitle()
 {
 return ($this->category === 'today'
 ? 'Today\'s' : 'This week\'s') . ' most popular posts';
 }
}
PopularBlogs.php
<BlogLayout> 
 <div>
 <button (click)="open('today')">Today</button>
 <button (click)="open('week')">This Week</button>
 </div>
 <Loading loading="{!$blogs}">
 <SearchableBlogList
 title="{getTitle()}"
 blogs="$blogs"
 />
 </Loading>
</BlogLayout>PopularBlogs.php
$router->get('/most-popular', PopularBlogs::class);routes.php
Today's most popular posts
Here is something that might interest you.
5 Posts
Embrace, not avoid
Viewi is not about avoiding JavaScript. It is about integrating them both for mutual benefits.
Read moreSEO friendly
Get fully rendered pages instantly without waiting for JavaScript.
Better user experience. Better metrics. Better everything.
Super intuitive
Viewi is a fully capable view framework that has components with its own state and comprehensive template syntax.
Learn more