Install Node with NVM

Installing Node with NVM prevents permission errors when installing NPM packages globally.

Install NVM.

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.9/install.sh | bash

Close, quit, and reopen the terminal.

Make sure it installed correctly.

nvm –version

Install and use the latest version of node.

nvm install node

nvm use node

Now, we can install npm packages globally without any permission errors and without using sudo.

npm install -g react-native-cli

Create Vagrant Box for Laravel (Using Nginx)

Set Up Ubuntu Vagrant Box

Find out what boxes are available vagrant box list Add the new newest Ubuntu box (currently xenial/16.04 LTS). vagrant box add envimation/ubuntu-xenial-docker https://atlas.hashicorp.com/envimation/boxes/ubuntu-xenial-docker Create a directory for the box and init the ubuntu box. cd ~/ mkdir testlar cd testlar vagrant init envimation/ubuntu-xenial-docker By default, Vagrant syncs the folder with the Vagrantfile in the host machine with the /vagrant folder in the virtual machine. Create a file called bootstrap.sh in the same folder as the Vagrant file and add the following.

#!/usr/bin/env bash

apt-get update

Include the bootstrap.sh file in the Vagrantfile.

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.provision :shell, path: "bootstrap.sh"
end

It is a good idea to allocate more memory to the virtual box. I got an error when trying to set up the Laravel project. Add this to the Vagrantfile.

  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #   vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
    vb.memory = "2000"
  end

Allow port forwarding to view web pages using the server we just set up. config.vm.network :forwarded_port, guest: 80, host: 4567 Also, allow the guest machine to be accessed by a static IP address. config.vm.network “private_network”, ip: “192.168.50.4” Now, you can visit 192.168.50.4 in your browser. If you set up Nginx, then you can view your Laravel site via that IP. If you add the following line to your host machine’s host file, you can visit your Laravel site by visiting testlar.test. cd ~/etc sudo vi hosts 192.168.50.4 testlar.test Create a folder called sites in the root folder (~/testlar). Add the following to the Vagrantfile to change the permissions of folders in the VM, so that www-data can modify them.

  config.vm.synced_folder "./sites", "/var/www",
      :owner => 'vagrant',
      :group => 'www-data',
      :mount_options => ['dmode=775', 'fmode=775']

Start up vagrant or reload it. vagrant up vagrant reload –provision

Install Nginx

Enter the vagrant machine and install nginx. cd ~/testlar && vagrant ssh sudo apt-get install nginx

Updating PHP

sudo add-apt-repository ppa:ondrej/php sudo apt-get update sudo apt-get install php7.2 sudo apt-get install php7.2-cli php7.2-fpm php7.2-curl php7.2-gd php7.2-mysql php7.2-mbstring zip unzip php7.2-xml If you don’t install php7.2-mbstring, you will get an error when install Laravel. Also, Nginx depends on some of the libraries above.

Install MySQL

sudo apt-get install mysql-server php7.2-mysql (The php7.2-mysql package is possibly part of the ppa:ondrej/php repo because it could not be found before enabling that repo.) Now, we can try connecting to MySQL using SequelPRO. Here is the location of the vagrant box’s SSH private key for SequelPRO if the username/password vagrant/vagrant doesn’t work: /Users/davidsr/testlar/.vagrant/machines/default/virtualbox/private_key https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-18-04 To connect to MySQL the first time, use the following command. sudo mysql When the MySQL prompt appears, run the following command to check to see if the root user is using the auth_socket plugin. If it is, we will change it to a password. SELECT user,authentication_string,plugin,host FROM mysql.user; ALTER USER ‘root’@’localhost’ IDENTIFIED WITH mysql_native_password BY ‘password’; FLUSH PRIVILEGES; Now, I can use the following info to connect to mysql with SequelPRO. MySQL Host: 127.0.0.1 Username: root Password: password Port: 3306 SSH Host: 192.168.50.4 SSH User: vagrant SSH Key: /Users/davidsr/testlar/.vagrant/machines/default/virtualbox/private_key

Install Composer

Now, I am going to start following this tutorial: https://www.howtoforge.com/tutorial/install-laravel-on-ubuntu-for-apache/ In Vagrant, run the two commands sudo apt-get update sudo apt-get upgrade curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer To install Laravel, run the following commands. cd /var/www mkdir testlar.test cd testlar.test

Install Laravel

composer create-project laravel/laravel testlar –prefer-dist It will take a couple seconds for this command to take affect (no loading)

Also install doctrine/dbal to be able to change table columns.

composer require doctrine/dbal

Configure Nginx

Replace the contents of the file named default with the code below. cd /etc/nginx/sites-available sudo vi default

server {
        listen 80;
        listen [::]:80;
        root /var/www/testlar/public;
        index index.php index.html index.htm;

        # Make site accessible from http://localhost/
        server_name testlar.test;

        location / {
                try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_intercept_errors on;
            fastcgi_pass unix:/run/php/php7.2-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
        }

        location ~ /\.ht {
            deny all;
        }
}

Make sure nginx setup is okay. sudo nginx -t sudo service nginx restart If ubuntu is using Apache instead of nginx, you can switch to nginx by disabling apache. sudo update-rc.d apache2 disable Now, you should be able to visit dox.test. Change the permissions for the storage directory. You have to do this on your host machine (not the virtual machine). Open a new tab in your terminal or exit vagrant and go to the location of this vagrant installation. exit cd ~/testlar sudo chmod -R 777 html/test/storage Now, visit the site. http://localhost:4568/ That’s it! Hopefully it will work! I noticed Firefox cached the Nginx welcome page. Try a different browser if you keep seeing that message. Set Up Node and NPM http://docs.webrichmedia.com/notes/install-node-nvm-prevents-permission-errors-installing-npm-packages-globally/ Set Up VueJS If you get the error “SyntaxError: Invalid or unexpected token” after compiling the JS, it may be an error with Nginx. Bullets would be injected at the end of my JavaScript file; the JavaScript file would just end for no reason; and the strange this is that it would work if I renamed the file, but if I made any changes, the error would happen, again. https://stackoverflow.com/questions/34718498/errors-with-vagrant-and-javascript-possibly-due-to-line-endings https://stackoverflow.com/questions/12719859/no-visible-cause-for-unexpected-token-illegal I updated Nginx, and it started working. cd /etc/nginx sudo vi nginx.conf Change sendfile on; to sendfile off;

Troubleshooting

I’ve encountered countless errors when working with Laravel. Here are some references for your benefit if you run into any of the errors that I did. https://github.com/thomaszbz/native-dockerfiles-typo3/issues/19 http://stackoverflow.com/questions/23540083/failed-to-open-stream-permission-denied-error-laravel https://laracasts.com/discuss/channels/servers/homesteadvagrant-cant-change-storage-file-permissions-issue I got a 500 internal server error. If you get a 500 error, the php versions might not be matching up. Particularly important is to change any references to php 7.0 to php 7.2. Laravel 5.6 only works with PHP versions greater than 7.1.3. You can also echo out PHP details by editing the index.php file in the public folder. cd /vagrant/html/test/public sudo vi index.php Add the following the very top of the file. phpinfo(); die(); If the version is 7.0, you need to update your Nginx blocks. cd /etc/nginx/sites-available sudo vi default Old: fastcgi_pass unix:/run/php/php7.0-fpm.sock; New: fastcgi_pass unix:/run/php/php7.2-fpm.sock; http://stackoverflow.com/questions/31543175/getting-a-500-internal-server-error-on-laravel-5-ubuntu-14-04 My Laravel installation would timeout. Running the following command fixed it. export COMPOSER_PROCESS_TIMEOUT=600 https://stackoverflow.com/questions/18917768/why-composer-install-timeouts-after-300-seconds https://laracasts.com/discuss/channels/laravel/laravel-56-parse-error-syntax-error-unexpected-expecting-variable-t-variable?page=1 Upgrade to php 7.2 https://gist.github.com/GhazanfarMir/03bd1f1f770a3834d47274586d46ea62 If routes aren’t working and return a 404, change try_files $uri $uri/ =404; to try_files $uri $uri/ /index.php;       I can visit testlar.test, but it goes to the default NGINX page (/usr/share/nginx/html). I had to change the server_name from localhost to server_name testlar.test. Here is the simple configuration for my Vagrantfile.

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

  config.vm.box = "ubuntu/trusty64"

  config.vm.provision :shell, path: "bootstrap.sh"

  config.vm.network :forwarded_port, guest: 8080, host: 80

  config.vm.network "private_network", ip: "192.168.50.4"

  config.vm.provider "virtualbox" do |vb|

    vb.memory = "2000"
  end

end

I was then able to visit http://testlar.test/ in the browser.

Creating a New Hubspot Timeline Event: What Am I Missing?

I am trying trying to create a new event using the Timeline Events API, but I keep getting an error: “You don’t have access to this application.”

I followed all the steps (creating an EventType, defined event properties, and defined template) in the following tutorial: https://developers.hubspot.com/docs/methods/timeline/timeline-overview

Here were my prerequisite steps to use the Timeline Events API.

I created a developer account and set that up.

I created an application.

I got a special code by doing the following things.

First, I created the following URL with my new client ID: https://app.hubspot.com/oauth/authorize?client_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&scope=contacts+timeline&redirect_uri=https://www.mysite.com/

After visiting that link, I was given the option of choosing an account (either the main account or my developer account). I chose my main account (my Enterprise account) since that’s the account that I am building the application to use the Timeline Events for.

After choosing my main account, I was redirected to https://www.mysite.com/?code=9e1a7276-86a0-4494-8a4c-248fa1206091

Then, I used that code to get an access_token from Hubspot. Here’s the PHP code for that. I had to set it up on my server and visit a page to activate it.

$headers = array();
$headers[] = 'Content-Type: application/x-www-form-urlencoded;charset=utf-8';

$hubEventUrl  = "https://api.hubapi.com/oauth/v1/token";
$fields = "grant_type=authorization_code";
$fields .= "&client_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
$fields .= "&client_secret=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
$fields .= "&redirect_uri=https://www.mysite.com/";
$fields .= "&code=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$hubEventUrl);
curl_setopt($ch,CURLOPT_POST, 5);
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result=curl_exec($ch);
curl_close($ch);

var_dump($result);

die();

Now, for the final step, I am trying to use the access token to create a timeline event for a contact in my main enterprise account. I followed all the steps (creating an EventType, defined event properties, and defined template) in the following tutorial: https://developers.hubspot.com/docs/methods/timeline/timeline-overview

Here’s the PHP code I am using for the final step. If anyone is interested, I have this set up in a PHP function, and it runs when I visit a certain URL.

$headers = array();
$headers[] = 'Content-Type: application/json';
$headers[] = "Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

$hubEventUrl  = 'https://api.hubapi.com/integrations/v1/179916/timeline/event?hapikey=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&userId=xxxxxxx;

$json = '{"id": "101921", "userEmail":"user@outlook.com","email":"user@gmail.com"}';

$fields = "id=101921";
$fields .= "&eventTypeId=279606"; 
$fields .= "&userEmail=user@gmail.com";
$fields .= "&email=user@outlook.com";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$hubEventUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch,CURLOPT_POST, 4);
curl_setopt($ch,CURLOPT_POSTFIELDS, $json);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result=curl_exec($ch);

var_dump($result);

die();

A couple questions about $hubEventUrl. In this tutorial (https://developers.hubspot.com/docs/methods/timeline/create-or-update-event), it says that “You must use an OAuth access token to create an event. API keys are not supported.” However, if I don’t include the hapikey in the $hubEventUrl, I get an error. I assumed I needed to use my developer account’s hapikey, but I noticed my Enterprise account also has a hapikey.
1) Do I use my developer account’s hapikey or my Enterprise account’s hapikey?
2) Also, same question for the userId. Do I use my developer account user’s ID, or my Enterprise account user’s ID? I have tried both, but I get the same error “”You don’t have access to this application.”

Just as a side note, this is a lot of work just to use the Timeline Events API. Is there an easier way?

Thanks, in advance!

Building a Web App with ReactJS and Laravel

I recently had the opportunity to build a web app using ReactJS and the PHP framework called Laravel. I was the front and back end web developer, the development operations manager, and the web designer. Somehow, it turned out okay. Note that this is not a tutorial, but that doesn’t mean you won’t be able to glean any useful information from it.

Install All the Packages

Development operations had me pulling my hair out, but the web development side of things (front end and back end) was more manageable. When I installed something, it would work… for the most part. Here’s a list of all the React and Laravel packages I had to install.

  • A Laravel package to manage images
  • A React package (which was broken) for managing pagination
  • A React package for letting users share their entries on social media.
  • A React package for using Stripe.
  • A React package (which was also broken) that created a popup to let users choose an image from facebook.
  • A vanilla JS package for managing cookies.

I’m sure there were many more packages, but those are the ones that come to mind.

The Confusions of React Router V4

Besides taking a few React courses on Teamtreehouse.com, I had never used React for a professional web application. I didn’t quite understand how to use it, but I was able to use it to build the web application. Getting it set up was very confusing though. React had just recently switched over to React Router V4. I never really understood what React Router V4 actually was the whole time I was building the app,. Basically, React Router V4 is a library for conditionally adding and removing (not just hiding) React components based on the URL/path of the site. Don’t try to equate React Router V4 with any routes that you normally use. It won’t work. I was equating React Router with Laravel routes, and I thought of  components as Laravel pages. That was definitely not the right way to think about them. They are a lot different. You can wrap a little button component in a route and only display that button on a page with the URL mysite.com/page-with-extra-button. You can put that button (<Route path=”/page-with-extra-button”><MyButton /></Route>) anywhere you want. It can be in a menu, in the footer, in a random component in the middle of another component. It can appear anywhere. You definitely can’t do that with a Laravel route. It is a very strange way of thinking about routes.

The Laravel Back End

There’s not too much to say about the back-end. I set up a couple models in Laravel and their corresponding database tables. Nothing really blew me away or totally confused me. Routes acted like routes. I still don’t quite understand Models, but I sure took advantage of Controller classes and functions.

For the most part, Laravel just acted as an API for React JS, and it acted as a very good API at that.

Development Operations (Launching the React/Laravel App)

I deployed the development project to the live server using git. I set up the app (the website) on a LEMP Digital Ocean droplet. Installing the Laravel dependencies was a bit of a doozy. I remember one composer package needed PHP 7.2 (gotta stay current, right?), and I had to uninstall the previous PHP version and install the new one. That caused some issues. I also had trouble (errors) setting up the MySQL database. Honestly, each of these errors seemed to be like a brick wall, but with enough troubleshooting, I was able to get through each one. In addition to actually building the app (development), I was also in charge of development operations (setting up the server for the site and deploying it) and web design. That’s usually how it goes in small companies. Since I’m not a designer, I got most of my inspiration from other websites.

A Good Result

There was so much stuff to do, but it turned out pretty good. It’s amazing to see everything working together in unison (and not crashing and burning).  One big issue is that the live site only updates every three hours. I think it’s a JS caching issue that I haven’t been able to figure out, but it may also be a Laravel template issue. It could also be both. EDIT: The issue was indeed a JavaScript caching issue. Each time I pushed the dev server to the live server, I’d have to change the version of the JavaScript file.

Because of time constraints, I had to really, really rely heavily on React and Laravel to work in development, and they both performed wonderfully. Would I use React and Laravel to build another web application? The answer is a definite yes.

If you want to read more about my experience with React, check out my article named My Biggest Takeaways from Using React JS.

Building a Great User Experience

As the web gets more sophisticated, the typical user experience becomes more demanding. Users expect more and more from everyday websites, even though they are everyday websites and not giants like Amazon, Facebook, or Yelp. These giants can provide “incredible” experiences because they have the resources. I put quotations marks around the word incredible because the experience really isn’t incredible. It’s just expected, normal, intuitive, and easy. The work it takes to create a user experience that feels intuitive is sometimes unimaginable. To a user, it just makes sense. I click this, and that happens. The typical user doesn’t think about the thousands of computations going on in the background in the blink of an eye. When they click something, and something happens, typically, the user isn’t awed by the fact that there is a complex system behind it made up of millions of lines of code with each component working in unison to accomplish a seemingly simple task. But users have come to expect that seamless experience on all the websites they visit. When a user clicks something, and what they thought would happen doesn’t happen, they usually don’t think “Oh, there is an incredibly complex system working behind this website made up of millions of lines of code that must work in unison. I can understand why this one small function might not work.” No, that would be nice if they thought that, but what they usually think is “Oh, it’s broken. What a terrible website.” But creating that seamless experience for users is becoming less and less of the monumental task it once was, thanks to SAAS (software as a service), APIs, and libraries like React JS. What once wasn’t possible a few years ago, is now possible for a few or even one web developer to accomplish. I don’t mean it’s possible for one person to build a clone of Facebook, but it is possible to harness a site like Algolia and a framework like React JS to create an incredibly fast and intuitive search experience: instant filtering of thousands of items, typo tolerance, ranking, distance sorting, and auto-complete. Granted, it will take a lot of work to set up that amazing search, but it is possible. And the possibilities are just increasing. The game’s getting more challenging. So, it’s time to step up your game. Get used to the fact that users will expect a “phenomenal” experience. Learn the ways of the new internet and pick up a skill like ReactJS or Laravel. As a web developer, you certainly won’t regret it!

My Biggest Takeaways from Using React JS

I recently started using ReactJS for projects at work a lot. These are my takeaways.

Not SEO Friendly

React applications are not SEO friendly if they load data using an AJAX request which is pretty much all React applications. None of the data retrieved from the AJAX request (like a blog post) will be indexed by search engines. To fix this issue, I started retrieving all the data for a specific page on first load. This does create some overhead in the application, but it’s worth it (and sometimes necessary). For example, the first time the user (or crawler) loads the application, I get all the data I need (blog posts), turn it into JSON, and echo it into a div. Then, when the HTML loads, I get the JSON string from the div using JavaScript (divEl.innerText), and I parse it with JavaScript (JSON.parse(json_string)). But I only do this if this is the first time the application is loading. It’s not very magical, but I don’t see any way around it if you’re not using Node. If you’re using Node, you can do server side rendering.

Routing Is Fun

Routing makes it really fun to conditionally show parts of your application (components), depending which page the visitor is on. There is nothing magical about Routes. You just wrap the component in a Route and specify the URL of that route. Then, when that route is visited, the component is mounted, and it is destroyed when that route changes. There are also Switch statements which are very useful.

Components Are Extremely Reusable

Components are incredibly reusable. When I first started using React, I thought of all components as pages. I created what I thought was a Login page and directed users to that page. But then, I realized that I could take that whole entire Login “page” (component), and load it wherever I wanted, as long as I supplied the right props.

State and Props

State and props are important. That’s kind of an understatement. State and props are the life blood of your application. If you’re building a blog website, state and props are the blog posts. Components are just used to display the blog posts (the state), and the components update automatically when the state updates. They are very tightly coupled. In fact, they inseparable.

Lifecycle Functions

Lifecycle functions are very important. Right now, the two I use the most are componentDidMount, and componentWillReceiveProps(nextProps). I used this component to solve my back button problems.

For example, I had a complicated component that would let the user filter the data and paginate. The route and URL would update with these changes (when I would get new data), but nothing happened when the user would hit the back button. The route (the URL) would change, but React would not get the data. I had to use componentWillRecieveProps to check to see if the route was changing. Since all of the changes were in the params of the URL, this worked pretty well for me. I would just get the previous page’s params, and get the data, again. I’m not sure if this is how I’m supposed to do it, but it works.

Hide Complex Components

You don’t have to destroy a component when you leave a route. You can load components (not using Routes) when a certain condition exists and hide hide them with CSS when that condition is false. This is completely fine. Vue has something callled keep-alive that works similarly. For example, I had a large component that loaded a lot of data and then performed a lot calculations on that data. Instead of including that component in a route (/oranges), I used plain JavaScript to check if the URL contained the word “oranges.” If it did, I would load the component and make note that the component loaded. If the user left the page, I hid the component using CSS, and I would reveal the component when the user visited that page, again. Simple, but it works.

Summary

So, React JS is not SEO friendly. Routes are fun. Components are incredibly reusable. And state and props are the lifeblood of your application.