Making Spark Your Own

Ahad L. Amdani • May 21, 2016

The Series – Table of Contents

An Overview

Introduction to Spark
Spark Up What You Have

The Backend

The Spark Philosophy
A Closer Look at the Innards of Spark
Making Spark Your Own


Contents-at-a-Glance

  1. Introduction and TL;DR
  2. “Why customize Spark?”
  3. Configuring Stripe/BrainTree
  4. Customizing plans & subscriptions
  5. Customizing views and using Vue components
  6. All the other things (vue-router/SPA)

Introduction and TL;DR

TL;DR. Customizing Spark is fairly straight forward after you make some quick decisions about using Vue or not. Essentially, you’ll want to backup your working installation first. Then, you want to configure your payment provider in your .env file via the appropriate tokens for either Stripe or Braintree. You will follow-up, quite appropriately, by updating your vendor and product details/information, as well as your plans and subscriptions in the App\Providers\SparkServiceProvider class. For presentation to the user, you’ll update your views in the resources/views/vendor/spark directory. For developer joy, you can also modify the behaviors of the existing Vue components in the resources/assets/js/components directory, and add your own (don’t forget to require them in your resources/assets/js/app.js file), or go with an existing view engine. Lastly, don’t forget to update your CSS via the /resources/less directory, where you can directly modify spark.less, introduce your own with styling, or utilize the bootstrap default variables.less. Otherwise, good luck!


First and foremost, you should be aware that this article is a part of Leo Sjöberg’s tutorial series, Laravel Spark: A Crash Course, and this time around, we’re going to focus on customization so you can see how to make Spark your own. It’s not frightening, so don’t be afraid. It’s not worrisome, so don’t worry. It’s fairly straight forward, unlike other things you can try to do with Spark that are nearly a nightmare, like integrating Spark into an existing application (shameless, I know). I also want to provide special thanks to Darek Wędrychowski who has been working with me on our Spark project for a client and who contributed heavily to the content found in this tutorial.


There are actually two types of customization that can be achieved with Spark — client-side, and server-side. We’re going to be primarily focused on client-side customization today, and any back end items that need to be sort of checked off to provide your user with a great experience. Before we do anything else — even delving into why we should customize Spark (I know, why are we even answering this question — you wouldn’t be here unless you wanted to know how because you already had a why!) — we’re going to backup our source code and our database. Because backups are fun, and helpful and so you have a “restore point” to go back to if things should go horribly awry. Although I’m sure I don’t need to tell you that, you’ve already got it covered, because you’ve setup a daily process to backup your code and your data. Right? And because you’ve got source control setup and you know how to properly branch and when to commit, so you never lose any more than, say, an hour’s worth of work. Right? Sure you do. I’ll just wait here while you take the necessary steps.. I mean, agree with me because you’re phenomenal and we can move on to the next topic.

“Why customize Spark?”

Well, you’ve all got your reasons, else you wouldn’t be here, but let me showcase it to the world that I can write a bunch of reasons why you should customize the Spark boilerplate.

  1. Users want an experience that matches the look and feel of the rest of your application (assuming you don’t just use Spark’s look and feel, even though it is awesome).
  2. You definitely want to have payments coming to you. I mean, if you don’t, e-mail me, and I can supply you with the credentials necessary for you to make those payments swing my way. Heck, I’ll even write the code for you. Just cause I’m a nice guy.
  3. Your components may vary — whether you use Vue, React, Angular, some other library or none of the above, you’re going to want a good development experience, and you’re going to want to know how to modify the existing Spark Vue components in case what’s already good out of the gate really needs to be your kind of great.

I mean, I could go on, but the above list should have already convinced you — you know, beyond your own reason for being here — that Spark can heavily benefit you by customization.

Configuring Stripe/BrainTree

Now, assuming we’ve made a backup of our code and our data, we’re moving forward. In case you haven’t, go back and do that. Then, locate your .env file and take a look at the tokens that are there by default. You can keep either the Stripe or the Braintree tokens, and populate them. The default tokens, from my other article (still no shame):

The AUTHY_SECRET token is for your 2FA, so that’s pretty much only relevant if you need that functionality — otherwise, you can ignore it. Refer to Stripe’s documentation or Braintree’s documentation for your respective provider if you want to do some of the more crazy/advanced stuff, but essentially, it’s as simple as signing up for an account from the provider if you haven’t already, taking the keys provided, and populating them in the .env file for the proper tokens. For the BRAINTREE_ENV token you’re more than likely going to want to start with sandbox as your value. The term “Private Key” in Braintree is your BRAINTREE_SECRET token and the term “Public Key” in Braintree is your BRAINTREE_KEY — it only seems obvious if you consider the words ‘private’ and ‘secret’ — and lots of people don’t. So… there you go.

Then, you want to login to your respective portal (I used Braintree) and proceed to the next section of this tutorial. It’ll be helpful to have the payment portal open when we’re customizing plans and subscriptions.

Customizing plans & subscriptions

When you get to this step, you’re going to want to make sure that two things line up — your payment portal’s plan ID for each subscription and your plan’s plan ID in the Spark plan constructor for that subscription:

1<?php
2 
3Spark::plan(‘Plan Name Here’, ‘plan-ID-here’)
4 ->price(90)
5 ->yearly()
6 ->features([
7 ‘feature 1',
8 ‘feature 2',
9 ‘feature 3',
10 ]);

You can create monthly plans, annual plans, and a free plan. A simple trick is to have the same plan name in Braintree for the monthly and the annual, but simply append a ‘-monthly’ or a ‘-yearly’/‘annually’ to the end of the plan ID to signify the difference. For the tutorial, I just went through and created 6 plans to represent 3 subscriptions with a monthly and an annual option.

Obviously everyone’s pricing model is different, but if you’re going to have recurring subscription model, typically you want to have some sort of a discount on your annual plan. I’ve generally seen 2 months of discount so that it makes your annual a nice 10X multiple of your monthly plan.

Don’t forget to look at https://spark.laravel.com/docs/1.0/billing to review the documentation outside of the code and for any specific details, including for some neat tips and tricks, such as site-wide coupons how to deal with European VAT, as well as swapping to team-based billing over individual user billing.

I plan on coming back to this article and seeing the most requested features that you’d like to see a quick guide on and appending them to this section.

Customizing views and using Vue components

You should be familiar with the views provided by default in Spark, and there’s a great reference in the documentation for Client Customization that you can review here. But even better for us, there are a few parts of Spark view layer that we may want to reuse. Among them are tabs layout, modals, notifications and the user dropdown.

With respect to the friendly-looking and responsive-feeling tabs in Spark, the problem is, Spark’s own semi-router is heavily integrated with these tabs. While the tabs are nice, we can’t use them for all of our navigation across the site, right? But if we wanted that snappy responsiveness, we would be forced to. Spark uses bootstrap and CSS magic to give us that nice, smooth and crisp transitioning. However, if we want pretty much any other kind of layout, we’ll have to switch away from the Spark routing/CSS magic. It’s actually written to manage tabs in particular, so if we want to have routing for anything else, we’re left with writing it ourselves or switch to a different router. Spark is designed to handle its own routing, rather than letting the default Laravel router take care of things. To use existing routers for Vue (such as vue-router, voie and vue-director), we need to give the router control over the main application component. In order to do this, we have to initiate this component from the router’s level, which makes sense cause routing should be at the top of everything. We’ll get to more of that later.

The Spark support modal is, more or less, a straightforward bootstrap modal. Spark provides Vue functions to display it as well as hide it, and we can leverage its code to make our own components. Often, we’ll want to integrate it with the SparkForm object, documented here, to show a form in a modal, just like Spark is doing for their support modal.

While we’re discussing the modal with support form, people may want to tweak Spark emails, like we wanted to. Spark provides email templates for some of the emails it sends, but not for the rest. It goes as far as using the Mail::raw function for sending some of the emails, which sends plain text by default. In this case, people can use swap to substitute their own handlers (read more about this in a previous article here). Speaking of swapping, it is recommended by the docs to use Spark::swap, but no clear guidelines have been surfaced around that with respect to an optimal place to handle that. Doing that across the application seems counterproductive, so some guidelines around this would be appreciated. *ahem* Move along, move along, nothing to see here. *cough*

Side note from Leo, owner of Laratips: it's not officially stated in the docs, but having talked to Taylor over in Larachat about this, the recommendation is using swap and placing the statements in a service provider.

We can keep utilizing the provided SweetAlert notifications for actions or write our own notifications component, which is what Darek and I ended up doing.

Spark provides basic Vue settings, but the developer is supposed to install vueify by himself. Vueify gives us single file components with the .vue extension. Since Spark doesn’t use them, we’ll want to write our own resources architecture to house the javascript files written for our Vue components. In the case of two of our Spark applications, we went with just one separate folder for our application (swg-components, in this example). However, we recommend you do subfolders such as in the /resources/views folder.

In your custom component folders, you can have a separate bootstrap.js file, which needs to be included in Spark’s bootstrap.js file. The bootstrap.js in /resources/assets/js/components requires both spark-components/bootstrap file and the appropriate file for swg-components, so that we don’t have to deal with the spark-components folder.

There is a global Spark object, which we can use in our Vue components. We decided not to use it, but to create a separate application-specific object that we require in our components. So we have (in our case, you can name yours whatever you want) swg.js file in the /resources/assets/js/swg-components folder and define our object there. It manages the application state as well as state for additional features like flash messages, so we don’t have to write all of the JavaScript object methods in the app.blade.php file.

Remember, you can always reference the Vue documentation here if you have any questions around how to use Vue or write your own components. Not that you need or read any documentation. Right? *Busts out his best Kevin Spacey/Lex Luthor impersonation* WRONG!!! Real devs know how to RTFM!

One final note about jQuery and Spark. There’s an order of execution problem you may encounter if you follow the convention of including all of your scripts in the body rather than the head of the HTML document. Our approach was to provide two sections from our layout file which would allow you to include the relevant sources in the head of the document as well as in the body of the document. It’s all about the execution, and your negative attitude ain’t helpin’ any! You’ve got to belieeeeeve!!!

All the other things (vue-router/SPA)

While this isn’t strictly necessary to this tutorial on how to customize your Spark installation, I thought it would be helpful to include a brief primer on how to Vue-ify your application with vue-router so you can build something closer to a Single Page Application (SPA) with a more responsive feel to it. Here’s a few quick steps, provided by Darek on how to do this:

Step 1 — We follow the steps described here: http://router.vuejs.org/en/installation.html and here: http://router.vuejs.org/en/basic.html. I did that in the main app.js file, but potentially it will work if we move it away from there.

Step 2 — We have to change the way we initialize Spark so that it can work under the control of vue-router. Spark is by default initialized with:

1var app = new Vue({
2 mixins: [require(‘spark’)]
3});

Whereas vue-router will need a component constructor instead, which looks like this:

1var app = Vue.extend({
2 mixins: [require(‘spark’)]
3});

Step 3 — Now that we modified the constructor for Spark, we need to make the main Spark mixin actually work as the constructor. Spark provides a nice way to overwrite any of its Vue components by tweaking files in /resources/js/spark-components folder, which are then required in bootstrap.js. We need to tweak a file which is not included here, but nothing is lost.

First, let’s copy the spark/resources/assets/js/spark.js file into resources/assets/js folder. We can rename it to spark-with-vue-router.js to remember why we did it.

Then, let’s change the path to mixin in app.js:

1var app = Vue.extend({
2 mixins: [require(‘./spark-with-vue-router’)]
3});

And finally, we can do the magic in our new file. The module needs both el and data to be a Vue instance. So let’s make them look like this:

1el() {
2 return ‘body’
3},
4data() {
5 return {
6 user: Spark.state.user,
7 teams: Spark.state.teams,
8 currentTeam: Spark.state.currentTeam,
9 loadingNotifications: false,
10 notifications: null,
11 supportForm: new SparkForm({
12 from: ‘’,
13 subject: ‘’,
14 message: ‘’
15 })
16 }
17}

Step 4 — What’s left is to add the router view into /resources/views/vendor/spark/layouts/app.blade.php:

1<!-- Document Content -->
2<div class=”row”>
3 <section>
4 <div class=”col-xs-12">
5 <router-view></router-view>
6 @yield(‘content’)
7 </div>
8 </section>
9</div>

That’ll be all! With that, we can freely use vue-router in our Spark application.

One last note from the author: I wanted a catchy closer, but this is as good as you’re going to get after you’ve tried doing this at least once: help me, help me, I’m all out of lies.. and ways to say you di..er.. good bye!