A first AML View project should teach the framework by producing a useful result immediately. In this guide, you will create a small reactive reading list, understand every generated folder, and see which work happens on the server and which work continues in the browser.
1. Check the CLI
AML includes the runtime required to create and serve a PHPAML project. Confirm the installed version before starting.
aml versionThis guide targets PHPAML 1.7.0-beta.22 or a newer compatible build. If your version is older, update AML first so the generated application contains the current View structure and runtime.
2. Create the application
Move to the directory where you keep projects, then create a new AML View application.
cd ~/Desktop
aml create-view-app reading-list
cd reading-list
aml serveThe development server starts at http://127.0.0.1:8910. If that port is already occupied, AML selects 8911, then 8912, without asking you to stop another project.
3. Read the generated structure
The generated project separates code you own from runtime code managed by AML.
reading-list/
├── public/
│ └── index.php
├── routes/
├── src/
│ ├── controllers/
│ ├── models/
│ └── views/
│ ├── pages/
│ ├── components/
│ ├── layouts/
│ ├── stylesheets/
│ └── assets/
├── runtime/
├── .env
└── phpaml.jsonpublic is the web entry point. Your declarative interface belongs in src/views. Controllers and models remain available when the frontend needs application logic or persistence. Generated caches, downloaded packages and internal configuration stay in runtime.
4. Build a reactive page
Open the home page in src/views/pages and replace its body with a small reading-list interface.
final class Home extends Page
{
#[State]
public array $books = ['Clean Code', 'Refactoring'];
#[State]
public string $title = '';
#[Computed]
public function total(): int
{
return count($this->books);
}
public function body(): View
{
return VStack(
Heading('My reading list')->size(44)->bold(),
Text("{$this->total()} books ready to read"),
TextField('Book title')
->value($this->title)
->onInput(fn (string $value) => $this->title = $value),
Button('Add book')->onClick(function (): void {
$title = trim($this->title);
if ($title === '') return;
$this->books[] = $title;
$this->title = '';
}),
ForEach(
$this->books,
fn (string $book) => Text($book)->class('book-row')
)
)->gap(16)->padding(40);
}
}State holds values that can change. Computed derives information from that state. Button and TextField declare browser interactions. ForEach renders a collection without mixing HTML tags into the page.
5. Add styles without touching public
Create src/views/stylesheets/pages/home.css. AML View discovers stylesheets recursively, so you can organize them by page, component or feature.
.book-row {
padding: 14px 16px;
background: #f4f3ee;
color: #17181c;
font-weight: 650;
}Use classes explicitly with ->class(). Keep directly addressable files such as favicon, robots.txt and sitemap.xml in public. Interface styles and imported images belong under src/views.
6. Understand what happens after a click
PHP renders the first document on the server. AML Engine activates declared interactions in the browser. Adding a book updates the relevant interface state without requesting a complete page render from the server.
This boundary is deliberate: View describes the interface, Engine handles client reactivity, Framework can serve backend routes, and Data can persist entities when the project needs durable storage.
7. Verify the result
Try adding an empty title: nothing should be inserted. Add three books and confirm that the computed total changes each time. Reload the page and observe that the list returns to its initial value because this first example uses local state only.
That last observation gives you the next useful exercise: create a Book model with PHPAML Data, load books through a controller or API route, and keep the same declarative View.
In summary
In a few minutes, you created a structured PHP application, rendered a declarative page, handled input, updated a collection, used computed state and organized page-specific CSS. You also saw the central PHPAML principle: each package has a clear job, and an application adopts only the layers it needs.