Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Project Setup

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.

Welcome back you beautiful front-end JavaScript people! In part 1 of our Vue series, we learned a ton of Vue basics and lots more. Now it's time to go further: to get into the nitty-gritty details of building a real app with products, a shopping cart, and a simple checkout form. Whoa. So let's get right down to business.

To truly embrace the Vue goodness, you should definitely download the course code from this page and code along with me. After you unzip the file, you'll find a start/ directory with the same code that you see here. Check out this README.md file for all of the setup instructions.

Starting the symfony Web Server

One of the last steps will be to find a terminal, move into the project and use the symfony binary as an easy way to start a local web server. Do it with:

symfony serve --allow-http -d

The -d is so that it runs as a daemon in the background. It starts a web server at that supports HTTPS or HTTP. I added the --allow-http flag because using HTTP makes it a bit easier to work with the webpack dev-server, which we'll use in a second. We talked about that in the previous tutorial including details on how to use the web server with https.

Anyways, let's go check out the site! Go to

Executing the Encore dev-server

And say hello to... a giant error! Ok, good start! Our site uses Webpack Encore to build its assets... and I have not executed Encore yet.

No problem: back at the terminal, run:

yarn dev-server

This starts another server that will host our compiled CSS and JS files. I like using this because parts of our page will automatically update without us needing to reload. Again, we talked more about this in part 1. If the dev-server gives you any trouble, just use yarn watch instead.

Hello MVP Office Supplies

Now when we refresh... woohoo! Welcome to MVP Office Supplies: our site to sell "mostly functional" office supplies to startups that truly embrace the minimum viable product mentality. All of these products are... barely viable.

Our app is not a single page application: it's designed to use normal server-side-rendered pages for most of the site. We're using Vue just to build a section of our app: this product listing page and, soon, a product show page, shopping cart and checkout.

In the section that's powered by the Vue app, you can already click a category to go to another page. This loads the same Vue app, but filtered to that specific category. We're not using something like Vue Router to avoid full page refreshes, but we will in a future tutorial. It's totally optional.

In our code, all of the logic lives in the assets/ directory and it's organized there into more folders, including one that holds the top-level component for our one page and components/ to hold different small - and sometimes re-usable - pieces. We also have helpers/ and services, which mostly holds AJAX logic. I did reorganize this slightly after part 1 to match the latest standards for organizing JavaScript in a Symfony app.

Ok: for our first mission, it's time to allow a user to click this link and view an individual product page. Will that page be a traditional server-side rendered page? Another Vue app? The same Vue app? Something written in ColdFusion? 3 of those are valid options! Let's talk about them and choose one next.

Leave a comment!

Login or Register to join the conversation
Yannick Avatar
Yannick Avatar Yannick | posted 8 months ago | edited

Hey guys, thank you for this tutorial. Quick heads-up: For yarn watch to work node.js needs to be on version 16. With later versions, e.x. 18 or so the following error appears:

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:71:19)
    at Object.createHash (node:crypto:133:10)
    at module.exports (C:\...\Vue.js\Vue2\start\node_modules\webpack\lib\util\createHash.js:135:53)
    at NormalModule._initBuildHash (C:\...\Vue.js\Vue2\start\node_modules\webpack\lib\NormalModule.js:417:16)
    at handleParseError (C:\...\Vue.js\Vue2\start\node_modules\webpack\lib\NormalModule.js:471:10)
    at C:\...\Vue.js\Vue2\start\node_modules\webpack\lib\NormalModule.js:503:5
    at C:\...\Vue.js\Vue2\start\node_modules\webpack\lib\NormalModule.js:358:12
    at C:\...\Vue.js\Vue2\start\node_modules\loader-runner\lib\LoaderRunner.js:373:3
    at iterateNormalLoaders (C:\...\Vue.js\Vue2\start\node_modules\loader-runner\lib\LoaderRunner.js:214:10)
    at Array.<anonymous> (C:\...\Vue.js\Vue2\start\node_modules\loader-runner\lib\LoaderRunner.js:205:4)
    at Storage.finished (C:\...\Vue.js\Vue2\start\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:55:16)
    at C:\...\Vue.js\Vue2\start\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:91:9
    at C:\...\Vue.js\Vue2\start\node_modules\graceful-fs\graceful-fs.js:123:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
1 Reply

Hey Yannick,

Thank you for this tip! Yeah, you need NodeJS v16 to make it work.



Hey, I cannot get the dev-server update the contents automatically. I even added the poll configuration like this in the end of webpack.config.js.

if (!Encore.isProduction()) {



config = Encore.getWebpackConfig();
config.watchOptions = {

poll: true,


module.exports = config;`

Any idea on how to solve this?


Hey Beo!

Hmm. Do you have any luck with yarn watch? I'm wondering if the problem is with the "watching" or something related to the dev-server (and if you're using Encore 1.0, that updated to a new major version of dev-server).

Btw, are you simply seeing that, when you change a file, nothing recompiles? Iirc, when you change a file, if you look a the terminal, you should see a message from dev server that it is "rebuilding".



Ciao Ryan!

yarn watch works, but the dev-server does not. Nothing changes in the terminal if I change any project file.

Is there a simple way to debug this?


Hey Beo!

Hmm, ok! Are you on Encore 1.0? Or still 0. something?

Do you need the watchOptions in order for yarn watch to work? Or does it work with standard config?

About the watchOptions, the dev-server has its own watch options. On Encore 1.0 (with webpack-dev-server 4), I'm 99% sure that the webpack-dev-server will re-use whatever watch options you have at the root level. But in Encore 0.33 (with webpack-dev-server 3), I'm less sure. If you're on that version, try using the standard way of setting the watch options:

    .configureWatchOptions(function(watchOptions) {
        watchOptions.poll = true;

In Encore 0.33 (and earlier), this will set this on the main watchOptions but also the webpack-dev-server options. In Encore 1.0, as I mentioned, I'm 99% sure that webpack-dev-server automatically uses the root watchOptions. And so, for that reason, Encore 1.0 only sets this config at the root level when you use this function.

I'm not sure of a good way to debug this other than to play around with the config!




I'm using Encore ^0.30.0, that I think resolves to 0.30.2, as specified in the code of the project (and also, same version of the Episode 1 of the tutorial).

I need those options for yarn watch to work, yes.

Should I try updating to Encore 1.0?


Hey Beo!

Should I try updating to Encore 1.0?

No, you don't need to do that... it's mostly just that 1.0 and 0.30.0 potentially work a bit different in this area - especially the dev-server. You could try upgrading to see if the new version of webpack-dev-server fixes it... but there is no guarantee. Because this is very odd behavior, I wasn't expecting it to happen on the old, very tried-and-tested Encore version :).

To answer your original question, I do not know of an easy way to debug this... it's usually something that just works :p. But, I do have 2 questions for you:

1) Why are you setting the poll option? This usually means you have some VM setup where you have a shared directory where the traditional watch mechanism doesn't work over a mount. What is your situation?

2) Did you try my suggestion of setting the watch options in the more traditional way for Encore? The key difference is that doing it this way explicitly sets the watchOptions for the root level config and also for the dev-server config:

    .configureWatchOptions(function(watchOptions) {
        watchOptions.poll = true;



Hey, answers below :)

0. I have a very basic setup: Mac OS with PHP 7.4 and nginx/php-fpm on the same machine. No docker or VM in the way. Node v10.

1. because if I don't even the yarn watch doesn't recompile. If I add the poll setting, it works.

2. ehm, sorry, I missed that! If I add that it works! I receive some warning during the startup regarding "Unhandled promise rejections are deprecated", but other than that, it works!

Thanks a lot!


Hey Pietro!

Woohoo! I can’t explain why you would need the polling with such a normal setup - that is a mystery! But I’m super glad it’s working :).



Note that, if you like me used the part 1 database, fixtures still need to be regenerated since they create the /uploads public folder.


Hey Pietro,

We always suggest our users to re-download the course source code for new episodes and start from the start/ folder instead of continue following it on the course code from the past episodes. The main reason is because we want to make thing very smooth to follow, that's why we almost always add some extra code between episodes: prepare some boilerplate code, upgrade dependencies to specific required versions, etc. If you want - you can continue following the same project from past episodes to follow new ones, but you should be ready for some minor difference or extra work.

I hope this helps!



Hi, thanks, but I did not start from the whole previous episode, just the db stayed the same, and the only missing thing were the missing pictures...

Abelardo Avatar
Abelardo Avatar Abelardo | posted 2 years ago

Hi there!
Do people who did the first part need to download this (new) code or is enough with the code we generated at this part 1?
Best regards.


Hey AbelardoLG,

We always recommend users to download the new course code from the next episodes and start from the start/ directory, because we almost always do some tweaks between the episodes: Preparing some boilerplate code, improving things, make some upgrades, etc. So if you will continue the project from the previous episode - it may slightly differ from the code in the new episode.

In short, you can continue your first project and follow the new episode on it, but you should be ready to some differences in the course code. So, my advice - download the new course code :)


1 Reply
Abelardo Avatar

Hey Victor,
It should be mentioned at your script in order to be noticed.


Hey AbelardoLG,

Agree, and we did mention it! :) Right in the 2nd paragraph on this page we do say that we recommend to download the course code from *this* page and code along with us ;)


Markus R. Avatar
Markus R. Avatar Markus R. | posted 3 years ago

Hi guys! I'm really excited about this tutorial! :)
I've got a question: when the page is loading (at 1:54-1:55) then first the layout appears (header & footer from base.html.twig) but the vue just a bit later. I have a feeling that twig is rendering faster than the vue component in this case (it's not waiting for it). Do I think right? Could you tell me what can we do against this issue? Does vue router help solving this?


Hi Gergo!

You are right. Basically the server rendered template will load, and then the Vue application will load and take the space.

Many applications on the internet resort to different loading mechanisms to make the user perceive that something is going on in the background before they can interact with the page. This can be easily done with just some css, where the Vue app can then replace whatever you do in the backgorund with the actual working App.

Hope this helps!

1 Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This course is also built to work with Vue 3!

What JavaScript libraries does this tutorial use?

// package.json
    "devDependencies": {
        "@fortawesome/fontawesome-free": "^5.15.1", // 5.15.1
        "@symfony/webpack-encore": "^0.30.0", // 0.30.2
        "axios": "^0.19.2", // 0.19.2
        "bootstrap": "^4.4.1", // 4.5.3
        "core-js": "^3.0.0", // 3.6.5
        "eslint": "^6.7.2", // 6.8.0
        "eslint-config-airbnb-base": "^14.0.0", // 14.2.0
        "eslint-plugin-import": "^2.19.1", // 2.22.1
        "eslint-plugin-vue": "^6.0.1", // 6.2.2
        "regenerator-runtime": "^0.13.2", // 0.13.7
        "sass": "^1.29.0", // 1.29.0
        "sass-loader": "^8.0.0", // 8.0.2
        "vue": "^2.6.11", // 2.6.12
        "vue-loader": "^15.9.1", // 15.9.4
        "vue-template-compiler": "^2.6.11", // 2.6.12
        "webpack-notifier": "^1.6.0" // 1.8.0