Symfony UX

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Hey friends! I sure am glad you're here for part 1 of our 2 part Symfony UX series.

HTML Build on the Server or in JavaScript

But what is this Symfony UX thing anyways? That requires... a short - and I promise thrilling - history lesson. Until a few years ago, the web worked one way: your server - like our Symfony app - created HTML and sent it to the user. Then, we usually sprinkled some JavaScript on top.

Then, frontend frameworks came along with a totally new paradigm where your server returns JSON and the HTML is built on the client side in JavaScript. Taken to the extreme, you get single page applications.

And so, it seemed that the world was destined to keep moving in this direction: to use frontend frameworks to generate HTML. After all, isn't the user experience of a single page app way better? With its lack of page refreshes and instant updates?

Hello Hotwire

But a storm was growing - a movement in the other direction. One, that's all about doing what we did 5 years ago: generating HTML on the server.

This exploded in 2020 when DHH and company - creator of Ruby on Rails and Basecamp - built a new email service entirely with server-side generated HTML. Their claim was bold: that they could get a single page application experience by building a traditional app.

They called the idea Hotwire. Symfony UX is built on top of this concept.

Hotwire: Stimulus & Turbo

Ok: so what does this mean for us? Having a beautiful & interactive user interface requires two things. First, we need a way to write professional JavaScript... not 1000 line long jQuery files, or one-off scripts. And we need that JavaScript to work... even if we load some HTML via AJAX. That's a classic problem with JavaScript: behavior isn't necessarily applied to HTML elements that arrive on the page later.

This is all solved with Stimulus: a tiny JavaScript library and the topic of this tutorial.

The second part of a rich user interface is being able to avoid full page refreshes. That's handled by Turbo: the topic of the next tutorial.

Put Stimulus and Turbo together and suddenly you can write clean JavaScript that always works and have a site where every link click and form submit loads via AJAX. So basically: the single page application experience... without the hassle of building a single page application.

And if you're wondering: does this kill frontend frameworks like React or Vue? Nope! Though, you'll probably use them less, if ever. Later in the tutorial we'll render a React component inside of Stimulus and talk about when and why you might do that.

Project Setup

So... let's get this party started! This stuff is super fun so I recommend coding along with me. Download the course code from this page and unzip it. After you do, you'll find a start/ directory with the same code that you see here. Check out the README.md file for all the details you'll need to get the project running. This is a tutorial about JavaScript, but we're using a fully-featured Symfony app with a database.

The last step in the README will be to find a terminal, move into the project and start up the flux capacitor by running:

symfony serve -d

Don't worry: I programmed the time machine to not let us go back to 2020. This starts a local web server in the background. To see the site, we can run:

symfony open:local

Or, if you're less lazy, go to https://127.0.0.1:8000 and say hello to... MVP office supplies! Our office furniture startup for other startups that embrace the minimum viable product mentality. All of our products are guaranteed to be barely viable at best.

This is the same project we built in our Vue tutorial if you want to compare them.

Right now, the site is styled but it has absolutely zero JavaScript. It's a completely traditional app with full page reloads. Adding things to the cart like this is done by submitting a normal, boring form.

Even the CSS itself is just a static file that lives in public/styles/: it's not being processed in any way.

So next: let's install Webpack Encore and use it to get a basic JavaScript and CSS setup that will form the baseline for using Stimulus.

Leave a comment!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=7.2.5",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "1.11.99.1", // 1.11.99.1
        "doctrine/annotations": "^1.0", // 1.11.1
        "doctrine/doctrine-bundle": "^2.2", // 2.2.3
        "doctrine/doctrine-migrations-bundle": "^3.0", // 3.0.2
        "doctrine/orm": "^2.8", // 2.8.1
        "phpdocumentor/reflection-docblock": "^5.2", // 5.2.2
        "sensio/framework-extra-bundle": "^5.6", // v5.6.1
        "symfony/asset": "5.2.*", // v5.2.3
        "symfony/console": "5.2.*", // v5.2.3
        "symfony/dotenv": "5.2.*", // v5.2.3
        "symfony/flex": "^1.3.1", // v1.12.1
        "symfony/form": "5.2.*", // v5.2.3
        "symfony/framework-bundle": "5.2.*", // v5.2.3
        "symfony/property-access": "5.2.*", // v5.2.3
        "symfony/property-info": "5.2.*", // v5.2.3
        "symfony/proxy-manager-bridge": "5.2.*", // v5.2.3
        "symfony/security-bundle": "5.2.*", // v5.2.3
        "symfony/serializer": "5.2.*", // v5.2.3
        "symfony/twig-bundle": "5.2.*", // v5.2.3
        "symfony/ux-chartjs": "^1.1", // v1.1.0
        "symfony/validator": "5.2.*", // v5.2.3
        "symfony/webpack-encore-bundle": "^1.9", // v1.11.1
        "symfony/yaml": "5.2.*", // v5.2.3
        "twig/extra-bundle": "^2.12|^3.0", // v3.2.1
        "twig/intl-extra": "^3.2", // v3.2.1
        "twig/twig": "^2.12|^3.0" // v3.2.1
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.0
        "symfony/debug-bundle": "^5.2", // v5.2.3
        "symfony/maker-bundle": "^1.27", // v1.28.0
        "symfony/monolog-bundle": "^3.0", // v3.6.0
        "symfony/stopwatch": "^5.2", // v5.2.3
        "symfony/var-dumper": "^5.2", // v5.2.3
        "symfony/web-profiler-bundle": "^5.2" // v5.2.3
    }
}

What JavaScript libraries does this tutorial use?

// package.json
{
    "devDependencies": {
        "@babel/preset-react": "^7.0.0", // 7.12.13
        "@symfony/stimulus-bridge": "^2.0.0", // 2.0.0
        "@symfony/ux-chartjs": "file:vendor/symfony/ux-chartjs/Resources/assets", // 1.1.0
        "@symfony/webpack-encore": "^1.0.0", // 1.0.4
        "bootstrap": "^4.6.0", // 4.6.0
        "core-js": "^3.0.0", // 3.8.3
        "react": "^17.0.1", // 17.0.1
        "react-dom": "^17.0.1", // 17.0.1
        "regenerator-runtime": "^0.13.2", // 0.13.7
        "stimulus": "^2.0.0", // 2.0.0
        "stimulus-use": "^0.22.1", // 0.22.1
        "sweetalert2": "^10.13.0", // 10.14.0
        "webpack-bundle-analyzer": "^4.4.0", // 4.4.0
        "webpack-notifier": "^1.6.0" // 1.13.0
    }
}