Your First Page - Step 2

Build your first Thorm page and learn the basic workflow: structure, state, and rendering mode.

The controller

Let's create the controller, the file that puts toghether all the code and builds the final output.

PHP
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; use function Thorm\{cls, el, fragment, state}; use App\Components\Contact; use App\Components\Header; use App\Components\Hero; use Thorm\Renderer; $app = fragment([ Header::get(), el('main', [ cls('mx-auto w-full max-w-6xl px-4 pb-10'), ], [ Hero::get(), Contact::get(), ]), ]);

This code defines the main node we render and, in turn, the HTML that appears on the page:

  • declare(strict_types=1); enables strict typing in PHP, so passing the wrong type will raise a TypeError instead of failing silently.
  • $app = fragment([...]); creates the root of our app. Since we're returning multiple top-level nodes, we use a fragment to group them without adding an extra wrapper element. Inside the fragment we define two nodes:
    • Header::get(), builds the header separately so it can be reused later.
    • A wrapper for the next two sections Hero::get(), and Contact::get(), both built independently to keep the file tidy and maintainable.
PHP
<?php ... $headScripts = '<script src="https://cdn.tailwindcss.com"></script> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Bangers&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet"> <link href="/tutorials/contact/public/style.css" rel="stylesheet">'; $renderer = new Renderer(); $res = $renderer->renderPage($app, [ 'title' => 'ACME HQ Contact', 'template' => file_get_contents(__DIR__.'/thorm/assets/index.tpl.html'), 'iruri_dir' => '/tutorials/contact/public/', 'headScripts' => $headScripts, 'iruri' => md5(__FILE__) . '.ir.json', 'runtime' => '/js/thorm/runtime/index.js', ], [ 'containerId' => 'app', ]); // save the IR bootstrap data $json_data = file_put_contents( __DIR__ . '/public/' . $res['iruri'], $res['irJson'] ); // save the page $html = file_put_contents( __DIR__.'/public/index.html', $res['tpl'] );

Next, we build the output and write it to disk. Right now, Thorm caches the rendered result on disk.

  • $headScripts defines the fonts, CSS, and any JavaScript you want to include. You can drop in widely used libraries such as Bootstrap, TailwindCSS, or Google Fonts. There are more elegant ways to manage assets, but for the scope of this tutorial a simple string is enough.
  • We then instantiate the Renderer class and render the page. $renderer->renderPage takes two arguments: the root node (here, $app) and an array of variables that will be injected into the HTML template.
  • The last two lines write the IR JSON and the final HTML output to disk.

The Final Code

Here is the final code.

PHP
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; use function Thorm\{cls, el, fragment, state}; use App\Components\Contact; use App\Components\Header; use App\Components\Hero; use Thorm\Renderer; $app = fragment([ Header::get(), el('main', [ cls('mx-auto w-full max-w-6xl px-4 pb-10'), ], [ Hero::get(), Contact::get(), ]), ]); $headScripts = '<script src="https://cdn.tailwindcss.com"></script> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Bangers&family=Nunito:wght@400;600;700&display=swap" rel="stylesheet"> <link href="/tutorials/contact/public/style.css" rel="stylesheet">'; $renderer = new Renderer(); $res = $renderer->renderPage($app, [ 'title' => 'ACME HQ Contact', 'template' => file_get_contents(__DIR__.'/thorm/assets/index.tpl.html'), 'iruri_dir' => '/tutorials/contact/public/', 'headScripts' => $headScripts, 'iruri' => md5(__FILE__) . '.ir.json', 'runtime' => '/js/thorm/runtime/index.js', ], [ 'containerId' => 'app', ]); // save the IR bootstrap data $json_data = file_put_contents( __DIR__ . '/public/' . $res['iruri'], $res['irJson'] ); // save the page $html = file_put_contents( __DIR__.'/public/index.html', $res['tpl'] );
Status: Developer Preview
Things may change, things might break. If something feels awkward, it's probably a design edge we're still smoothing out.