This post was written by Jeremy Davis, JavaScript Developer for Toptal.

CSS was designed for documents, what the “old web” was expected to contain. The emergence of pre-processors like Sass or Less shows that the community needs more than what CSS offers. With web apps getting more and more complex over time, CSS’ limitations have become increasingly visible and difficult to mitigate.

Styled-components leverages the power of a complete programming language—JavaScript—and its scoping capabilities to help structure the code into components. This helps to avoid the common pitfalls of writing and maintaining CSS for large projects. A developer can describe a component’s style with no risk of side effects.

What’s the Problem?

One advantage of using CSS is that the style is completely decoupled from the code. This means that developers and designers can work in parallel without interfering with each other.

On the other hand, styled-components makes it easier to fall in the trap of strongly coupling style and logic. Max Stoiber explains how to avoid this. While the idea of separating logic and presentation is definitely not new, one might be tempted to take shortcuts when developing React components. For example, it’s easy to create a component for a validation button that handles the click action as well as the button’s style. It takes a bit more effort to split it in two components.

The Container/Presentational Architecture

This is a pretty simple principle. Components either define how things look, or they manage data and logic. A very important aspect of presentation components is that they should never have any dependencies. They receive props and render DOM (or children) accordingly. Containers, on the other hand, know about the data architecture (state, redux, flux, etc.) but should never be responsible for display. Dan Abramov’s article is a very good and detailed explanation of this architecture.

Remembering SMACSS

Although the Scalable and Modular Architecture for CSS is a style guide for organizing CSS, the basic concept is one that is followed, for the most part automatically, by styled-components. The idea is to separate CSS into five categories:

  • Base contains all the general rules.
  • Layout’s purpose it to define the structural properties as well as various sections of content (header, footer, sidebar, content, for instance).
  • Module contains subcategories for the various logical blocks of the UI.
  • State defines modifier classes to indicate elements’ states, e.g. field in error, disabled button.
  • Theme contains color, font, and other cosmetic aspects that may be modifiable or dependent on user preference.

Keeping this separation while using styled-components is easy. Projects usually include some kind of CSS normalization or reset. This typically falls in the Base category. You may also define general font sizing, line sizing, etc. This can be done through normal CSS (or Sass/Less), or through the injectGlobal function provided by styled-components.

For Layout rules, if you use a UI framework, then it will probably define container classes, or a grid system. You can easily use those classes in conjunction with your own rules in the layout components you write.

Module is automatically followed by the architecture of styled-components, since the styles are attached to components directly, rather than described in external files. Basically, each styled component that you write will be its own module. You can write your styling code without worrying about side effects.

State will be rules you define within your components as variable rules. You simply define a function to interpolate values of your CSS attributes. If using a UI framework, you might have useful classes to add to your components as well. You will probably also have CSS pseudo-selector rules (hover, focus, etc.)

The Theme can simply be interpolated within your components. It is a good idea to define your theme as a set of variables to be used throughout your application. You can even derive colors programmatically (using a library, or manually), for instance to handle contrasts and highlights. Remember that you have the full power of a programming language at your disposal!

Bring Them Together for a Solution

It is important to keep them together, for an easier navigation experience; We don’t want to organize them by type (presentation vs. logic) but rather by functionality.

Thus, we will have a folder for all the generic components (buttons and such). The others should be organized depending on the project and its functionalities. For instance, if we have user management features, we should group all the components specific to that feature.

To apply styled-components’ container/presentation architecture to a SMACSS approach, we need an extra type of component: structural. We end up with three kinds of components; styled, structural, and container. Since styled-components decorates a tag (or component), we need this third type of component to structure the DOM. In some cases, it might be possible to allow a container component to handle the structure of sub-components, but when the DOM structure becomes complex and is required for visual purposes, it’s best to separate them. A good example is a table, where the DOM typically gets quite verbose.

Example Project

Let’s build a small app that displays recipes to illustrate these principles. We can start building a Recipes component. The parent component will be a controller. It will handle the state—in this case, the list of recipes. It will also call an API function to fetch the data.

class Recipes extends Component{
  constructor (props) {
    super(props);
    this.state = {
      recipes: []
    };
  }

  componentDidMount () {
    this.loadData()
  }

  loadData () {
    getRecipes().then(recipes => {
      this.setState({recipes})
    })
  }

  render() {
    let {recipes} = this.state

    return (
      <RecipesContainer recipes={recipes} />
    )
  }
}

It will render the list of recipes, but it does not (and should not) need to know how. So we render another component that gets the list of recipes and outputs DOM:

class RecipesContainer extends Component{
  render() {
    let {recipes} = this.props

    return (
      <TilesContainer>
        {recipes.map(recipe => (<Recipe key={recipe.id} {...recipe}/>))}
      </TilesContainer>
    )
  }
}

Here, actually, we want to make a tile grid. It may be a good idea to make the actual tile layout a generic component. So if we extract that, we get a new component that looks like this:

class TilesContainer extends Component {
  render () {
    let {children} = this.props

    return (
      <Tiles>
        {
          React.Children.map(children, (child, i) => (
            <Tile key={i}>
              {child}
            </Tile>
          ))
        }
      </Tiles>
    )
  }
}

TilesStyles.js:

export const Tiles = styled.div`
  padding: 20px 10px;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
`

export const Tile = styled.div`
  flex: 1 1 auto;
  ...
  display: flex;

  & > div {
    flex: 1 0 auto;
  }
`

Notice that this component is purely presentational. It defines its style and wraps whatever children it receives inside another styled DOM element that defines what tiles look like. It’s a good example of what your generic presentational components will look like architecturally.

Then, we need to define what a recipe looks like. We need a container component to describe the relatively complex DOM as well as define the style when necessary. We end up with this:

class RecipeContainer extends Component {
  onChangeServings (e) {
    let {changeServings} = this.props
    changeServings(e.target.value)
  }

  render () {
    let {title, ingredients, instructions, time, servings} = this.props

    return (
      <Recipe>
        <Title>{title}</Title>
        <div>{time}</div>
        <div>Serving
          <input type="number" min="1" max="1000" value={servings} onChange={this.onChangeServings.bind(this)}/>
        </div>
        <Ingredients>
          {ingredients.map((ingredient, i) => (
            <Ingredient key={i} servings={servings}>
              <span className="name">{ingredient.name}</span>
              <span className="quantity">{ingredient.quantity * servings} {ingredient.unit}</span>
            </Ingredient>
          ))}
        </Ingredients>
        <div>
          {instructions.map((instruction, i) => (<p key={i}>{instruction}</p>))}
        </div>
      </Recipe>
    )
  }
}

Notice here that the container does some DOM generation, but it’s the only logic it contains. Remember that you can define nested styles, so you don’t need to make a styled element for each tag that requires styling. It’s what we do here for the name and quantity of the ingredient item. Of course, we could split it further and create a new component for an ingredient. That is up to you—depending on the project complexity—to determine the granularity. In this case, it is just a styled component defined along with the rest in the RecipeStyles file:

export const Recipe = styled.div`
  background-color: ${theme('colors.background-highlight')};
`;

export const Title = styled.div`
  font-weight: bold;
`

export const Ingredients = styled.ul`
  margin: 5px 0;
`

export const Ingredient = styled.li`
  & .name {
    ...
  }

  & .quantity {
    ...
  }
`

For the purpose of this exercise, I have used the ThemeProvider. It injects the theme in the props of styled components. You can simply use it as color: ${props => props.theme.core_color}, I am just using a small wrapper to protect from missing attributes in the theme:

const theme = (key) => (prop) => _.get(prop.theme, key) || console.warn('missing key', key)

You can also define your own constants in a module and use those instead. For example: color: ${styleConstants.core_color}

Pros

A perk of using styled-components is that you can use it as little as you want. You can use your favorite UI framework and add styled-components on top of it. This also means that you can easily migrate an existing project component by component. You can choose to style most of the layout with standard CSS and only use styled-components for reusable components.

Cons

Designers/style integrators will need to learn very basic JavaScript to handle variables and use them in place of Sass/Less.

They will also have to learn to navigate the project structure, although I would argue that finding the styles for a component in that component’s folder is easier than having to find the right CSS/Sass/Less file that contains the rule you need to modify.

They will also need to change their tools a bit if they want syntax highlighting, linting, etc. A good place to start is with this Atom plugin and this babel plugin.

 

This post was written by Ben Jones, Front-end Developer for Toptal.

Ben is a skilled developer who always keeps the user in mind, which allows him to see how beneficial or detrimental a development process can be. He wants to create simple but effective software to reduce workload on all sides and to make employees, employers, and customers happy.


JavaScript frameworks/libraries such as Vue can offer a fantastic user experience when browsing your site. Most offer a way of dynamically changing page content without having to send a request to the server each time.

However, there is an issue with this approach. When initially loading your website, your browser doesn’t receive a complete page to display. Instead, it gets sent a bunch of pieces to construct the page (HTML, CSS, other files) and instructions for how to put them all together (a JavaScript framework/library) It takes a measurable amount of time to put all this information together before your browser actually has something to display. It’s like being sent a bunch of books along with a flat-pack bookcase. You’d have to build the bookcase first and then fill it with the books.

The solution to this is clever: Have a version of the framework/library on the server that can build a ready-to-display page. Then send this complete page to the browser along with the ability to make further changes and still have dynamic page content (the framework/library), just like being sent a ready-made bookcase along with some books. Sure, you still have to put the books in the bookcase, but you’ve got something usable immediately.

Visual comparison of client-side and server-side rendering

Beyond the silly analogy, there are also a bunch of other advantages. For example, a page that rarely changes, such as an About Us page, doesn’t need to be recreated every single time a user asks for it. So a server can create it once and then cache it or store it somewhere for future use. These kinds of speed improvements may seem tiny, but in an environment where time until responsiveness is measured in milliseconds (or less), every little bit counts.

If you’d like more information on the advantages of SSR in a Vue environment, you should check out Vue’s own article on SSR. There is a variety of options to achieve these results, but the most popular one, which is also recommended by the Vue team, is Nuxt.

Why Nuxt.js

Nuxt.js is based off an implementation of SSR for the popular React library called Next. After seeing the advantages of this design, a similar implementation was designed for Vue called Nuxt. Those familiar with the React+Next combination will spot a bunch of similarities in design and layout of the application. However, Nuxt offers Vue-specific features to create a powerful yet flexible SSR solution for Vue.

Nuxt was updated to a production-ready 1.0 version in January 2018 and is part of an active and well-supported community. One of the great things is that building a project using Nuxt isn’t that different from building any other Vue project. In fact, it provides a bunch of features that allow you to create well-structured codebases in a reduced amount of time.

Another important thing to note is Nuxt doesn’t have to be used for SSR. It’s promoted as a framework for creating universal Vue.js applications and includes a command (nuxt generate) for creating static generated Vue applications using the same codebase. So if you’re apprehensive about diving deep into SSR, don’t panic. You can always create a static site instead while still taking advantage of Nuxt’s features.

In order to grasp the potential of Nuxt, let’s create a simple project. The final source code for this project is hosted on GitHub if you want to see it, or you can view a live version created using nuxt generate and hosted on Netlify.

Creating a Nuxt Project

To start off, let’s use a Vue project generator called vue-cli to quickly create a sample project:

# install vue-cli globally
npm install -g vue-cli

# create a project using a nuxt template
vue init nuxt-community/starter-template my-nuxt-project

After going through a couple options, this will create a project inside the folder my-nuxt-project or whatever you specified. Then we just need to install dependencies and run the server:

cd my-nuxt-project
npm install # Or yarn
npm run dev

There we go. Open your browser to localhost:3000 and your project should be running. Not much different from creating a Vue Webpack project. However, when we look at the actual structure of the app, there’s not much there, especially when compared to something like the Vue Webpack template.

Diagram of project directories and their relation to the Nuxt config file

Looking in the package.json also shows that we only have one dependency, Nuxt itself. This is because each version of Nuxt is tailored to work with specific versions of Vue, Vue-router, and Vuex and bundles them all together for you.

There is also a nuxt.config.js file at the project root. This allows you to customize a bunch of features that Nuxt provides. By default, it sets the header tags, loading bar color, and ESLint rules for you. If you’re eager to see what you can configure, here’s the documentation; we will be covering some options in this article.

So what’s so special about those directories?

Project Layout

If you browse through the directories created, all of them have an accompanying Readme stating a brief summary of what goes in that directory and often a link to the docs.

This is one benefit of using Nuxt: a default structure for your application. Any good front-end developer will structure an application similar to this, but there are many different ideas about structures, and when working on a team, some time will inevitably go into discussing or choosing this structure. Nuxt provides one for you.

Nuxt will look for certain directories and build your application for you depending on what it finds. Let’s examine these directories one by one.

Pages

This is the only required directory. Any Vue components in this directory are automatically added to vue-router based on their filenames and the directory structure. This is extremely convenient. Normally I would have a separate Pages directory anyway and have to manually register each of those components in another router file. This router file can become complex for larger projects and may need splitting to maintain readability. Instead, Nuxt will handle all of this logic for you.

To demonstrate, we can create a Vue component called about.vue inside the Pages directory. Let’s just add a simple template such as:

<template>
 <h1>About Page</h1>
</template>

When you save, Nuxt will re-generate the routes for you. Seeing as we called our component about.vue, if you navigate to /about, you should see that component. Simple.

There is one filename which is special. Naming a file index.vue will create a root route for that directory. When the project is generated, there’s already an index.vue component in the pages directory which correlates to the homepage or landing page of your site. (In the development example, this would simply be localhost:3000.)

Nuxt scans the Vue files in the pages directory and outputs the appropriate pages.

What about deeper routes? Sub-directories in the Pages directory help to structure your routes. So if we wanted a View Product page, we could structure our Pages directory something like this:

/pages
--| /products
----| index.vue
----| view.vue

Now, if we navigate to /products/view, we will see the view.vue component inside the products directory. If we navigate instead to /products, we will see the index.vuecomponent inside the products directory.

You may be asking why we didn’t just create a products.vue component in the pages directory instead like we did for the /about page. You may think the result would be the same, but there is a difference between the two structures. Let’s demonstrate this by adding another new page.

Say we wanted a seperate About page for each employee. For example, let’s create an About page for me. It should be located at /about/ben-jones. Initially, we may try structuring the Pages directory like this:

/pages
--| about.vue
--| /about
----| ben-jones.vue

When we try to access /about/ben-jones, we instead get the about.vue component, the same as /about. What’s going on here?

Interestingly, what Nuxt is doing here is generating a nested route. This structure suggests that you want a permanent /about route and anything inside that route should be nested in its own view area. In vue-router, this would be signified by specifying a <router-view />component inside the about.vue component. In Nuxt, this is the same concept except, instead of <router-view />, we simply use <nuxt />. So let’s update our about.vuecomponent to allow for nested routes:

<template>
 <div>
   <h1>About Page</h1>
   <nuxt />
 </div>
</template>

Now, when we navigate to /about, we get the about.vue component we had before, with just a title. However, when we navigate to /about/ben-jones, we instead have the title andthe ben-jones.vue component rendered where the <nuxt/> placeholder was.

This wasn’t what we initially wanted, but the idea of having an About page with a list of people that, when clicked on, fill a section on the page with their information is an interesting concept, so let’s leave it as is for now. If you did want the other option, then all we would do is restructure our directories. We’d just have to move the about.vuecomponent inside the /about directory and rename it index.vue, so the resulting structure would be:

/pages
--| /about
----| index.vue
----| ben-jones.vue

Finally, say we wanted to use route params to retrieve a specific product. For example, we want to be able to edit a product by navigating to /products/edit/64 where 64 is the product_id. We can do this the following way:

/pages
--| /products
----| /edit
------| _product_id.vue

Note the underscore at the beginning of the _product_id.vue component—this signifies a route param which is then accessible on the $route.params object or on the params object in Nuxt’s Context (more on that later). Note that the key for the param will be the component name without the initial underscore—in this case, product_id—so try to keep them unique within the project. As a result, in _product_id.vue, we may have something like:

<template>
 <h1>Editing Product {{ $route.params.product_id }}</h1>
</template>

You can start to imagine more complex layouts, which would be a pain to set up using vue-router. For example, we can combine all of the above into a route such as:

/pages
--| /categories
----| /_category_id
------| products.vue
------| /products
--------| _product_id.vue

It’s not too difficult to reason on what /categories/2/products/3 would display. We would have the products.vue component with a nested _product_id.vue component, with two route params: category_id and product_id. This is much simpler to reason on than an equivalent router config.

While we’re on the topic, one thing I tend to do in the router config is set up router guards. As Nuxt is building the router for us, this can be done instead on the component itself with beforeRouteEnter. If you want to validate route params, Nuxt provides a component method called validate. So if you wanted to check if the product_id was a number before trying to render the component, you would add the following to the script tag of _product_id.vue:

export default {
 validate ({ params }) {
   // Must be a number
   return /^\d+$/.test(params.product_id)
 }
}

Now, navigating to /categories/2/products/someproduct results in a 404 because someproduct isn’t a valid number.

That’s it for the Pages directory. Learning how to structure your routes properly in this directory is essential, so spending a little time initially is important to getting the most out of Nuxt. If you’re looking for a brief overview, it is always helpful to refer to the docs for routing.

If you’re worried about not being in control of the router, don’t be. This default setup works great for a wide variety of projects, provided they are well structured. However, there are some cases where you may need to add more routes to the router than Nuxt automatically generates for you or restructure them. Nuxt provides a way to customize the router instance in the config, allowing you to add new routes and customize generated routes. You can also edit the core functionality of the router instance, including extra options added by Nuxt. So if you do encounter an edge case, you still have the flexibility to find the appropriate solution.

Store

Nuxt can build your Vuex store based on the structure of the store directory, similar to the Pages directory. If you don’t need a store, just remove the directory. There are two modes for the store, Classic and Modules.

Classic requires you to have an index.js file in the store directory. There you need to export a function that returns a Vuex instance:

import Vuex from 'vuex'

const createStore = () => {
 return new Vuex.Store({
   state: ...,
   mutations: ...,
   actions: ...
 })
}

export default createStore

This allows you to create the store however you wish, much like using Vuex in a normal Vue project.

Modules mode also requires you to create an index.js file in the store directory. However, this file only needs to export the root state/mutations/actions for your Vuex store. The example below specifies a blank root state:

export const state = () => ({})

Then, each file in the store directory will be added to the store in its own namespace or module. For example, let’s create somewhere to store the current product. If we create a file called product.js in the store directory, then a name-spaced section of the store will be available at $store.product. Here’s a simple example of what that file may look like:

export const state = () => ({
 _id: 0,
 title: 'Unknown',
 price: 0
})

export const actions = {
 load ({ commit }) {
   setTimeout(
     commit,
     1000,
     'update',
     { _id: 1, title: 'Product', price: 99.99 }
   )
 }
}

export const mutations = {
 update (state, product) {
   Object.assign(state, product)
 }
}

The setTimeout in the load action simulates some sort of API call, which will update the store with the response; in this case, it takes one second. Now, let’s use it in the products/view page:

<template>
 <div>
   <h1>View Product {{ product._id }}</h1>
   <p>{{ product.title }}</p>
   <p>Price: {{ product.price }}</p>
 </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
 created () {
   this.$store.dispatch('product/load')
 },
 computed: {
   ...mapState(['product'])
 }
}
</script>

A few things to note: Here, we are calling our fake API when the component is created. You can see that the product/load action we are dispatching is namespaced under Product. This makes it clear exactly what section of the store we are dealing with. Then, by mapping the state to a local computed property, we can easily use it in our template.

There is a problem: We see the original state for a second while the API runs. Later, we will use a solution provided by Nuxt to fix this (known as fetch).

Just to stress this again, we never had to npm install vuex, as it is already included in the Nuxt package. When you add an index.js file to the store directory, all those methods are then opened up to you automatically.

That’s the main two directories explained; the rest are much simpler.

Components

The Components directory is there to contain your reusable components such as a navigation bar, image gallery, pagination, data tables, etc. Seeing as components in the Pages directory are converted into routes, you need somewhere else to store these types of components. These components are accessible in pages or other components by importing them:

import ComponentName from ~/components/ComponentName.vue

Assets

This contains uncompiled assets and has more to do with how Webpack loads and processes files, rather than with how Nuxt works. If you’re interested, I suggest reading the guide in the Readme.

Static

This contains static files which are mapped to the root directory of your site. For example, putting an image called logo.png in this directory would make it available at /logo.png. This is good for meta files like robots.txt, favicon.ico, and other files you need available.

Layouts

Normally, in a Vue project, you have some sort of root component, normally called App.vue. Here is where you can set up your (normally static) app layout, which may include a navbar, footer, and then a content area for your vue-router. The default layout does exactly that and is provided for you in the layouts folder. Initially, all it has is a div with a <nuxt />component (which is equivalent to <router-view />) but it can be styled however you wish. For example, I’ve added a simple navbar to the example project for navigation around the various demonstration pages.

A layout can be applied to multiple pages.

You may want to have a different layout for a certain section of your app. Maybe you have some sort of CMS or admin panel that looks different. To solve this, create a new layout in the Layouts directory. As an example, let’s create an admin-layout.vue layout which just has an extra header tag and no navbar:

<template>
 <div>
   <h1>Admin Layout</h1>
   <nuxt />
 </div>
</template>

Then, we can create an admin.vue page in the Pages directory and use a property provided by Nuxt called layout to specify the name (as a string) of the layout we want to use for that component:

<template>
 <h1>Admin Page</h1>
</template>

<script>
export default {
 layout: 'admin-layout'
}
</script>

That’s all there is to it. Page components will use the default layout unless specified, but when you navigate to /admin, it now uses the admin-layout.vue layout. Of course, this layout could be shared across several admin screens if you wish. The one important thing to remember is layouts must contain a <nuxt /> element.

There’s one final thing to note about layouts. You may have noticed while experimenting that if you type an invalid URL, you are shown an error page. This error page is, in fact, another layout. Nuxt has its own error layout (source code here), but if you wanted to edit it, just create an error.vue layout and that will be used instead. The caveat here is that the error layout must not have a <nuxt /> element. You will also have access to an errorobject on the component with some basic information to display. (This is printed out in the terminal running Nuxt if you want to examine it.)

Middleware

Middleware are functions that can be executed before rendering a page or layout. There is a variety of reasons you may want to do so. Route guarding is a popular use where you could check the Vuex store for a valid login or validate some params (instead of using the validate method on the component itself). One project I worked on recently used middleware to generate dynamic breadcrumbs based on the route and params.

These functions can be asynchronous; just be careful, as nothing will be shown to the user until the middleware is resolved. They also have access to Nuxt’s Context, which I will explain later.

Plugins

This directory allows you to register Vue plugins before the application is created. This allows the plugin to be shared throughout your app on the Vue instance rather than creating it each time you import it into a component. This helps to keep the bundle sizes small.

Most major plugins have a Nuxt version that can be easily registered to the Vue instance by following their docs. However, there will be circumstances when you will be developing a plugin or need to adapt an existing plugin for this purpose. An example I’m borrowing from the docs shows how to do this for vue-notifications. First, we need to install the package:

npm install vue-notifications --save

Then create a file in the plugins directory called vue-notifications.js and include the following:

import Vue from 'vue'
import VueNotifications from 'vue-notifications'

Vue.use(VueNotifications)

Very similar to how you would register a plugin in a normal Vue environment. Then edit the nuxt.config.js file at your project root and add the following entry to the module.exports object:

plugins: ['~/plugins/vue-notifications']

That’s it. Now you can use vue-notifications throughout your app without increasing the bundle size. An example of this is at /plugin in the example project.

So that completes a rundown of the directory structure. It may seem a lot to learn, but if you’re developing a Vue app, you’re already setting up the same kind of logic. Nuxt helps to abstract away the setup and help you focus on building.

Nuxt does more than assist in development though. It supercharges your components by providing extra functionality.

Nuxt’s Supercharged Components

When I first started researching Nuxt, I kept reading about how Page components are supercharged. It sounded great, but it wasn’t immediately obvious what exactly that meant and what benefits it brings.

What it means is that all Page components have extra methods attached to them that Nuxt can use to provide additional functionality. In fact, we’ve already seen one of these earlier when we used the validate method to check params and redirect a user if they are invalid.

The two main ones used in a Nuxt project will be the asyncData and fetch methods. Both are very similar in concept, they are run asynchronously before the component is generated, and they can be used to populate the data of a component and the store. They also enable the page to be fully rendered on the server before sending it to the client even when we have to wait for some database or API call.

What’s the difference between asyncData and fetch?

  • asyncData is used to populate the data of the Page component. When you return an object, it is then merged with the output of data before rendering.
  • fetch is used to populate the Vuex Store. If you return a promise, Nuxt will wait until it is resolved before rendering.

So let’s put these to good use. Remember earlier on the /products/view page we had a problem where the initial state of the store was being displayed briefly while our fake API call was being made? One way of fixing this is having a boolean stored on the component or in the Store such as loading = true and then displaying a loading component while the API call finishes. Afterward, we would set loading = false and display the data.

Instead, let’s use fetch to populate the Store before rendering. In a new page called /products/view-async, let’s change the created method to fetch; that should work, right?

export default {
 fetch () {
   // Unfortunately the below line throws an error
   // because 'this.$store' is undefined...
   this.$store.dispatch('product/load')
 },
 computed: {...}
}

Here’s the catch: These “supercharged” methods run before the component is created, so this doesn’t point to the component and nothing on it can be accessed. So how do we access the Store here?

The Context API

Of course, there is a solution. On all of Nuxt’s methods, you are provided with an argument (normally the first) containing an extremely useful object called the Context. In this is everything you will need reference to across the app, meaning we don’t need to wait for Vue to create those references on the component first.

I would highly recommend checking out the Context docs to see what is available. Some handy ones are app, where you can access all your plugins, redirect, which can be used to change routes, error to display the error page, and some self-explanatory ones such as routequery, and store.

So, to access the Store, we can destructure the Context and extract the Store from it. We also need to make sure we return a promise so that Nuxt can wait for it to resolve before rendering the component, so we need to make a small adjustment to our Store action too.

// Component
export default {
 fetch ({ store }) {
   return store.dispatch('product/load')
 },
 computed: {...}
}

// Store Action
load ({ commit }) {
 return new Promise(resolve => {
   setTimeout(() => {
     commit('update', { _id: 1, title: 'Product', price: 99.99 })
     resolve()
   }, 1000)
 })
}

You could use async/await or other methods depending on your coding style, but the concept is the same—we’re telling Nuxt to make sure the API call finishes and the Store is updated with the result before trying the render the component. If you try navigating to /products/view-async, you will not see the flash of content where the product is in its initial state.

You can imagine how useful this can be in any Vue app even without SSR. The Context is also available to all middlewares as well as to other Nuxt methods such as NuxtServerInitwhich is a special store action that runs before the Store is initialized (an example of this is in the next section)

Considerations When Using SSR

I’m sure many (myself included) who start using a technology such as Nuxt while treating it like any other Vue project eventually hit a wall where something we know would normally work seems impossible in Nuxt. As more of these caveats are documented, it will be easier to overcome, but the main thing to consider when starting to debug is that the client and server are two separate entities.

When you access a page initially, a request is sent to Nuxt, the server builds as much as possible of that page and the rest of the app, and then the server sends it to you. Then the responsibility is on the client to continue with navigation and load chunks as it needs them.

We want the server to do as much as possible first, but sometimes it doesn’t have access to the information it needs, which results in the work being done client-side instead. Or worse, when the final content presented by the client is different from what the server expected, the client is told to rebuild it from scratch. This is a big indication that something is wrong with the application logic. Thankfully, an error will be generated in your browser’s console (in development mode) if this starts to happen.

Let’s take an example of how to solve a common issue, session management. Imagine you have a Vue app where you can log in to an account, and your session is stored using a token (JWT, for example) which you decide to keep in localStorage. When you initially access the site, you want to authenticate that token against an API, which returns some basic user info if valid and puts that information in the Store.

After reading through Nuxt’s docs, you see that there’s a handy method called NuxtServerInit which allows you to asynchronously populate the Store once on initial load. That sounds perfect! So you create your user module in the Store and add the appropriate action in the index.js file in the Store directory:

export const actions = {
 nuxtServerInit ({ dispatch }) {
   // localStorage should work, right?
   const token = localStorage.getItem('token')
   if (token) return dispatch('user/load', token)
 }
}

When you refresh the page, you get an error, localStorage is not defined. Thinking about where this is happening, it makes sense. This method is run on the server, it has no idea what is stored in localStorage on the client; in fact, it doesn’t even know what “localStorage” is! So that’s not an option.

The server tries to execute localStorage.getItem('token') but throws an error, then a caption below explaining the problem.

So what’s the solution? There are a few, actually. You can get the client to initialize the Store instead but end up losing the benefits of SSR because the client ends up doing all the work. You can set up sessions on the server and then use that to authenticate the user, but that’s another layer to set up. What’s most similar to the localStorage method is using cookies instead.

Nuxt has access to cookies because they are sent with the request from the client to the server. As with other Nuxt methods, nuxtServerInit has access to the Context, this time as the second argument because the first is reserved for the store. On the Context, we can access the req object, which stores all the headers and other information from the client request. (This will be especially familiar if you’ve used Node.js.)

So after storing the token in a cookie instead (called “token,” in this case), let’s access it on the server.

import Cookie from 'cookie'

export const actions = {
 nuxtServerInit ({ dispatch }, { req }) {
   const cookies = Cookie.parse(req.headers.cookie || '')
   const token = cookies['token'] || ''
   if (token) return dispatch('user/load', token)
 }
}

A simple solution, but one that might not be immediately obvious. Learning to think about where certain actions are happening (client, server, or both) and what they have access to takes some time but the benefits are worth it.

Deployment

Deployment with Nuxt is extremely simple. Using the same codebase, you can create an SSR app, single-page application, or static page.

Server-side Rendered App (SSR App)

This is probably what you were aiming for when using Nuxt. The basic concept for deployment here is to run the build process on whatever platform you choose and set a few configurations. I’ll use the Heroku example from the docs:

First, set up scripts for Heroku in package.json:

"scripts": {
 "dev": "nuxt",
 "build": "nuxt build",
 "start": "nuxt start",
 "heroku-postbuild": "npm run build"
}

Then set up the Heroku environment using the heroku-cli (setup instructions here:

# set Heroku variables
heroku config:set NPM_CONFIG_PRODUCTION=false
heroku config:set HOST=0.0.0.0
heroku config:set NODE_ENV=production

# deploy
git push heroku master

That’s it. Now your SSR Vue app is live ready for the world to see. Other platforms have different setups, but the process is similar. The official deployment methods currently listed are:

Single-page Application (SPA)

If you wanted to take advantage of some of the extra features Nuxt provides but avoid the server trying to render pages, then you can deploy as an SPA instead.

First, it’s best to test your application without the SSR as by default npm run dev runs with SSR on. To change that, edit the nuxt.config.js file and add the following option:

mode: 'spa',

Now, when you run npm run dev, SSR will be turned off and the application will run as an SPA for you to test. This setting also makes sure no future builds will include SSR.

If everything looks fine, then deployment is exactly the same as for an SSR app. Just remember you need to set mode: 'spa' first to let the build process know you want an SPA.

Static Pages

If you don’t want to deal with a server at all and instead want to generate pages for use with static hosting services such as Surge or Netlify, then this is the option to choose. Just bear in mind that, without a server, you won’t be able to access the req and res in the Context, so if your code relies on that, be sure to accommodate it. For example, when generating the example project, the nuxtServerInit function throws an error because it’s trying to fetch a token from the cookies in the request headers. In this project, it doesn’t matter, as that data isn’t being used anywhere, but in a real application, there would need to be an alternative way to access that data.

Once that’s sorted, deployment is easy. One thing you will probably need to change first is adding an option so that the nuxt generate command will also create a fallback file. This file will prompt the hosting service to let Nuxt handle the routing rather than the hosting service, throwing a 404 error. To do so, add the following line to nuxt.config.js:

generate: { fallback: true },

Here’s an example using Netlify, which isn’t currently in the Nuxt docs. Just bear in mind that if this is your first time using netlify-cli, you will be prompted to authenticate:

# install netlify-cli globally
npm install netlify-cli -g

# generate the application (outputs to dist/ folder)
npm run generate

# deploy
netlify deploy dist

It’s as simple as that! As mentioned at the beginning of the article, there’s a version of this project here. There’s also official deployment documentation for the following services below:

Learn More

Nuxt is updating rapidly, and this is only a small selection of the features it offers. I hope this article encourages you to try it out and see if it could help improve the capabilities of your Vue applications, allowing you to develop faster and take advantage of its powerful features.

If you’re looking for more information, then look no further than Nuxt’s official links:

Looking to up your JavaScript game? Try reading The Comprehensive Guide to JavaScript Design Patterns by fellow Toptaler Marko Mišura.

This article is written by André Castelo and originally posted at Toptal

With the rise of mobile development and JavaScript frameworks, using a RESTful API is the best option to build a single interface between your data and your client.

Laravel is a PHP framework developed with PHP developer productivity in mind. Written and maintained by Taylor Otwell, the framework is very opinionated and strives to save developer time by favoring convention over configuration. The framework also aims to evolve with the web and has already incorporated several new features and ideas in the web development world—such as job queues, API authentication out of the box, real-time communication, and much more.

Laravel API Tutorial - Building a RESTful Web service

In this tutorial, we’ll explore the ways you can build—and test—a robust API using Laravel with authentication. We’ll be using Laravel 5.4, and all of the code is available for reference on GitHub.

RESTful APIs

First, we need to understand what exactly is considered a RESTful API. REST stands for REpresentational State Transfer and is an architectural style for network communication between applications, which relies on a stateless protocol (usually HTTP) for interaction.

HTTP Verbs Represent Actions

In RESTful APIs, we use the HTTP verbs as actions, and the endpoints are the resources acted upon. We’ll be using the HTTP verbs for their semantic meaning:

  • GET: retrieve resources
  • POST: create resources
  • PUT: update resources
  • DELETE: delete resources
HTTP verbs: GET, POST, PUT and DELETE are actions in RESTful APIs

Update Action: PUT vs. POST

RESTful APIs are a matter of much debate and there are plenty of opinions out there on whether is best to update with POSTPATCH, or PUT, or if the create action is best left to the PUT verb. In this article we’ll be using PUT for the update action, as according to the HTTP RFC, PUT means to create/update a resource at a specific location. Another requirement for the PUT verb is idempotence, which in this case basically means you can send that request 1, 2 or 1000 times and the result will be the same: one updated resource in the database.

Resources

Resources will be the targets of the actions, in our case Articles and Users, and they have their own endpoints:

  • /articles
  • /users

In this laravel api tutorial, the resources will have a 1:1 representation on our data models, but that is not a requirement. You can have resources represented in more than one data model (or not represented at all in the database) and models completely off limits for the user. In the end, you get to decide how to architect resources and models in a way that is fitting to your application.

A Note on Consistency

The greatest advantage of using a set of conventions such as REST is that your API will be much easier to consume and develop around. Some endpoints are pretty straightforward and, as a result, your API will be much more easier to use and maintain as opposed to having endpoints such as GET /get_article?id_article=12 and POST /delete_article?number=40. I’ve built terrible APIs like that in the past and I still hate myself for it.

However, there will be cases where it will be hard to map to a Create/Retrieve/Update/Delete schema. Remember that the URLs should not contain verbs and that resources are not necessarily rows in a table. Another thing to keep in mind is that you don’t have to implement every action for every resource.

Setting Up a Laravel Web Service Project

As with all modern PHP frameworks, we’ll need Composer to install and handle our dependencies. After you follow the download instructions (and add to your path environment variable), install Laravel using the command:

$ composer global require laravel/installer

After the installation finishes, you can scaffold a new application like this:

$ laravel new myapp

For the above command, you need to have ~/composer/vendor/bin in your $PATH. If you don’t want to deal with that, you can also create a new project using Composer:

$ composer create-project --prefer-dist laravel/laravel myapp

With Laravel installed, you should be able to start the server and test if everything is working:

$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>
When you open localhost:8000 on your browser, you should see the Laravel sample page
When you open localhost:8000 on your browser, you should see this sample page.

Migrations and Models

Before actually writing your first migration, make sure you have a database created for this app and add its credentials to the .env file located in the root of the project.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

You can also use Homestead, a Vagrant box specially crafted for Laravel, but that is a bit out of the scope of this article. If you’d like to know more, refer to the Homestead documentation.

Let’s get started with our first model and migration—the Article. The article should have a title and a body field, as well as a creation date. Laravel provides several commands through Artisan—Laravel’s command line tool—that help us by generating files and putting them in the correct folders. To create the Article model, we can run:

$ php artisan make:model Article -m

The -m option is short for --migration and it tells Artisan to create one for our model. Here’s the generated migration:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('articles');
    }
}

Let’s dissect this for a second:

  • The up() and down() methods will be run when we migrate and rollback respectively;
  • $table->increments('id') sets up an auto incrementing integer with the name id;
  • $table->timestamps() will set up the timestamps for us—created_at and updated_at, but don’t worry about setting a default, Laravel takes care of updating these fields when needed.
  • And finally, Schema::dropIfExists() will, of course, drop the table if it exists.

With that out of the way, let’s add two lines to our up() method:

public function up()
{
    Schema::create('articles', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->text('body');
        $table->timestamps();
    });
}

The string() method creates a VARCHAR equivalent column while text() creates a TEXTequivalent. With that done, let’s go ahead and migrate:

$ php artisan migrate

You can also use the --step option here, and it will separate each migration into its own batch so that you can roll them back individually if needed.

Laravel out of the box comes with two migrations, create_users_table and create_password_resets_table. We won’t be using the password_resets table, but having the users table ready for us will be helpful.

Now let’s go back to our model and add those attributes to the $fillable field so that we can use them in our Article::create and Article::update models:

class Article extends Model
{
    protected $fillable = ['title', 'body'];
}

Fields inside the $fillable property can be mass assigned using Eloquent’s create() and update()methods. You can also use the $guarded property, to allow all but a few properties.

Database Seeding

Database seeding is the process of filling up our database with dummy data that we can use to test it. Laravel comes with Faker, a great library for generating just the correct format of dummy data for us. So let’s create our first seeder:

$ php artisan make:seeder ArticlesTableSeeder

The seeders will be located in the /database/seeds directory. Here’s how it looks like after we set it up to create a few articles:

class ArticlesTableSeeder extends Seeder
{
    public function run()
    {
        // Let's truncate our existing records to start from scratch.
        Article::truncate();

        $faker = \Faker\Factory::create();

        // And now, let's create a few articles in our database:
        for ($i = 0; $i < 50; $i++) {
            Article::create([
                'title' => $faker->sentence,
                'body' => $faker->paragraph,
            ]);
        }
    }
}

So let’s run the seed command:

$ php artisan db:seed --class=ArticlesTableSeeder

Let’s repeat the process to create a Users seeder:

class UsersTableSeeder extends Seeder
{
    public function run()
    {
        // Let's clear the users table first
        User::truncate();

        $faker = \Faker\Factory::create();

        // Let's make sure everyone has the same password and 
        // let's hash it before the loop, or else our seeder 
        // will be too slow.
        $password = Hash::make('toptal');

        User::create([
            'name' => 'Administrator',
            'email' => 'admin@test.com',
            'password' => $password,
        ]);

        // And now let's generate a few dozen users for our app:
        for ($i = 0; $i < 10; $i++) {
            User::create([
                'name' => $faker->name,
                'email' => $faker->email,
                'password' => $password,
            ]);
        }
    }
}

We can make it easier by adding our seeders to the main DatabaseSeeder class inside the database/seedsfolder:

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call(ArticlesTableSeeder::class);
        $this->call(UsersTableSeeder::class);
    }
}

This way, we can simply run $ php artisan db:seed and it will run all the called classes in the run() method.

Routes and Controllers

Let’s create the basic endpoints for our application: create, retrieve the list, retrieve a single one, update, and delete. On the routes/api.php file, we can simply do this:

Use App\Article;
 
Route::get('articles', function() {
    // If the Content-Type and Accept headers are set to 'application/json', 
    // this will return a JSON structure. This will be cleaned up later.
    return Article::all();
});
 
Route::get('articles/{id}', function($id) {
    return Article::find($id);
});

Route::post('articles', function(Request $request) {
    return Article::create($request->all);
});

Route::put('articles/{id}', function(Request $request, $id) {
    $article = Article::findOrFail($id);
    $article->update($request->all());

    return $article;
});

Route::delete('articles/{id}', function($id) {
    Article::find($id)->delete();

    return 204;
})

The routes inside api.php will be prefixed with /api/ and the API throttling middleware will be automatically applied to these routes (if you want to remove the prefix you can edit the RouteServiceProvider class on /app/Providers/RouteServiceProvider.php).

Now let’s move this code to its own Controller:

$ php artisan make:controller ArticleController

ArticleController.php:

use App\Article;
 
class ArticleController extends Controller
{
    public function index()
    {
        return Article::all();
    }
 
    public function show($id)
    {
        return Article::find($id);
    }

    public function store(Request $request)
    {
        return Article::create($request->all());
    }

    public function update(Request $request, $id)
    {
        $article = Article::findOrFail($id);
        $article->update($request->all());

        return $article;
    }

    public function delete(Request $request, $id)
    {
        $article = Article::findOrFail($id);
        $article->delete();

        return 204;
    }
}

The routes/api.php file:

Route::get('articles', 'ArticleController@index');
Route::get('articles/{id}', 'ArticleController@show');
Route::post('articles', 'ArticleController@store');
Route::put('articles/{id}', 'ArticleController@update');
Route::delete('articles/{id}', 'ArticleController@delete');

We can improve the endpoints by using implicit route model binding. This way, Laravel will inject the Articleinstance in our methods and automatically return a 404 if it isn’t found. We’ll have to make changes on the routes file and on the controller:

Route::get('articles', 'ArticleController@index');
Route::get('articles/{article}', 'ArticleController@show');
Route::post('articles', 'ArticleController@store');
Route::put('articles/{article}', 'ArticleController@update');
Route::delete('articles/{article}', 'ArticleController@delete');
class ArticleController extends Controller
{
    public function index()
    {
        return Article::all();
    }

    public function show(Article $article)
    {
        return $article;
    }

    public function store(Request $request)
    {
        $article = Article::create($request->all());

        return response()->json($article, 201);
    }

    public function update(Request $request, Article $article)
    {
        $article->update($request->all());

        return response()->json($article, 200);
    }

    public function delete(Article $article)
    {
        $article->delete();

        return response()->json(null, 204);
    }
}

A Note on HTTP Status Codes and the Response Format

We’ve also added the response()->json() call to our endpoints. This lets us explicitly return JSON data as well as send an HTTP code that can be parsed by the client. The most common codes you’ll be returning will be:

  • 200: OK. The standard success code and default option.
  • 201: Object created. Useful for the store actions.
  • 204: No content. When an action was executed successfully, but there is no content to return.
  • 206: Partial content. Useful when you have to return a paginated list of resources.
  • 400: Bad request. The standard option for requests that fail to pass validation.
  • 401: Unauthorized. The user needs to be authenticated.
  • 403: Forbidden. The user is authenticated, but does not have the permissions to perform an action.
  • 404: Not found. This will be returned automatically by Laravel when the resource is not found.
  • 500: Internal server error. Ideally you’re not going to be explicitly returning this, but if something unexpected breaks, this is what your user is going to receive.
  • 503: Service unavailable. Pretty self explanatory, but also another code that is not going to be returned explicitly by the application.

Sending a Correct 404 Response

If you tried to fetch a non-existent resource, you’ll be thrown an exception and you’ll receive the whole stacktrace, like this:

NotFoundHttpException Stacktrace

We can fix that by editing our exception handler class, located in app/Exceptions/Handler.php, to return a JSON response:

public function render($request, Exception $exception)
{
    // This will replace our 404 response with
    // a JSON response.
    if ($exception instanceof ModelNotFoundException) {
        return response()->json([
            'error' => 'Resource not found'
        ], 404);
    }

    return parent::render($request, $exception);
}

Here’s an example of the return:

{
    data: "Resource not found"
}

If you’re using Laravel to serve other pages, you have to edit the code to work with the Accept header, otherwise 404 errors from regular requests will return a JSON as well.

public function render($request, Exception $exception)
{
    // This will replace our 404 response with
    // a JSON response.
    if ($exception instanceof ModelNotFoundException &&
        $request->wantsJson())
    {
        return response()->json([
            'data' => 'Resource not found'
        ], 404);
    }

    return parent::render($request, $exception);
}

In this case, the API requests will need the header Accept: application/json.

Authentication

There are many ways to implement API Authentication in Laravel (one of them being Passport, a great way to implement OAuth2), but in this article, we’ll take a very simplified approach.

To get started, we’ll need to add an api_token field to the users table:

$ php artisan make:migration --table=users adds_api_token_to_users_table

And then implement the migration:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('api_token', 60)->unique()->nullable();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn(['api_token']);
    });
}

After that, just run the migration using:

$ php artisan migrate

Creating the Register Endpoint

We’ll make use of the RegisterController (in the Auth folder) to return the correct response upon registration. Laravel comes with authentication out of the box, but we still need to tweak it a bit to return the response we want.

If APIs were in English, this is what an api authentication conversation would sound like

The controller makes use of the trait RegistersUsers to implement the registration. Here’s how it works:

public function register(Request $request)
{
    // Here the request is validated. The validator method is located
    // inside the RegisterController, and makes sure the name, email
    // password and password_confirmation fields are required.
    $this->validator($request->all())->validate();

    // A Registered event is created and will trigger any relevant
    // observers, such as sending a confirmation email or any 
    // code that needs to be run as soon as the user is created.
    event(new Registered($user = $this->create($request->all())));

    // After the user is created, he's logged in.
    $this->guard()->login($user);

    // And finally this is the hook that we want. If there is no
    // registered() method or it returns null, redirect him to
    // some other URL. In our case, we just need to implement
    // that method to return the correct response.
    return $this->registered($request, $user)
                    ?: redirect($this->redirectPath());
}

We just need to implement the registered() method in our RegisterController. The method receives the $request and the $user, so that’s really all we want. Here’s how the method should look like inside the controller:

protected function registered(Request $request, $user)
{
    $user->generateToken();

    return response()->json(['data' => $user->toArray()], 201);
}

And we can link it on the routes file:

Route::post(register, 'Auth\RegisterController@register);

In the section above, we used a method on the User model to generate the token. This is useful so that we only have a single way of generating the tokens. Add the following method to your User model:

class User extends Authenticatable
{
    ...
    public function generateToken()
    {
        $this->api_token = str_random(60);
        $this->save();

        return $this->api_token;
    }
}

And that’s it. The user is now registered and thanks to Laravel’s validation and out of the box authentication, the nameemailpassword, and password_confirmation fields are required, and the feedback is handled automatically. Checkout the validator() method inside the RegisterController to see how the rules are implemented.

Here’s what we get when we hit that endpoint:

$ curl -X POST http://localhost:8000/api/register \
 -H "Accept: application/json" \
 -H "Content-Type: application/json" \
 -d '{"name": "John", "email": "john.doe@toptal.com", "password": "toptal123", "password_confirmation": "toptal123"}'
{
    "data": {
        "api_token":"0syHnl0Y9jOIfszq11EC2CBQwCfObmvscrZYo5o2ilZPnohvndH797nDNyAT",
        "created_at": "2017-06-20 21:17:15",
        "email": "john.doe@toptal.com",
        "id": 51,
        "name": "John",
        "updated_at": "2017-06-20 21:17:15"
    }
}

Creating a Login Endpoint

Just like the registration endpoint, we can edit the LoginController (in the Auth folder) to support our API authentication. The login method of the AuthenticatesUsers trait can be overridden to support our API:

public function login(Request $request)
{
    $this->validateLogin($request);

    if ($this->attemptLogin($request)) {
        $user = $this->guard()->user();
        $user->generateToken();

        return response()->json([
            'data' => $user->toArray(),
        ]);
    }

    return $this->sendFailedLoginResponse($request);
}

And we can link it on the routes file:

Route::post('login', 'Auth\LoginController@login');

Now, assuming the seeders have been run, here’s what we get when we send a POST request to that route:

$ curl -X POST localhost:8000/api/login \
  -H "Accept: application/json" \
  -H "Content-type: application/json" \
  -d "{\"email\": \"admin@test.com\", \"password\": \"toptal\" }"
{
    "data": {
        "id":1,
        "name":"Administrator",
        "email":"admin@test.com",
        "created_at":"2017-04-25 01:05:34",
        "updated_at":"2017-04-25 02:50:40",
        "api_token":"Jll7q0BSijLOrzaOSm5Dr5hW9cJRZAJKOzvDlxjKCXepwAeZ7JR6YP5zQqnw"
    }
}

To send the token in a request, you can do it by sending an attribute api_token in the payload or as a bearer token in the request headers in the form of Authorization: Bearer Jll7q0BSijLOrzaOSm5Dr5hW9cJRZAJKOzvDlxjKCXepwAeZ7JR6YP5zQqnw.

Logging Out

With our current strategy, if the token is wrong or missing, the user should receive an unauthenticated response (which we’ll implement in the next section). So for a simple logout endpoint, we’ll send in the token and it will be removed on the database.

routes/api.php:

Route::post('logout', 'Auth\LoginController@logout');

Auth\LoginController.php:

public function logout(Request $request)
{
    $user = Auth::guard('api')->user();

    if ($user) {
        $user->api_token = null;
        $user->save();
    }

    return response()->json(['data' => 'User logged out.'], 200);
}

Using this strategy, whatever token the user has will be invalid, and the API will deny access (using middlewares, as explained in the next section). This needs to be coordinated with the front-end to avoid the user remaining logged without having access to any content.

Using Middlewares to Restrict Access

With the api_token created, we can toggle the authentication middleware in the routes file:

Route::middleware('auth:api')
    ->get('/user', function (Request $request) {
        return $request->user();
    });

We can access the current user using the $request->user() method or through the Auth facade

Auth::guard('api')->user(); // instance of the logged user
Auth::guard('api')->check(); // if a user is authenticated
Auth::guard('api')->id(); // the id of the authenticated user

And we get a result like this:

An InvalidArgumentException Stacktrace

This is because we need to edit the current unauthenticated method on our Handler class. The current version returns a JSON only if the request has the Accept: application/json header, so let’s change it:

protected function unauthenticated($request, AuthenticationException $exception)
{
    return response()->json(['error' => 'Unauthenticated'], 401);
}

With that fixed, we can go back to the article endpoints to wrap them in the auth:api middleware. We can do that by using route groups:

Route::group(['middleware' => 'auth:api'], function() {
    Route::get('articles', 'ArticleController@index');
    Route::get('articles/{article}', 'ArticleController@show');
    Route::post('articles', 'ArticleController@store');
    Route::put('articles/{article}', 'ArticleController@update');
    Route::delete('articles/{article}', 'ArticleController@delete');
});

This way we don’t have to set the middleware for each of the routes. It doesn’t save a lot of time right now, but as the project grows it helps to keep the routes DRY.

Testing Our Endpoints

Laravel includes integration with PHPUnit out of the box with a phpunit.xml already set up. The framework also provides us with several helpers and extra assertions that makes our lives much easier, especially for testing APIs.

There are a number of external tools you can use to test your API; however, testing inside Laravel is a much better alternative—we can have all the benefits of testing an API structure and results while retaining full control of the database. For the list endpoint, for example, we could run a couple of factories and assert the response contains those resources.

To get started, we’ll need to tweak a few settings to use an in-memory SQLite database. Using that will make our tests run lightning fast, but the trade-off is that some migration commands (constraints, for example) will not work properly in that particular setup. I advise moving away from SQLite in testing when you start getting migration errors or if you prefer a stronger set of tests instead of performant runs.

We’ll also run the migrations before each test. This setup will allow us to build the database for each test and then destroy it, avoiding any type of dependency between tests.

In our config/database.php file, we’ll need to set up the database field in the sqlite configuration to :memory::

...
'connections' => [

    'sqlite' => [
        'driver' => 'sqlite',
        'database' => ':memory:',
        'prefix' => '',
    ],
    
    ...
]

Then enable SQLite in phpunit.xml by adding the environment variable DB_CONNECTION:

    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_CONNECTION" value="sqlite"/>
    </php>

With that out of the way, all that’s left is configuring our base TestCase class to use migrations and seed the database before each test. To do so, we need to add the DatabaseMigrations trait, and then add an Artisancall on our setUp() method. Here’s the class after the changes:

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, DatabaseMigrations;

    public function setUp()
    {
        parent::setUp();
        Artisan::call('db:seed');
    }
}

One last thing that I like to do is to add the test command to composer.json:

    "scripts": {
        "test" : [
            "vendor/bin/phpunit"
        ],
    ... 
    },    

The test command will be available like this:

$ composer test

Setting Up Factories for Our Tests

Factories will allow us to quickly create objects with the right data for testing. They’re located in the database/factories folder. Laravel comes out of the box with a factory for the User class, so let’s add one for the Article class:

$factory->define(App\Article::class, function (Faker\Generator $faker) {
    return [
        'title' => $faker->sentence,
        'body' => $faker->paragraph,
    ];
});

The Faker library is already injected to help us create the correct format of random data for our models.

Our First Tests

We can use Laravel’s assert methods to easily hit an endpoint and evaluate its response. Let’s create our first test, the login test, using the following command:

$ php artisan make:test Feature/LoginTest

And here is our test:

class LoginTest extends TestCase
{
    public function testRequiresEmailAndLogin()
    {
        $this->json('POST', 'api/login')
            ->assertStatus(422)
            ->assertJson([
                'email' => ['The email field is required.'],
                'password' => ['The password field is required.'],
            ]);
    }


    public function testUserLoginsSuccessfully()
    {
        $user = factory(User::class)->create([
            'email' => 'testlogin@user.com',
            'password' => bcrypt('toptal123'),
        ]);

        $payload = ['email' => 'testlogin@user.com', 'password' => 'toptal123'];

        $this->json('POST', 'api/login', $payload)
            ->assertStatus(200)
            ->assertJsonStructure([
                'data' => [
                    'id',
                    'name',
                    'email',
                    'created_at',
                    'updated_at',
                    'api_token',
                ],
            ]);

    }
}

These methods test a couple of simple cases. The json() method hits the endpoint and the other asserts are pretty self explanatory. One detail about assertJson(): this method converts the response into an array searches for the argument, so the order is important. You can chain multiple assertJson() calls in that case.

Now, let’s create the register endpoint test and write a couple for that endpoint:

$ php artisan make:test RegisterTest
class RegisterTest extends TestCase
{
    public function testsRegistersSuccessfully()
    {
        $payload = [
            'name' => 'John',
            'email' => 'john@toptal.com',
            'password' => 'toptal123',
            'password_confirmation' => 'toptal123',
        ];

        $this->json('post', '/api/register', $payload)
            ->assertStatus(201)
            ->assertJsonStructure([
                'data' => [
                    'id',
                    'name',
                    'email',
                    'created_at',
                    'updated_at',
                    'api_token',
                ],
            ]);;
    }

    public function testsRequiresPasswordEmailAndName()
    {
        $this->json('post', '/api/register')
            ->assertStatus(422)
            ->assertJson([
                'name' => ['The name field is required.'],
                'email' => ['The email field is required.'],
                'password' => ['The password field is required.'],
            ]);
    }

    public function testsRequirePasswordConfirmation()
    {
        $payload = [
            'name' => 'John',
            'email' => 'john@toptal.com',
            'password' => 'toptal123',
        ];

        $this->json('post', '/api/register', $payload)
            ->assertStatus(422)
            ->assertJson([
                'password' => ['The password confirmation does not match.'],
            ]);
    }
}

And lastly, the logout endpoint:

$ php artisan make:test LogoutTest
class LogoutTest extends TestCase
{
    public function testUserIsLoggedOutProperly()
    {
        $user = factory(User::class)->create(['email' => 'user@test.com']);
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];

        $this->json('get', '/api/articles', [], $headers)->assertStatus(200);
        $this->json('post', '/api/logout', [], $headers)->assertStatus(200);

        $user = User::find($user->id);

        $this->assertEquals(null, $user->api_token);
    }

    public function testUserWithNullToken()
    {
        // Simulating login
        $user = factory(User::class)->create(['email' => 'user@test.com']);
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];

        // Simulating logout
        $user->api_token = null;
        $user->save();

        $this->json('get', '/api/articles', [], $headers)->assertStatus(401);
    }
}

It’s important to note that, during testing, the Laravel application is not instantiated again on a new request. Which means that when we hit the authentication middleware, it saves the current user inside the TokenGuard instance to avoid hitting the database again. A wise choice, however—in this case, it means we have to split the logout test into two, to avoid any issues with the previously cached user.

Testing the Article endpoints is straightforward as well:

class ArticleTest extends TestCase
{
    public function testsArticlesAreCreatedCorrectly()
    {
        $user = factory(User::class)->create();
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];
        $payload = [
            'title' => 'Lorem',
            'body' => 'Ipsum',
        ];

        $this->json('POST', '/api/articles', $payload, $headers)
            ->assertStatus(200)
            ->assertJson(['id' => 1, 'title' => 'Lorem', 'body' => 'Ipsum']);
    }

    public function testsArticlesAreUpdatedCorrectly()
    {
        $user = factory(User::class)->create();
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];
        $article = factory(Article::class)->create([
            'title' => 'First Article',
            'body' => 'First Body',
        ]);

        $payload = [
            'title' => 'Lorem',
            'body' => 'Ipsum',
        ];

        $response = $this->json('PUT', '/api/articles/' . $article->id, $payload, $headers)
            ->assertStatus(200)
            ->assertJson([ 
                'id' => 1, 
                'title' => 'Lorem', 
                'body' => 'Ipsum' 
            ]);
    }

    public function testsArtilcesAreDeletedCorrectly()
    {
        $user = factory(User::class)->create();
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];
        $article = factory(Article::class)->create([
            'title' => 'First Article',
            'body' => 'First Body',
        ]);

        $this->json('DELETE', '/api/articles/' . $article->id, [], $headers)
            ->assertStatus(204);
    }

    public function testArticlesAreListedCorrectly()
    {
        factory(Article::class)->create([
            'title' => 'First Article',
            'body' => 'First Body'
        ]);

        factory(Article::class)->create([
            'title' => 'Second Article',
            'body' => 'Second Body'
        ]);

        $user = factory(User::class)->create();
        $token = $user->generateToken();
        $headers = ['Authorization' => "Bearer $token"];

        $response = $this->json('GET', '/api/articles', [], $headers)
            ->assertStatus(200)
            ->assertJson([
                [ 'title' => 'First Article', 'body' => 'First Body' ],
                [ 'title' => 'Second Article', 'body' => 'Second Body' ]
            ])
            ->assertJsonStructure([
                '*' => ['id', 'body', 'title', 'created_at', 'updated_at'],
            ]);
    }

}

Next Steps

That’s all there is to it. There’s definitely room for improvement—you can implement OAuth2 with the Passportpackage, integrate a pagination and transformation layer (I recommend Fractal), the list goes on—but I wanted to go through the basics of creating and testing an API in Laravel with no external packages.

Laravel has certainly improved my experience with PHP and the ease of testing with it has solidified my interest in the framework. It’s not perfect, but it’s flexible enough to let you work around its issues.

If you’re designing a public API, check out 5 Golden Rules for Great Web API Design.

This article is written by André Castelo and originally posted at Toptal

About the Author: André Castelo is a web developer focused on PHP and JavaScript with experience developing apps with Laravel and CodeIgniter as well as APIs in Laravel and client-side single-page apps using AngularJS. He's equally comfortable working with a team or flying solo.

This article written by Fahad Munawar Khan and is originally posted at Toptal

 

Salesforce Einstein. The AI revolution is already transforming the consumer world.

Sometimes, it’s in everyday ways like product recommendations, and sometimes it’s in magnificent ways: Cochlear implants, which provide artificial hearing for those born completely deaf, have switched to AI for a superior end-user experience.

Artificial intelligence (AI) is the latest milestone in modern technology.

The AI revolution is leading to a smarter world, and this smarter world has been built on the mega-trends that we’ve all witnessed over the last 20 years: the web, the cloud, social, mobile, and the Internet of Things (IoT).

With cloud technology, we have, as developers, virtually unlimited computing and storage capacity, and it’s really that combination of massive data and massive computing power that’s leading to this revolution. Now that everybody is connected to each other and to everything in some way or another, all of these connections are generating orders of magnitude more data for the AI cloud to process than ever before.

You experience the AI cloud every day as a consumer. When you see a product recommendation on Amazon, a movie recommendation on Netflix, or a photo that’s automatically identified and tagged in your Facebook feed, you’re experiencing the power of AI.

Now wouldn’t it be great if the app you’re working on—whether it’s a Salesforce app or not—could somehow also provide these smarter, AI-powered experiences? For example, what if our business and our sales app could work together to tell us which leads are most likely to convert, or our service app could use the AI cloud to tell us which cases are likely to be escalated?

Unfortunately, for many teams, it seems too complex and expensive to apply AI to their app’s business process. First, it starts with data science and, to do data science, you have to collect and integrate all the required data. And then you need to do data wrangling, transforming the data so that you can use it for machine learning. And then, depending on your expertise, you may even need outside help from data scientists to build predictive models, maintain them, refresh them, and create an infrastructure that is trusted and secure and scalable. Then, after all that work, you have to take these predictions and put them into the context of the business user.

Enter Salesforce Einstein

Knowing that AI was often out of reach, Salesforce acquired companies like MetaMind (deep learning specialists), Implisit Insights (applying AI to the sales process specifically), and PredictionIO (machine learning and big data analytics) to help them build Salesforce Einstein.

Salesforce Einstein is AI for Salesforce, and it’s built right into the platform. As Einstein’s GM put it, “It takes the world’s number one CRM and makes it the world’s smartest CRM.” With Salesforce’s AI offering, you can now empower a company’s sales, service, marketing, and IT professionals to be their best by making every customer interaction faster, smarter, and more predictive.

Deep Learning: Einstein Vision and Einstein Language

Salesforce Einstein should bring the AI cloud within reach of developers. Maybe. But where should you start? The first thing to know is that AI has three major components:

  • Data
  • Algorithms
  • Computation

Big data in general has been a hot topic for the past couple of years. Everyone is excited to have new sources of data, new ways of analyzing it, and new ways of storing it.

This is going to be a big part of how we bring artificial intelligence into the enterprise but a lot of the AI development effort has been on the algorithm side. These are complex algorithms that are being built upon, expanded, and actually having new research from both the private and public sectors. You can be sure that AI cloud algorithms are going to continue to be innovative and continue to drive new features for your applications and for customer experiences.

The computation aspect you’ve probably heard of lately, too: GPUs, TPUs, new investments, and new research from all the best hardware companies are all going towards computing power, ensuring that these algorithms have the infrastructure they need to continue to be innovative and to be able to provide insight into your data.

Before we get into how you can develop something that leverages this technology, let’s dig into some more details of what you’ll be dealing with.

The Data

There are two forms of data to consider here: Structured and unstructured.

Structured and unstructured data.

Structured data includes your ERP data and the majority of your CRM data; it could be data coming out of IoT devices, for example. This type of data is already easily searchable by basic algorithms.

Unstructured data could be your image data, email messages, PowerPoint presentations, Word documents, etc. This is where deep learning and machine learning algorithms come in, vastly simplifying how we search through this type of data.

The Algorithm

Deep learning is a complicated term: A lot of developers and DevOps engineers get overwhelmed by it. They think they don’t have the infrastructure to handle neural networks. They think they need a PhD to sufficiently understand the state-of-the-art model to be incorporated in order to break it down into a more manageable thought process. Fortunately, knowing enough of it to be able to leverage it is a lot more accessible than that.

You only need to know about the input and output layers; all the really difficult work happens in the hidden layer, which is taken care of by the Salesforce AI cloud.

Let’s start this way: You have an input file. This could be an image, an audio file, or a text file. And you want to derive insightful output from it. Salesforce Einstein has a set of APIs which you can use to make this process really seamless: You don’t have to know anything about what happens in between.

With Salesforce Einstein, it is very easy for you to embed deep learning into your applications. It provides you with well-hosted infrastructure that manages your models as a service and thus takes care of any scalability needs. So it makes it easy for you to upload, train, and understand your model metrics, and in the end provide predictions in real time on a pre-trained model or a custom model that you create.

If even that sounds foreign to you, the next examples will quickly get you up to speed.

Computation: Einstein Vision

This is one of the deep learning services offered by Salesforce Einstein. Not all deep learning models or neural networks are equal: Specific architectures are used for specific problems. And in the case of computer vision, the AI cloud uses what is called a convolutional neural network, which means that each layer learns from the previous one. So when such a network is trained on image data, it rebuilds the image from the ground up to understand its different components. It will first look at an image’s smallest unit, the pixel, and then understand the edges, and then the next layer understands object parts or elements, and then eventually it gets to whole objects.

And that entire process is taken care of for you, so you can focus on the business value you can unlock for your clients with computer vision instead of on the process itself.

Einstein Vision can be trained to recognize objects in images.

Think about how the transportation industry could be transformed by using drones to monitor highways—no one would need to send a cleanup crew.

Or how CPG companies, instead of sending individuals to manually record the products on a shelf, could just take a picture and have it be automatically analyzed.

Or how consumer retail can be revolutionized with visual search, or how insurance companies can automate the triaging of claims, or how image processing can be leveraged by healthcare.

All such scenarios can be covered by Einstein Image Classification, which is part of Einstein Vision. All you need is a model, which is more or less just a set of classification labels.

Build a Custom Model

A custom model can predict the classification of new data based on a training dataset made of data with known classifications.

You can build your own custom models and then integrate these within your workflows, whether that’s a Salesforce workflow or an external application.

Building your own custom model involves just three steps:

  1. Create your own data set, based on what your custom model needs to do. Say you want to be able to tell the difference between three-door refrigerators and two-door refrigerators. You’ll need to collect a bunch of images of two-door refrigerators and put them in a folder, and then a bunch of images of three-door refrigerators and put them in another folder.
  2. Train your model. Now, whatever data sets you collected in the previous step, you upload them and the AI cloud will train the model based on that dataset. The fact that you already separated the images is all that’s needed for training. Once the new data model is trained, you will receive its ID.
  3. Use it for prediction! You can now get predictions on images that the model has never seen before. It’s as simple as making an API call using the new model ID.

Computation: Einstein Language

If images aren’t what you need to process, chances are you’re looking to train using text. For this, Salesforce’s AI cloud has Einstein Language, which is currently made of two services: Einstein Intent and Einstein Sentiment.

  • Einstein Intent is a general classifier of the natural language processing (NLP) type. It allows you to define your own classes and upload data that represents those classes.
  • Einstein Sentiment is a pre-trained model which is able to analyze human language to derive the feelings of the content and surrounding users’ statements and classify those into positive, negative, and neutral classes.
Einstein Language's model makes natural-language AI cloud training and classification easily accessible to your Salesforce Einstein app via an API.

Einstein Language services work just like our image classification example. Here, we will also define classes.

In the above example, the intent is about routing cases. Every time a case comes through, we want to analyze that and route it to the right department: Shipping, billing, product, sales…we can define as many classes as we need. But in the case of Einstein Sentiment, the classes are fixed, so we just have positive, negative, or neutral.

Once you have separated the data into different classes, you can train your models. Training the model is very easy with the provided API. Just like with Einstein Vision, once the model is trained, you’ll have your model ID and you’re ready to get predictions.

Salesforce Einstein: Off to a Smart Start

Now that you have a taste for the possibilities that Salesforce Einstein brings within your reach as a Salesforce developer, and how easy it would be to help your clients or employer leverage the AI cloud, getting started merely requires setting up an account. We look forward to hearing how you’re using the AI cloud to revolutionize your own app!

This article written by Fahad Munawar Khan and is originally posted at Toptal

 

About the Author:

Fahad is a Salesforce Certified Force.com developer with 5 years of experience working on various client engagements in the web technology area. He takes pride in creating solutions that not only satisfies the requirements, but also makes the best possible usage of all Salesforce platform features and resources.