You should for sure be setting far-out cache headers on your assets like CSS and JavaScript (and images and fonts and whatever else). That tells the browser “hang on to this file basically forever.” That way, when navigating from page to page on a site — or revisiting it, or refreshing the page — the browser doesn’t have to download it again which produces way faster page loads. It’s massively important for web performance, so do it!
But how do you force the browser to get a fresh version of the file? Well, there are a bunch of ways. Check out that blog post for more. But here’s one that I’ve used just recently that I wanted to document.
The trick is to change the query string
There was an era where the prevailing wisdom was that changing the query string wasn’t enough, but even then it, the reasons it wouldn’t work were pretty much edge cases. These days, changing the query string is fine (assuming you don’t change the default behavior, services like Cloudflare let you do it).
So, one day you ship it like this in your HTML:
<link rel="stylesheet" href="style.css?v=1" />
Then you change that query string to break the cache when you need to:
<link rel="stylesheet" href="style.css?v=2" />
The HTML, by the way, is either not cached or cached for a much shorter amount of time, so changes to HTML will be seen.
I sometimes do it by hand
For many years, I busted cache on this very site by setting a PHP variable and using it to break assets, like…
Hey that works, but it was me hand-manipulating that variable. I would sometimes forget to do it, and even if I did remember, I sort of resented having to do it.
Automating version busting with Gulp
I’m using a Gulp-powered build process at the moment on this site, which does all the classic stuff: Sass, Babel, file concatenation, live reloading…
It occurred to me I might as well have Gulp do the query-string changing whenever changes are made to CSS or JavaScript. JavaScript has a .replace() method, and that’s available in Node/Gulp easily with the gulp-replace plugin.
I make a task. When I call it, it looks in my header filer for the string cache_bust= plus some value, and replaces it with a new randomized string based on the date and time.
I do the same thing in a separate task when JavaScript files are editing and compiled.
It’s still a little dumb
Notice that I’m changing the query string on all the CSS assets every time any of them changes. That’s not as efficient as it could be. I should probably be changing the query string only on the changed files.
I’ll get to it eventually. Sometimes you just gotta baby-step your way to better solutions over time.
This is just one way! There are other Gulp plugins just for this. Other build systems have different approaches. This approached happened to work well for me and my exact needs at the time. Feel free to share your strategy!
Every day in my work helping grow digital agencies and Fortune 500 brands, I hear countless companies struggle with how to discuss, interact with, and grow their client’s brand, leaving dollars on the table and creating problems along the way. The agency owner offers their perspective, shares why branding is important, but usually lacks the conversational skills to navigate the need. And as a result, it’s not just the client that suffers. Sure, their brand doesn’t grow, but the agency doesn’t either.
The Typical Logo Scenario
One of the top problems I hear from agency owners is how to address branding in their scope of services or even how to bring it up. Usually, clients are coming to them with little to no investment in their branding, and the branding discussion usually doesn’t happen until after the project is signed. They don’t have the words to justify what they’re saying to the client or even to point out the “why” behind the “what.”
It’s a touchy subject no matter how you slice it
Usually the client goes to hand over what few branding assets they have at the start of the project. Then the agency is stuck. Do they simply “clean it up” and miss the opportunity to strategically help their client? How do you tell a new client that their brand assets are sub-par? How do you approach a client about a redesign when they didn’t approach you for that as part of the job? It’s a touchy subject no matter how you slice it.
This, of course, throws the project off-course, generates scope creep, and adds unnecessary anxiety. You may not have the time or resources to address it, and your client wants everything to be successful while expecting something “extra” thrown in. You’re not getting paid for it, but you feel like you have to address the ugly branding since your name is on the site credits.
So, What Do You Do?
Typically, you’ll pitch them a modest dollar amount of time, they agree, and you both move forward by picking a more modern color scheme, a cleaner typeface, and possibly a logo refresh. You try to get inside the client’s head and find something that resonates with them. It turns an adventure into the subjective minutiae of selection, with the client nit-picking about how they hate circles or don’t like the color blue. In the end, the client says they’re happy and everyone moves on.
But so much is wrong with this scenario. The real issue here isn’t about the client’s lack of branding initially, how you tacked on an attempt to modernize it, or that you don’t have the resources to do it. It’s not just when you addressed it, it’s also how you addressed it.
What Agencies Are Missing
If there’s one thing that’s missing from the arsenal of digital agency owners, it’s a solid understanding of branding – one that’s solid enough to convince the client of the investment on the front end, and one that during the process, solidifies the agency owner’s expertise as a strategist and partner.
A lot of digital agencies think that effective branding is a beautiful logo. While a logo is important, it’s simply one of several visual and verbal market-based assets that comprise the client’s Distinctive Brand Assets (more on that later). Most agencies are trying to tackle branding by cleaning up the logo alone, and in the process, are not helping their clients grow and succeed, and end up missing out on a larger amount of success, for both their agency and their client.
With branding only having developed as a commercial industry in the past century, it has undergone significant growth, debate, and superfluous opinion – with lots of “experts” out there. And with most agency owners and designers having gone out on their own, they’ve inherited a broken model, and not all the facts. In fact, what every digital agency needs before broaching the subject with a client is an updated understanding of how brands actually function, grow, and scale.
The Secret is Brand Science
The secret that top-performing web and digital agency owners know (that you might not) is that there is, in fact, evidence-based metrics to branding. They exist, and formally, it’s called “brand science,” and informally, it’s talking about the elements of branding in a new way, but with some boundaries. Those that are using brand science are able to help their clients grow their brand, increase their success, and ultimately increase their own.
Brand Science is simply the branding side of evidence-based marketing, making branding and design decisions based on metrics and well, science. There’s a bit of economics, psychology, and consumer behavior in there too, but the basics are easy to master, and the results are well worth it.
If you learn how successful brands actually grow, the logo conversation, the resource issues, and the client back and forth goes away. In fact, bad clients even start going away. Most web agencies didn’t get into business with the intent of working on branding and are uncomfortable with the subject, but it’s the truth: in order to succeed as a digital agency, no matter where or how you got your start, you have to upgrade your understanding of branding to brand science.
Distinctive Brand Assets
If you didn’t do too good, or even pay attention, in school during science class, don’t let the word “science” scare you off. Brand science is simply evidence-based marketing and research-based support for making branding and design decisions. That means, making design decisions based on research, and marketing decisions based on laws that are actually proven and making these a part of your agency’s service offerings as soon as possible.
If you’re a real go-getter, you can read more about these in Byron Sharp’s book, “How Brands Grow.” For the rest of us, keep reading.
Luckily for you and me, the marketing researchers at Ehrenberg-Bass Institute of Southern Australia have done decades of research into how buyers buy and how brands compete and grow and discovered that the best way to grow a brand is through creating higher mental and physical availability through creating distinct visual and verbal market assets, called Distinctive Brand Assets (DBAs).
Let’s step out of the web world for just a moment. Coca-Cola has its own DBA’s. In fact, red is the dominant color in the soft drink category. Other competitors or even generic brand name knock-off colas may use red, but they don’t have the some of the other signature DBAs, such as the brandmark’s typeface, the signature bottle, or their advertising style. There’s even the jingle, “always Coca-Cola,” as well as their tagline, as well as the polar bears, the curvey swoosh overlayed on photos, and the color combinations of red, black, green, and white they use to canonize the family of products.
These DBAs are specific to the soft drink category and don’t have associations outside. CVS and Target are also red but don’t compete mentally with Coca-Cola, and as a result, each category has its own plethora of associations to discuss. Your job is to ensure that your client has a palette of DBAs formulated within the insights of their category that they can use on their website which can translate to every other part of their business.
There are some additional principles, laws, and metrics in there too, but as a primer for brand science, this is the biggest idea.
Brand Science, Explained
Think of it like this: scientifically, branding is like the movie Inception plus Total Recall – it’s the on-going strategic business approach of creating memories for people to recall. Brand science calls these “cognitive associations.” The brand with the most famous and unique associations and networks at the top of the consumers’ minds has the highest mental availability. They then purchase based on how physically available that product, good, or service is.
So when initially talking to the client, the goal is to create the most mental networks, associations, and memories possible so they can be recalled quickly, connectedly, and most importantly, first.
The Number One Way to Grow a Brand
The number one way to create these associations is by creating distinctive market assets with a palette of unique, memorable and famous sounds, colors, characters (celebrities, spokespeople, cartoons), words, word combinations, color, color combinations, stories, common stylistic elements, photography, and yes, even logos. Together, these DBAs are a palette to be used in a variety of ways to create, cue, and refresh these associations.
capturing the complete landscape of the category is imperative
The goal of these market assets is to be both distinct and memorable. This is where it’s important to research the whole category, not just a few competitors. Brands, as a whole, compete against all brands in the category and also other brands their size. So this means when attempting to get insights into designing a new brand identity or refresh, capturing the complete landscape of the category is imperative. The more assets your client has that are both famous and unique within their category, the more associations they can have, the higher the mental availability, which is the end goal.
If you discover that a category is predominantly blue and green, always uses sans serif typefaces, always tends to use objective, product-focused copy, and is overall focused on practicality, you can interpret the data, gather insights, and find out why some of these things are as such, and from there, innovate.
How Brands Grow
Now that we’ve discussed Distinctive Brand Assets. We need to know how to use them.
According to Sharp, we make our lives unnecessarily difficult by handicapping ourselves with unfounded theories, anecdotes, and metaphors. There are some pretty hard hitters here. For example, there’s no evidence to suggest that consumers want a relationship with brands, that brand commitment and loyalty are just wishful thinking, and that the whole exercise of creating brand personalities is even a productive endeavor.
7 Rules for Brand Growth
Let’s replace our complicated theories of marketing, and brand infographics, with seven scientifically derived rules for brand growth.
Continuously reach all buyers of the category: Communicate to both light, infrequent, and frequent buyers. Avoid being silent in communication and distribution.
Ensure the brand is easy to buy: The best brands have universal appeal, so communicate how the brand fits with the users’ lives, based on inspiration and needs corresponding to the product/brand, not demographic details.
Get noticed: Grab their attention and focus on brand salience to prime the users’ minds. Remember, unseen is unsold, so stay seen, and make sure they’re attracted to it.
Refresh and build memory structures: Respect existing associations that make the brand easy to notice and easy to buy.
Create and use distinctive brand assets: Use sensory cues to get noticed and stay top of mind. This is where you use the DBA Palette.
Be consistent: You should avoid unnecessary changes, whilst keeping the brands fresh and interesting.
Stay competitive: You should keep the brand easy to buy and avoid giving excuses not to buy (i.e. by targeting a particular group)
How Can You Succeed?
If you want your client to succeed, you’re going to have to make sure that DBAs are part of the conversation from day one. This presents the opportunity for you to ensure your client is getting an expert to diagnose their business, not just another web agency.
So, when a client knocks on your door and barely has a logo to offer, it’s an opportunity to position yourself as an expert, using brand science to justify the importance of considering developing more brand assets to utilize on his/her website, and for any additional needs he/she may have as a set of assets to invest in.
Addressing branding as part of the strategy from the first interaction will have massive benefits for your agency and life. In the immediate term, you’ll start marking more money, which means more profit and success in your business.
Think about how freeing it would be to eliminate clients who think “their logo is just fine,” or expect you to ninja some magic for them without paying for it. Think about becoming positioned even more as the expert when presenting your solutions to the client. Think about how much better you’ll feel putting your name on the site credits or how much more confident you’ll feel having that client in your portfolio. The initial effects are significant.
It’s also not just the agency who benefits. The client does in immense ways. By ensuring they have a DBA palette of assets, the client is now able to use those market assets to grow their mental and physical availability. They’re able to focus their efforts on becoming a leader in their category, and are able to see the big picture, and how the website is part of it. And with client growth, comes more agency growth, and the ability to be part of it.
But there’s one benefit that is more important than all the others. By learning about the importance of DBAs, I see agency owners go from a place of insecurity to a place of confidence. Everything changes. Agency owners go from frustrated and flustered, to educated and empowered. They’re able to diagnose with confidence that the client’s brand is weak, and can make recommendations immediately to make brand design and strategy packages part of the website, leading to a more successful relationship in the long run.
Ionic has recently added support for React; so now, React developers can get the advantages of Ionic to build hybrid mobile apps and progressive web apps (PWAs). In this post, we’ll show you how to get started using Ionic with React by building a simple demo app from scratch.
Prerequisites
In order to properly follow this tutorial, you’ll need the following prerequisites:
recent versions of Node.js and npm installed on your system,
working knowledge of TypeScript and React.
You can check that you have the latest Node.js version (v10) installed by running the following command:
$ node -v
Introducing React And Ionic
Let’s start with brief introductions to both React and Ionic.
“React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called ‘components’.”
React focuses on building UIs and doesn’t provide any built-in tools for the common tasks required in web development, such as fetching remote data and routing, so you’ll need to use some existing third-party libraries for these tasks.
“Ionic Framework is the free, open-source mobile UI toolkit for developing high-quality cross-platform apps for native iOS, Android, and the web — all from a single codebase.”
Basically, it’s a set of UI components that you can use with plain JavaScript or any popular front-end framework or library, such as Angular, React or Vue, to build a hybrid mobile app and PWA.
In this tutorial, we’ll see and use some Ionic UI components such as the following:
IonMenu: With this, a navigation drawer will slide in from the side of the current view.
IonToolbar: These top bars are positioned above or below the content.
IonHeader: This parent component holds the toolbar component.
IonContent: This component provides a content area, with methods to control the scrollable area and other things. You need only one content component inside a single view.
IonList: This component contains items with similar data content, such as images and text. It’s made up of IonItem objects.
IonItem: This component may contain text, icons, avatars, images, inputs and any other native or custom element.
IonButton: This component provides a clickable element, which can be used in a form or anywhere that needs simple, standard button functionality.
Installing Ionic CLI v5
Ionic’s command line interface (CLI), version 5, has support for creating Ionic projects based on React. So, let’s get started by installing the tool from npm.
Open a CLI, and run the following command:
$ npm install -g ionic
At the time of writing, Ionic’s CLI v5.2.3 is the latest.
Note: *According to how you installed Node.js in your system, you may need to add sudo before your command in macOS or Linux or run the command prompt as administrator in Windows if you get any permission errors. You can also simply fix your npm permissions or use a tool such as nvm.*
Next, install Cordova Resources (which is used to generate Cordova resources locally) and Native Run (used to deploy app binaries to devices):
$ npm install -g cordova-res native-run
These are required only if you want to test your application on a real mobile device or emulator.
Creating An Ionic And React Project
Now, let’s create a project based on React. Go back to your terminal, make sure you are in your working directory, and run the following command:
$ ionic start myApp --type=react
We use --type=react to generate a project based on React. You’ll next need to choose a starter template from the available ones. Let’s pick sidemenu for a starter template with a side menu and navigation.
After generating the project and installing the dependencies, you can serve your app locally using the following commands:
$ cd ./myApp
$ ionic serve
Your app will be available from the http://localhost:8100 address, and you can actually use your web browser to start playing with it.
Ionic is called a hybrid mobile framework because it makes use of web technologies that were originally designed to create web apps, along with a native container (Cordova or Capacitor), to build mobile apps without using native technologies for the target platforms, such as Java or Kotlin for Android or Swift for iOS.
Because your mobile app is actually a web application, you can do most development by testing in a web browser without using an emulator or a real mobile device, except for testing native device features such as the camera or the SQLite storage, in case you’ve used them in your app. In fact, it’s even possible to use certain techniques to mimic the plugins that provide the native features and do the entire testing during development in your web browser.
Cleaning Our Project
We have the app’s basic structure, with two pages (home and list) and a menu. Let’s remove the list page since it’s just boilerplate code.
First, remove the src/pages/List.tsx file, then open the src/App.tsx file, and remove the entry for the list page from the appPages array:
The App component is the root component that gets rendered by our application. If you open the src/index.tsx file, you’ll find the following code:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
The render() method is used to render a React element into the DOM in the supplied root element.
Theming The App
Having created, served and cleaned our Ionic project, let’s now see how we can change the colors of the UI so that it looks more professional.
Let’s get started with the side menu. Open the src/components/Menu.tsx file, and add a color attribute with a primary value to the IonToolbar, IonContent, IonList and IonItem UI components:
Ionic provides some default colors (primary, secondary, tertiary, success, warning, danger, light, medium and dark) that can be used to change the color of UI components. A color can be applied to an Ionic component in order to change the default colors using the color attribute. See “Colors” for more information.
These colors have default values, but you can customize them via some predefined CSS variables. See “Modifying Colors“.
This is a screenshot of our menu:
Next, let’s change the color of the Home page. Open the src/pages/Home.tsx file, and set the color attribute of the IonToolbar and IonContent components to primary:
We’ll see how to install Axios and consume a third-party RESTful API in our application, and we’ll also see how to display the fetched data using Ionic card and list components.
Having themed our application, let’s now see how to fetch data using Axios. We’ll use the third-party API available from NewsAPI.org.
First, we need to grab an API key, so that we can communicate with the API. Go to the registration page, enter your information, and register an account. You’ll be given an API key; note it, and let’s continue.
Head back to your terminal, and run the following command to install Axios:
$ npm install axios --save
Next, open the src/pages/Home.tsx file, and start by importing Axios and IonButton:
import {
IonButton
} from '@ionic/react';
import axios from 'axios';
Next, define the API_KEY and URL constant variables:
In the URL variable, we’ll add an endpoint to get the top headlines from our source, TechCrunch. You can use any source you want from the available sources.
Note: Make sure to put your own API key in the API_KEY variable.
Next, define the fetchArticles() method as follows:
We simply call the axios() method to send a GET request to the news endpoint, and the result from the method is a promise that needs to be resolved in order to get the news data.
Next, update the HomePage component as follows to call the fetchArticles() method and resolve the returned promise:
In our function component, we first call the useState() hook of React to create the articles state variable, which will hold the news articles after we fetch them from the API.
useState() returns the state variable, which has the empty array as its initial value and a function that we can use to change the value of the variable. We use destructuring assignment to unpack the values from the returned pair into distinct variables (i.e. articles and setArticles()).
Next, we call the useEffect() hook to perform a side effect in our component. In our case, the side effect is to fetch data from the news API using the fetchArticles() method, which returns a promise. Once the promise is resolved, we call the setArticles() method to assign the news data to the articles variable.
Both useState() and useEffect() are built-in React hooks that were introduced in React 16.8; they simply let you use state and other React features without having to write a class. The useEffect() hook is equivalent to calling the componentDidMount, componentDidUpdate and componentWillUnmount lifecycle methods combined in class-based components.
Finally, in the view template, we iterate over the articles array using the map() method, and we display the title of each news article inside an IonItem element of the IonList component, and also a button that takes us to the page of the full article.
In this tutorial, we have started using both Ionic and React and used them to build a simple mobile application that fetches and displays news data from a third-party API using the Axios client. We have also seen how to use hooks in React — namely, the useState() and useEffect() hooks — to create state and perform side effects inside React function components. With Ionic, we’ve seen how easy it is to generate a project based on React and how we can theme the application using the color attributes of components.
We live in an era of webpack and npm scripts. Good or bad, they took the lead for bundling and task running, along with bits of Rollup, JSPM and Gulp. But let’s face it. Some of your older projects are still using good ol’ Grunt. While it no longer glimmers as brightly, it does the job well so there’s little reason to touch it.
Though, from time to time, you wonder if there’s a way to make those projects better, right? Then start from “Organizing Your Grunt Tasks” article and come back. I’ll wait. That’ll set the stage for this post and then we’ll take it further together to create a solid organization of Grunt tasks.
Automatic Speed Daemon task loading
It’s no fun writing loading declarations for each task, like this:
1.4 seconds doesn’t really make it a Speed Daemon… so I kinda lied. But still, it’s six times faster than the traditional way! If you’re curious how that’s possible, read about the original issue which led to the creation of jit-grunt.
How is jit-grunt used? First, install:
npm install jit-grunt --save
Then replace all tasks load statements with a single line:
module.exports = function (grunt) {
// Intead of this:
// grunt.loadNpmTasks('grunt-contrib-clean')
// grunt.loadNpmTasks('grunt-contrib-watch')
// grunt.loadNpmTasks('grunt-csso')
// grunt.loadNpmTasks('grunt-postcss')
// grunt.loadNpmTasks('grunt-sass')
// grunt.loadNpmTasks('grunt-uncss')
// Or instead of this, if you've used `load-grunt-tasks`
// require('load-grunt-tasks')(grunt, {
// scope: ['devDependencies', 'dependencies']
// })
// Use this:
require('jit-grunt')(grunt)
grunt.initConfig({})
}
Done!
Better configs loading
In the last example, we told Grunt how to load tasks itself, but we didn’t quite finish the job. As “Organizing Your Grunt Tasks” suggests, one of the most useful things we’re trying to do here is split up a monolithic Gruntfile into smaller standalone files.
If you read the mentioned article, you’ll know it’s better to move all task configuration into external files. So, instead of a large single gruntfile.js file:
module.exports = function (grunt) {
require('jit-grunt')(grunt)
grunt.initConfig({
clean: {/* task configuration goes here */},
watch: {/* task configuration goes here */},
csso: {/* task configuration goes here */},
postcss: {/* task configuration goes here */},
sass: {/* task configuration goes here */},
uncss: {/* task configuration goes here */}
})
}
But that will force us to load each external configuration into gruntfile.js manually, and that takes time! We need a way to load our configuration files automatically.
We’ll use load-grunt-configs for that purpose. It takes a path, grabs all of the configuration files there and gives us a merged config object which we use for Grunt config initialization.
module.exports = function (grunt) {
require('jit-grunt')(grunt)
grunt.initConfig({})
// Load all your external configs.
// It's important to use it _after_ Grunt config has been initialized,
// otherwise it will have nothing to work with.
grunt.loadTasks('tasks')
grunt.registerTask('default', ['cssmin'])
}
Grunt will automatically load all js or coffee config files from the specified directory. Nice and clean! But, if you’ll try to use it, you’ll notice it does nothing. How is that? We still need to do one more thing.
Let’s look into our gruntfile.js code once again, this time without the comments:
We initialize our Grunt config before actually loadings tasks configuration. If you are getting a strong feeling that it will make us end up with empty Grunt config — you’re totally right. You see, on contrary to the load-grunt-configs, grunt.loadTasks just imports files into gruntfile.js. It does nothing more.
Woah! So, how do we make use of it? Let’s explore!
First, create a file inside directory tasks named test.js
module.exports = function () {
console.log("Hi! I'm an external task and I'm taking precious space in your console!")
}
Let’s run Grunt now:
$ grunt
We’ll see printed to the console:
> Hi! I'm an external task and I'm taking precious space in your console!
So, upon importing grunt.loadTasks, every function is executed as it loads files. That’s nice, but what’s the use of it for us? We still can’t do a thing we actually want — to configure our tasks.
Hold my beer because there is a way to command Grunt from within external configuration files! Using grunt.loadTasks upon importing provides current Grunt instance as a function first argument and also binds it to this.
So, we can update our Gruntfile:
module.exports = function (grunt) {
require('jit-grunt')(grunt)
grunt.initConfig({
// Add some value to work with
testingValue: 123
})
grunt.loadTasks('tasks')
grunt.registerTask('default', ['cssmin'])
}
…and change the external config file tasks/test.js:
// Add `grunt` as first function argument
module.exports = function (grunt) {
// Now, use Grunt methods on `grunt` instance
grunt.log.error('I am a Grunt error!')
// Or use them on `this` which does the same
this.log.error('I am a Grunt error too, from the same instance, but from `this`!')
const config = grunt.config.get()
grunt.log.ok('And here goes current config:')
grunt.log.ok(config)
}
Now, let’s run Grunt again:
$ grunt
And what we’ll get:
> I am Grunt error!
> I am Grunt error too, from the same instance, but from `this`!
> And here goes current config:
> {
testingValue: 123
}
See how we accessed native Grunt methods from an external file and were even able to retrieve the current Grunt config? Are you thinking about that too? Yeah, the full power of Grunt is already there, right at our fingertips in each file!
If you are wondering why methods inside external files can affect our main Grunt instance, it is because of a referencing. grunt.loadTasks passing this and grunt to our current Grunt instance — not a copy of it. By invoking methods on that reference, we’re able to read and mutate our main Grunt configuration file.
Now, we need to actually configure something! One last thing…
This time, let’s make configuration loading work for real
Alright, we’ve come a long way. Our tasks are loaded automatically and faster. We learned how to load external configs with native Grunt method. But our task configs are still not quite there because they do not end up in Grunt config.
But we’re almost there! We learned that we can use any Grunt instance methods in imported files using grunt.loadTasks. They are available on grunt and this instances.
Among many other methods, there is a precious grunt.config method. It allows us to set a value in an existing Grunt config. The main one, which we initialized in our Gruntfile… remember that one?
What’s important is the way we can define tasks configurations. Exactly what we need!
That keeps Gruntfile relatively small and things seem to be well organized. But do you get a clear picture of the project just by glancing into this cold and lifeless list of tasks? What actually do they do? What’s the flow?
Can you tell that Sass files are going through grunt-sass, then grunt-postcss:autoprefixer, then grunt-uncss, and finally through grunt-csso? Is it obvious that the clean task is cleaning the CSS or that grunt-spritesmith is generating a Sass file which should be picked up too, as grunt-watch watches over changes?
Seems like things are all over the place. We may have gone too far with externalization!
So, finally… now what if tell you that there’s yet a better way would be group configs… based on features? Instead of a not-so-helpful list of tasks, we’ll get a sensible list of features. How about that?
We already learned about grunt.config. And believe it or not, you can use it multiple times in a single external file to configure multiple tasks at once! Let’s see how it works:
One file, multiple configurations. Quite flexible! But there is an issue we missed.
How should we deal with tasks such as grunt-contrib-watch? Its configuration is a whole monolithic thing with definitions for each task that are unable to be split.
We can’t simply use grunt.config to set watch configuration in each file, as it will override the same watch configuration in already imported files. And leaving it in a standalone file sounds like a bad option too — after all, we want to keep all related things close.
While grunt.config explicitly sets and overrides any existing values in Grunt config, grunt.config.merge recursively merges values with existing values in other Grunt config files giving us a single Grunt config. A simple, but effective way to keep related things together.
Now it’s much easier to tell just by glancing into tasks/styles.js that styles have three related tasks. I’m sure you can imagine extending this concept to other grouped tasks, like all the things you might want to do with scripts, images, or anything else. That gives us a reasonable configuration organization. Finding things will be much easier, trust me.
And that’s it! The whole point of what we learned.
That’s a wrap
Grunt is no longer the new darling it once was when it first hit the scene. But to date, it is a straightforward and reliable tool that does its job well. With proper handling, it gives even fewer reasons to swap it for something newer.
Let’s recap what we can do to organize our tasks efficiently:
Move specific task configurations out from Gruntfile and into external config files to keep things organized.
Use native grunt.task.loadTasks to load external config files. It’s simple but powerful as it exposes all Grunt capabilities.
Finally, think about a better way to organize your config files! Group them by feature or domain instead of the task itself. Use grunt.config.merge to split complex tasks like watch.
And, for sure, check Grunt documentation. It’s still worth a read after all these years.
If you’d like to see a real-world example, check out Kotsu, a Grunt-based starter kit and static website generator. You’ll find even more tricks in there.
Got better ideas about how to organize Grunt configs even better? Please share them in the comments!
Grey Goose has revamped their visual identity and we love it. The redesign was done by London, UK-based Ragged Edge.
“We needed a bold statement. So we started by redrawing the logotype from scratch – the biggest change to the brand’s identity since its launch in 1997. [The] bespoke type is more contemporary, with just a hint of swagger. The perfect complement to the iconic lone goose symbol.”
When it comes to the goose logo, I have some reservations regarding just how distinctive the goose will actually be.
Although I love the movement towards a more minimalistic icon, the 3D texturing that the logo previously had gave it character and a more luxurious identity.
Ragged Edge has successfully made the brand feel more accessible in their attempt to, as they said it, “build a flexible identity full of optimism”
From a marketing perspective, the shorter tagline that spells just “Vodka” now instead of “World’s best tasting Vodka” makes a lot of sense. Most people shop for alcohol based on the label. In recent years, more and more consumers will go for a more minimal tag. This is a trend we’ve seen in wine bottles as well.
However, having a splash of color on your label does help a lot as this study proves. This is why the new Grey Goose packaging will definitely draw your attention in a duty free store. The new subtle patters and their dynamic with the other visuals are definitely my favorite part of the redesign.
Now back to you. What do you think about the Grey Goose Vodka redesign? What do you like and what do you dislike about it?
Let us know in the comments bellow.
You know what a “reduced test case” is, right? We’ve talked about it here. I imagine the concept is useful in many walks of life, but in the world of front-end development, you can think of it like:
A reduced test case is a demo/example page you create which reproduces the problem you are having with the least amount of code possible. Only the HTML needed to show the problem content. Only CSS that is related to that reduced HTML. Only the JavaScript related to the problem functionality at hand.
The point of making these is typically troubleshooting. It’s both for you and for anyone else looking at the trouble. The less unrelated code anyone has to wade through to understand the problem, the better. The secret trick is that while making a reduced test case, you often figure out the problem in the process. 😉
I recently found out another acronym for all this: SSCCE.
That stands for “Short, Self Contained, Correct (Compilable), Example.” Sleuthing the meta tags, it looks like the credit is to Andrew Thompson and last updated in 2014. That landing page describes them wonderfully and explains what you need to do to create one.
It covers this classic situation where you discover the problem isn’t where you think it is:
If trimming a very large amount if code for others to see, you might trim out a part of it early on that you think is not related to the problem, yet the problem is fixed.
…and closes with the most important thing:
We are not proposing that every single problem needs a SSCCE in order to be solved. It will, however, make people much more likely to help, and will therefore increase the chance of finding a solution.
I’d say it’s a dramatic difference. The chances of me trying to help on a small bug where the bug is buried within a giant pile of unfamiliar code? Very low. The chances of me trying to help on a small bug with a SSCCE? High.
However, I think I still prefer “reduced test case” since the term is more self-explanatory.
Netlify has their own docs for Custom Domains, so if you’re looking for horse’s mouth technical docs on this stuff, that should be treated as the source of truth. But I’d like to take a crack at it from a slightly different angle, where we look at where you are and what you wanna do, and the point you in the right direction.
Do you NOT own the domain yet?
If that’s the case, you can buy it directly through Netlify if you want. There is a big advantage there in that it automatically gets set up to work perfectly, so it’s easier.
You don’t have to buy your domain through Netlify though, you can buy it wherever you like. There is nothing you can’t do with Netlify if you choose to buy a domain elsewhere.
Easiest possible method: register the domain with Netlify.
Alternative: If you anticipate some hosting/DNS churn, like you think you might ultimately need to host elsewhere, it probably makes more sense to manage to domain somewhere agnostic where you can re-point DNS stuff wherever you need to. It’s not that you can’t manage the DNS on Netlify and point it elsewhere, it just doesn’t make loads of sense. Also, there is something to be said (lower cognitive load) managing all your domains in one place if you can.
What if you already own the domain?
No problem. The rest of this article deals with that scenario.
Are you cool pointing the nameservers at Netlify?
If you are, this is the best way. It means you don’t have to fiddle with subdomains and the CDN features work the best. The requires you to go into the DNS administration area of wherever you bought the domain and change the nameservers there. Every domain registrant will be a bit different in where and how you do that.
Can’t or don’t want to point nameservers at Netlify?
I would guess that the main reason you might have this preference is that you use Cloudflare, or perhaps something else similar that gives you fancy performance and security advantages by going through their proxy. Netlify actually says that you don’t need Cloudflare with them, because many of the main advantages of Cloudflare Netlify already provides.
Technology is a moving place though, and it’s entirely possible that you need or really want some feature that a proxy service like Cloudflare provides.
If you need to do this, you’ve got two options:
Use the www. version of your domain and a CNAME record to point to Netlify (you can “CNAME flatten” it to remove www. if you really want).
This is actually a lot easier. If this is the case, you probably already own the domain name anyway, and you should stick with your existing DNS host. All you need to do is CNAME the subdomain to the Netlify domain. Here’s an example where the root domain is hosted elsewhere and uses Cloudflare for DNS, but the subdomain is Netlify hosted and points with a CNAME.
If you care about the Netlify domain sitting there with the same content on it, you can always redirect it. Also, you might need to “gray cloud” (turn off the Cloudflare proxy) for those subdomains so Netlify can issue SSL certificates for it.
If you’re currently a business owner or are thinking about becoming one, you’ve no doubt heard of PayPal. You may have even used it a few times as a consumer. But now that you’re in business mode, you may be curious about what the popular platform has to offer as a payment system.
The first chapter of this guide covers what PayPal is, but in case you’re not familiar with payment gateways in general, here are their typical capabilities and attributes:
They enable online and in-person payments for goods and services.
They provide a way for individuals to send or request money.
They provide varied levels of digital security and payment protections.
They charge a variable or fixed fee for their services, or a mix of the two.
We have plenty of guidance on PayPal specifically in the rest of this guide. It’s also chock-full of insights from business owners who have used PayPal in one form or another for years.
Chapter synopsis
This guide consists of several chapters, which you can easily navigate to at any time:
What is PayPal? Learn about the basics of PayPal.
PayPal business solutions. Get an in-depth look at the business services PayPal offers.
PayPal personal solutions. Get a buyer’s look at payments to better understand their perspective.
Benefits and drawbacks of PayPal. Discover what you’re really getting with PayPal — both the good and the bad.
How safe is PayPal? Security is always a concern when it comes to money. See what protections PayPal has in place for buyers and sellers.
PayPal software, apps, and integrations. Learn about the technology PayPal offers to enhance the buyer and seller experiences.
The PayPal + JotForm integration makes accepting payments easy. See how PayPal integrates with JotForm to make accepting payments a snap.
Remember to bookmark this guide for later reference. Your journey as a business owner is a long one.
PayPal is a well-known digital payments platform used by businesses and consumers alike to conduct financial transactions around the world — via the web, mobile apps, or in person. With PayPal, you can pay bills, send and receive money, accept payments, and more.
Here are a few interesting facts about the service, as noted on its website:
More than 267 million active account holders
Available in more than 200 markets worldwide
Supports the receipt of 100+ currencies, fund withdrawals in 50+ currencies, and balance holdings in 25+ currencies
Founded in December 1998
Headquartered in San Jose, California
Owns other brands, including Braintree, Venmo, and Xoom
Has its own dedicated typeface, called PayPal Sans
Who uses PayPal?
Compared to a traditional merchant account you’d get through a bank or other financial institution, PayPal has a lower barrier of entry. That means just about anyone can create a PayPal account and start using it — sometimes in the same day.
The result? All types of businesses, independent ventures, and everyday consumers use PayPal. Let’s look at a few examples:
An entrepreneurial teen selling custom-made T-shirts. All someone needs to sell something is a product (or service) and access to a laptop or phone. Most teens have the latter — so all they need to do is make their shirts; download the PayPal app; and convince their friends, classmates, and family to swipe their cards or send money.
A large group of friends at dinner. Sometimes it’s easier for one person to pay and then have everyone else pay them back afterward. Instead of trying to collect cash from each person, PayPal lets people use credit cards or funds from their bank accounts to send the money directly to an account.
A corporate worker with a side hustle. Many traditional employees often start their entrepreneurial journey by moonlighting — performing work that isn’t supplied by their main job. Decades ago this meant having a second job somewhere like a retail store, working in the evening and/or on the weekend. Today, this could be anything from selling products online to selling services as a freelancer or consultant. In any case, PayPal gives these would-be entrepreneurs the ability to accept money for whatever they’re selling.
A Fortune 500 company selling…whatever they sell. PayPal isn’t just for small businesses or person-to-person transactions. While large corporations may use the platform for different reasons (such as for customer convenience), they are no strangers to PayPal either. For example, Home Depot lets customers use PayPal online and in store.
Why use PayPal?
It instills trust with customers
Customers are less likely to trust what they haven’t seen, used, or interacted with before. As a small business owner, you’ll struggle with this for longer than you’d like.
Thankfully, PayPal is a well-known, trusted brand. “There’s a lot of value in the PayPal brand, and it’s primarily in the trust it communicates to your potential customers. While they may not know your business, they know PayPal. The result is reduced friction in the payment experience and ultimately more sales,” notes Peter White, founder of Tenancy Stream.
It’s convenient for customers
We mentioned that PayPal has a lot of active users (more than 267 million). That’s a lot of people who use the service and, more importantly, expect to keep using it wherever they shop. They already have their information — bank accounts, credit cards, etc. — set up on their account, which saves them time while shopping.
It’s when that expectation is not met that customers get annoyed or even upset. That’s the friction in their experience that White noted. Some may choose to use another of the payment options you’ve provided to make their purchase, but it’s much more convenient for them to just use PayPal — and likely more lucrative for you to give them what they’re looking for.
It lets you quickly test out business ideas
Since setting up a PayPal account is quick and simple, you can start selling a product or service today. While the product or service you’re selling might not catch on, accepting payment won’t be a problem. If you don’t get any sales or don’t see the profit margin you were expecting, you can scrap the idea and move on to another one.
It’s widely accepted
Who accepts PayPal? While PayPal is a largely digital solution and is accepted by an untold number of online businesses globally, it’s also accepted at more than 18,000 stores in the U.S. Big names like Home Depot, Office Depot, and Foot Locker all accept the service in store and online.
Speaking of businesses, you’re probably curious about what the PayPal experience is like specifically for business owners. We explore that in the next chapter.
PayPal business solutions
OK, so PayPal is popular, but just how popular? Well, more than 19 million merchants — from retailers to restaurants to e-commerce stores — use PayPal.
While every business owner has their own reasons for using the platform, John Frigo, who used to run an e-commerce business for collectibles, says his primary reason was because it helped him keep things organized.
He previously used a WordPress e-commerce store and admits the backend was “all over the place.” However, using several PayPal merchant services together helped him form a recordkeeping system for tracking orders, generating sales reports, etc.
Frigo also notes that PayPal has a lot of flexibility. “You can easily set PayPal up on your website, invoice customers, create digital buttons for quick payment, and accept payment in person, such as at a trade show or street fair. It works for pretty much any situation.”
The platform isn’t without its downfalls, though. Frigo says that buyers can sometimes take advantage of sellers by “working the system.” (We’ll detail more drawbacks and advantages of a PayPal business account in a later chapter.)
Explore your PayPal merchant tools
Here are some of the many PayPal merchant services that help you get the most out of your PayPal Business account:
PayPal payment options. PayPal offers an array of payment options, including credit cards, debit cards, Venmo, PayPal, and PayPal Credit — an option that lets customers pay over time (with credit approval). You can accept payments online, in person, and via invoice. Fees vary and may change, but here are the typical rates:
2.7 percent per swipe for mobile and in-store payments in the U.S.
3.5 percent + $0.15 for keyed sales on mobile or in store
2.9 percent + $0.30 per transaction within the U.S. for online payments and invoicing
PayPal Business app. The PayPal Business app is available for both iOS and Android. You can download it on the App Store and Google Play for your mobile phone or tablet. It enables you to view your account activity, send invoices, transfer funds, and issue refunds whenever you want. You can also view customers’ transaction history, import contacts, and get in touch directly from your device.
PayPal business debit card. You can use your PayPal balance anywhere Mastercard is accepted with the PayPal Business Debit Mastercard. The standard cash back rate is 1 percent on eligible purchases, and you can use it at ATMs to get cash.
PayPal shipping. PayPal offers a fee-free shipping service that even lets you get discounts on USPS and UPS shipping labels. You can purchase and print shipping labels (single or in batches), and track packages through your PayPal account. The service automatically saves your tracking numbers for PayPal Seller Protection.
PayPal invoicing. Like shipping, PayPal’s invoicing service is also fee free. Quickly create and send prebuilt or customized invoices to customers via email or a shared link. The service accepts partial payments and even tipping. You can also view billing history, track payments, and send reminders.
Discover this hidden gem among PayPal merchant options
Starting or growing your business can be costly, especially in the beginning. Your options for funding are often limited. PayPal offers business account holders two loan options.
PayPal Business Loan
PayPal notes that this type of loan is best for businesses that have been operating for at least nine months and that have at least $42,000 in annual revenue. You can check your eligibility in minutes online or over the phone. (A credit check is required.) If your application is approved, you can receive funds as quickly as the next business day.
Loan terms range from 13 to 52 weeks based on the loan amount.
Payments are fixed and deducted from your bank account on a weekly basis.
There are no late fees, early repayment fees, or processing fees.
PayPal Working Capital
Alternatively, this loan requires no credit check. However, you must be an existing PayPal customer who has had a PayPal Business account for at least 90 days and processed $15,000+ with PayPal within any time period less than or equal to 12 months. Your loan is based on your PayPal sales, and it can be funded in minutes once approved.
Loan amounts range from $1,000 to $125,000. The maximum amount can be up to 35 percent of your annual PayPal sales, and no more than $125,000 for your first loan.
Loan terms vary based on your PayPal sales.
Payments are pulled automatically based on a percentage of your PayPal sales that you choose when you apply — higher sales equal faster repayment and vice versa. However, you must repay a minimum of 5 percent or 10 percent every 90 days to keep your loan in good standing. You can also make payments manually.
There are no periodic interest charges, late fees, prepayment fees, or penalty fees.
Boost your business with PayPal partners
Starting your PayPal Business account is just the beginning. While PayPal merchant tools provide a great foundation, PayPal also partners with a number of third parties to help you grow and run your business. Here’s what they help you do.
Build your online store
If you’re interested in e-commerce, PayPal partners with website and online store builders like Wix, Squarespace, Shopify, and BigCommerce.
Wix and Squarespace work well if you’re in the early stages of your business, as they offer simple design tools to get you up and running quickly. Shopify gives businesses of all sizes a broad selection of options, including letting you buy an existing online store. As the name implies, BigCommerce powers big brands like Ben & Jerry’s — offering enterprise functionality and a robust set of analytical tools.
Each partner offers their own version of a discount or special offer for PayPal users, which makes getting started that much easier (and cheaper).
Upgrade your existing online store
Partners like Magento enable you to further develop your online store. You can integrate multiple shopping experiences — eBay, Amazon, your web store, and more — and manage all of your inventory and sales through one system.
Similar to Magento, Miva is another PayPal partner that gives you the tools to boost your online store with capabilities such as marketing tools, social integrations, and automated reordering.
PayPal offers its native PayPal Here solution for accepting payments in your store, but its point-of-sale (POS) partners offer more tailored capabilities. For example, Vend is a leading POS brand focused on inventory management and customer loyalty for retailers. Alternatively, Lavu helps thousands of restaurants and other quick-serve and hospitality businesses take orders and reduce wait times.
Manage your finances with invoicing and accounting tools
Partners like Intuit QuickBooks let you easily import your PayPal transactions, then edit, categorize, and match transactions to keep your books accurate and up to date. Xero is an online accounting software that helps small businesses (and their advisors) simplify bank reconciliations, billing, payroll, and more. Invoice2go is a bit more niche, focusing on invoicing and estimates.
As a business owner, it’s important to always understand your customer’s perspective — which is why we walk through PayPal’s personal solutions in the next chapter.
PayPal personal solutions
Your current and potential customers have a number of options available for paying you. We explore several of these below.
An eCheck is an electronic payment funded by the buyer’s bank account. An eCheck must clear the bank before it’s credited to the recipient. It usually takes 3 to 6 business days for an eCheck to clear and the money to appear in the recipient’s PayPal account.
Basically, it’s like writing a physical check from your bank, but you’re sending it digitally. Of course, most people don’t use physical checks anymore, but an eCheck is an option if you don’t have a credit card or just prefer to pay directly from your bank account.
Note that you must have enough funds in your bank account to cover the eCheck amount you’re requesting. If you don’t, the bank will decline your request, and PayPal will follow up with a second request. In addition, you cannot use an eCheck if the Instant Transfer option is available.
An Instant Transfer is a way to send money or make a payment from your bank account instantly using PayPal. The seller is credited immediately while our request for the money from your bank is processing.
To use an Instant Transfer, you’ll need
A confirmed U.S. bank account with enough funds to cover the full payment amount
An unexpired backup funding source like a credit or debit card in case your payment request is declined (you can change this anytime before requesting an Instant Transfer)
PayPal eChecks vs instant payment
To clearly distinguish between PayPal eChecks and Instant Transfers, we created this handy reference table that compares the two payment options.
Item
eCheck
Instant Transfer
Time for payment to clear
3–6 business days
Instantly
Need full amount of requested payment in bank account to initiate?
Yes
Yes
Backup payment source (credit or debit card) required?
No
Yes
If payment is declined the first time
PayPal submits a second payment request within 3 business days
PayPal submits a second payment request within 3 business days
If payment is declined the second time
Purchase does not go through
PayPal charges your backup payment source
Time for refund to clear
3–6 business days
Instantly if the payment shows as completed between the bank and PayPal. Otherwise, 2–5 business days after the payment was made
Frigo shares his thoughts on the PayPal eCheck vs instant payment debate: “In my opinion, there’s really no reason to use an eCheck. It takes entirely too long — both in sending the payment and getting it back if the seller cancels or refunds it. Beyond that, I’ve seen and heard of cases where an eCheck was reversed by the bank months after it cleared, and the seller lost money because of it. When you consider these important factors, Instant Transfer is just the better option for both the buyer and the seller.”
PayPal credit card services
PayPal has a collection of credit, debit, and prepaid cards in partnership with Mastercard. It also offers a digital credit line. Exact terms for each may change over time, so we cover just the basics below.
Credit cards and digital credit line
PayPal Cashback Mastercard. A 2 percent cash back card with no purchase exceptions and no annual fee.
PayPal Extras Mastercard. A variable point-earning card that allows redemption for gift cards, travel vouchers, or cash back to your PayPal balance. No annual fee for new accounts.
PayPal Credit. This digital, reusable credit line lets U.S. PayPal account holders shop online anywhere PayPal is accepted. It requires no card and has no annual fee.
Debit and prepaid cards
PayPal Cash Mastercard. This debit card gives you access to your PayPal Cash Plus account, whether swiped at a store, keyed in online, or used at an ATM.
PayPal Prepaid Mastercard. This reloadable debit card acts similarly to the Cash card, only it’s prepaid. You can load funds onto the card via the no-cost direct deposit service, via transfers from your PayPal account, or via a Netspend Reload Network location.
We’ve covered solutions available for both sellers and buyers, but what exactly are the drawbacks and advantages of PayPal?
Benefits and drawbacks of PayPal
Beyond the power of its well-known brand, PayPal has a number of business benefits. For example, the PayPal Business account offers many tools and merchant services that can help develop and grow your business. However, PayPal isn’t perfect. Below, we explore both the benefits and drawbacks of PayPal.
Where PayPal wins
Advantages of a PayPal Business account
You can offer customers multiple payment processing methods. With the platform’s business account, you can process payments from PayPal, Venmo, PayPal Credit, and debit and credit cards — both online and in person.
You can take advantage of available shipping discounts. PayPal offers a fee-free shipping service. In addition, it also provides discounts on USPS and UPS shipping labels.
You can get the business debit card. With the PayPal Business Debit Mastercard, you can use your PayPal balance anywhere Mastercard is accepted. Much like a bank debit card, you can make purchases and even get cash from ATMs.
You gain access to business loans. PayPal Business account holders have the opportunity to apply for one of PayPal’s two business loans, which can help give your business the cash flow it needs to grow. (We explored those loans in detail in the chapter about PayPal’s personal solutions.)
You can link with PayPal partners. Numerous third parties like Wix and Intuit QuickBooks partner with PayPal to offer your business a helping hand. Through these partners, you can build or upgrade an online store, manage your finances, and more.
Benefits of PayPal Credit
You can buy now and pay later. As its name implies, PayPal Credit is a revolving credit line that gives you immediate purchasing power without having to pay in full immediately.
You can avoid interest. PayPal offers promotional financing with no interest as long as purchases of $99 or more are paid in full within six months.
You can send money. Don’t have enough available funds to pay a friend? You can send them money from your PayPal Credit account for PayPal’s standard fee of 2.9 percent + $0.30 per transaction. Note that any special promotional financing offers don’t apply to these types of transactions.
You don’t have to pay an annual fee. There’s no fee for maintaining access to your credit line, unlike many credit cards.
Advantages of the PayPal brand
“Buyers know and trust PayPal. They like how easy and convenient it is to use. That’s great for any seller, but especially those just starting out. People don’t know you or your business, and seeing the PayPal brand instantly instills a sense of trust. Greater trust equates to higher conversion. That in itself is one of the greatest advantages of PayPal,” explains Frigo.
Where PayPal falls short
Inadequate seller protection
When it comes to transaction disputes, it’s well known in the seller community that PayPal typically favors buyers, putting the onus on sellers to “prove” their case.
Frigo notes that some buyers know how to “work the system,” taking advantage of PayPal’s protections to get free stuff from sellers. “This is especially true with digital or intangible products where you’re not physically shipping an item. You need a paper trail, as PayPal asks for things like a tracking number that shows the item was delivered to the address the buyer entered. Without something like this, the buyer may automatically get their money back, meaning they got a free product. It’s a huge vulnerability in the PayPal ecosystem,” he cautions.
Limited development customization
While PayPal does offer a sizable number of integrations that cover common business scenarios, the integrations are optimized for only those scenarios. That means any instances outside of these common business cases are not fully covered.
Further, White notes that some PayPal integrations and APIs can be “complex, clunky, or outdated,” not using more modern development approaches like restful API.
“The result is less flexibility, meaning you’ll have to figure out workarounds. For example, it’s difficult to integrate usage-based pricing through PayPal. Whereas with a processor like Stripe, developers in the community have already created solutions for that business case that you can use as is or tweak a bit to your liking,” he adds.
Limited room for business growth
There’s an old saying—don’t put all your eggs in one basket. Using PayPal as your only payment processor could be limiting.
Frigo explains why: “PayPal is a great option for businesses just starting out. It often provides the trust needed to convince people to buy from you. But if anything goes wrong with PayPal, you’re stuck. So as you grow your business, assess the market and see what other payment processing options are available and could work for you. One solution may offer lower fees. Another one may be more customizable and provide a payment flow that suits you and your customers better. In short, keep your options open.”
How PayPal stacks up against competitors
PayPal vs First Data
Compared to First Data, a more traditional payment processor, PayPal has a lower barrier of entry for merchants. It has fewer documentation requirements and require less setup time. Another big win for PayPal is its fees. PayPal offers lower processing fees, doesn’t charge monthly account and maintenance fees, and doesn’t impose multiyear contracts that bind your business with early termination fees.
On the other hand, First Data is the larger player, processing 45 percent of all credit and debit card transactions in the U.S. — through direct transactions and third parties. And unlike PayPal, First Data keeps customers on your e-commerce site throughout their transaction. (PayPal sometimes navigates your customers away from your site to pay with their PayPal accounts.) For larger businesses with a high number of sales, First Data offers discounted pricing and a robust tool set, such as in-depth reporting capabilities.
PayPal vs Stripe
PayPal and Stripe are actually quite similar in many ways. Both charge the same processing fee. Both offer a large knowledge base of frequently asked questions and how-to content. And neither requires a contract or charges an early termination fee.
The largest distinction between the platforms revolves around their integrations. As noted earlier, Stripe has a more developer-friendly platform. It’s highly customizable, so if you’re looking to develop a payment flow for maximum conversion, Stripe is your platform. If you’re looking for pure ease of use, PayPal is probably the better option.
PayPal vs Square
PayPal’s card processing fee for point-of-sale and mobile transactions is 0.05 percent less than that of popular payment processor Square. In addition, PayPal is geared toward e-commerce businesses, easily integrating with all popular e-commerce platforms.
PayPal wins over Square when it comes to funds availability. While funds from customer purchases on PayPal can be available immediately, funds from Square take one to two business days to transfer and be usable.
However, if you’re looking to set up a recurring payment option for your customers, Square offers this service for free, while PayPal charges $40 per month. Square also has advanced business management tools for brick-and-mortar businesses. For example, it offers a robust point-of-sale software, along with inventory, sales, employee, and customer management tools.
Next, onto one of the most common questions people have about this payment processing platform: Is PayPal safe?
How safe is PayPal?
When online shopping first started, people were highly skeptical and often concerned about the safety of their information. Despite how popular and commonplace it’s become, that concern is still a reality, though it’s not nearly as prevalent as it once was. It’s perfectly understandable to wonder about the safety of a service like PayPal — for both buyers and sellers. Let’s take a look at the varying perspectives on safety.
How secure is PayPal for buyers?
PayPal buyer protection
Sean Dawes, cofounder of Modded Euros, summarizes PayPal buyer protection this way: “By offering fraud protection and digital encryption, and masking financial information from sellers, PayPal ensures buyers are able to buy with confidence online. If there’s ever an issue with a purchase, buyers can file disputes. PayPal then acts as a mediator between the buyer and seller to resolve any order-related discrepancies, such as a lost or damaged package, or a package shipped to the wrong address.”
Purchase resolution process
PayPal’s resolution process is meant to give buyers confidence that, if something goes wrong with their purchase experience, there is an established approach to remedy the problem. In most cases, this means getting a refund on the purchase price and even the shipping costs.
Buyers have about six months (180 days, to be exact) from the date the payment was made to start the resolution process. Here’s how it works:
Buyer opens dispute. The buyer opens a dispute in their PayPal account and communicates directly with the seller to seek a remedy.
Buyer escalates to claim. If the seller doesn’t respond or doesn’t provide a remedy the buyer is satisfied with, the buyer can escalate the dispute to a claim — as long as they do so within 20 days of opening the dispute.
PayPal investigates and resolves. Once the issue has been identified as a claim, PayPal begins investigating. PayPal may request supporting documentation — e.g., proof of delivery, receipts, police reports — from both the buyer and the seller.
Frigo cautions that the last step of the process is where sellers can get taken advantage of: “If you read the terms of service closely, you can see where there’s room for buyers to work the system. The terms tell you that if you can’t give PayPal sufficient evidence in a ‘timely manner,’ the buyer can win the dispute—even if their purchase wasn’t eligible for PayPal buyer protection! You really have to be careful as a seller. It can be a hassle, but always keep your receipts and any documentation related to buyers’ purchases.”
To be fair, PayPal notes that, should the seller provide the needed evidence, the seller could win the dispute. This is true even if the buyer claims to have not received the item. In any case, while reality may see buyers winning disputes more often than sellers, PayPal’s terms appear to allow for fairness in the resolution process.
When buyers make a purchase online, they have a choice to make. Some may choose to use their PayPal account because it’s convenient, but others may prefer using their credit card because they want to collect points or because they don’t have their credit card tied to their PayPal account.
For the latter type of buyer, having only PayPal as an option may turn them off. In any case, PayPal has several safety advantages over credit cards that may convince these would-be buyers to use PayPal:
As we described in detail in the last section, PayPal’s buyer protection program offers a resolution process that can result in buyers getting a full refund. This is an important safety net should something go wrong during a transaction.
PayPal also has a security key service that acts as a secondary authentication factor. Whenever you try to log into your PayPal account, the service sends you a text message with a temporary security code. You enter this code, along with your password, to gain access.
If your credit card information is stolen, it can be used to make purchases both online and offline. However, if your PayPal account is compromised and your credit card is connected to your account, the card can only be used to make purchases online.
On the technical side, PayPal employs transport layer security (TLS) connections whenever you log in. According to its security page, “Strong TLS configurations are the current industry standard for trusted communication channels and allow your information to transmit across the internet in a secure manner.”
Like the transactions made from your computer or mobile browser, transactions made through the PayPal app are also protected with the same security policies. PayPal does employ some additional security measures for its iOS and Android apps:
Your login sessions on the app time out after 15 minutes, meaning you have to log back in after the time is up.
Key pinning is implemented when you access the app, ensuring that your mobile device connects to a “true PayPal server.” This prevents PayPal impostors from hijacking the connection.
How secure is PayPal for sellers?
PayPal seller protection
Much like PayPal buyer protection, PayPal seller protection provides sellers with fraud prevention measures and financial protections. Dawes adds this about PayPal seller protection: “One of the most important things to pay attention to with orders as a seller is the three classes of buyers: Eligible, Not Eligible, and Partially Eligible. This classification will determine whether a transaction is covered under PayPal’s seller protection policy.”
Dawes also notes that PayPal doesn’t cover items picked up locally or in person, or intangibles, such as digital goods or services. If you run a business that sells information products or any kind of service, PayPal seller protection won’t do much for you.
However, seller protection affords many e-commerce businesses a certain peace of mind as long as they meet the requirements for the program, which Dawes spells out in layman’s terms:
The buyer’s order must have a physical good that can be shipped.
Buyers’ accounts must be verified, and orders must be shipped to the address entered on the account.
If a dispute is filed, the seller must submit the requested documentation ASAP to prove the order was shipped to the correct address.
The seller’s address must be in the United States.
Now it’s time for the fun stuff — PayPal’s tech offerings. We cover their apps and integrations in the next chapter.
PayPal software, apps, and integrations
The PayPal software ecosystem is vast and includes all manner of solutions for consumers and businesses alike. Relying on White’s technical expertise, we focus on the most relevant apps and integrations you need to know about.
PayPal mobile apps
PayPal app
There is a PayPal app for Android and iOS, which you can find on Google Play and the App Store, respectively. Consumers use the PayPal app to send, receive, and access their money securely and for free. Of course, a PayPal account is required to use the app.
With the PayPal app, you can do the following:
Use your bank account or PayPal Cash balance to send money to someone using their phone number or email.
Track and monitor every transaction you make.
Collect money from a group of people by creating a custom Money Pools page, such as when coworkers chip in for an office gift. You’ll need to set up PayPal Cash or PayPal Cash Plus to create a Money Pools page. Otherwise, people chipping in only need a PayPal account.
Link PayPal to investment service Acorns and micro-invest your PayPal Cash or PayPal Cash Plus funds. Options include one-time or recurring investments.
Donate directly to any of the thousands of approved PayPal charities and causes.
PayPal Business app
Like the standard PayPal app, the PayPal Business app is available for both Android and iOS. Its purpose is to help you manage your business transactions.
With the PayPal Business app, you can
Create and send invoices to customers, track unpaid invoices, and send reminders to help you get paid
Generate reports on business trends, such as monthly, quarterly, or yearly sales
Transfer funds between linked accounts, check your account balance, view transaction details, and issue refunds
Access your PayPal customer information, view their transaction history, and contact them
PayPal Here app
Also available for Android and iOS, the PayPal Here app is mobile point-of-sale software. To be fully functional, the app requires a companion PayPal credit card reader.
With the PayPal Here app and card reader, you can
Accept payments on your mobile device from debit and credit cards, including major card brands like Visa, Mastercard, American Express, and Discover
Accept contactless payments like Apple Pay or Google Pay (though the card readers that accept these are more expensive)
Create a product and service list, including photos and descriptions, for checkout
Set up employees with special roles and permissions to accept payments on your account
View sales reports based on variables such as time, products, services, and employees
PayPal web apps and integrations
PayPal Checkout
This integration’s biggest selling point is its focus on reducing shopping cart abandonment rates, which average about 70 percent. A complicated checkout process is one of the main culprits behind this high rate, which is why PayPal Checkout cuts down on the number of actions a customer must take before completing their purchase.
One of the most visible ways it does this is with Smart Payment Buttons, which give customers the option of paying with PayPal, Venmo, or PayPal Credit through a secure popup window. Compare this to a customer having to navigate away from the shopping site to the PayPal website to complete their transaction.
White notes that this integration is important because online retailers are always looking for ways to reduce friction in the checkout process. “Even eliminating a single step can improve conversion rates significantly. This means higher profits.”
While PayPal keeps its checkout solution up to date, you will need some technical help to set it up. According to White, “PayPal recommends that you work with a developer to integrate the solution, and for good reason. When you’re running an e-commerce operation, the last thing you want to do is introduce a new integration or widget without technical knowledge. You could cause some serious digital damage and hurt your bottom line.”
If you’re looking to attract customers to sign up for subscription-based goods or services, PayPal Subscriptions is an option. For example, you may want to enable your customers to purchase an item, such as lipstick or a bag of dog food, automatically every month.
With PayPal Subscriptions, you can
Create subscription plans that charge customers a fixed amount on a set schedule or based on a subscribed item quantity
Offer customers free or discounted trials to generate more subscription signups
Modify the price of your plans as needed
Enable customers to upgrade and downgrade their subscription plans or adjust their subscribed item quantity
Automate payment recovery for failed payments
“Subscriptions offer a great way to get recurring revenue from customers, whether you sell physical goods or offer ongoing services. Just remember to get a developer’s help to ensure you set everything up right,” says White.
Speaking of integrations, there are many ways PayPal can be used with other solutions to help your business run a little smoother. Check out one such integration in the next chapter: PayPal + JotForm.
The PayPal + JotForm integration makes accepting payments easy
Do you operate an e-commerce store with physical inventory? Have a digital business that sells information products? Run a hotel and need a way to collect customer details and take payment? Own a gym and want to sign up your customers for a monthly membership plan?
Much like PayPal, JotForm can help your business get customers from the interest stage to the purchase stage — whether you sell goods or services, whether your business is for-profit or nonprofit, and whether you need a simple form or a robust form and payment solution. JotForm is a simple-to-use form builder that lets you seamlessly add a payment form to your website and integrate it with a number of payment processors, including PayPal.
Create branded, amazing-looking order forms to improve customer perception and conversion on your digital goods and physical products
Collect customer information that’s important for delivering your services, and easily accept payment
Ask for feedback from customers when collecting subscription payments, and then use that feedback to ensure customers stay subscribed
All you need is an account with JotForm and a business account on PayPal.
Your PayPal integration options
Everyone loves choices! See which one of these JotForm-PayPal integrations is best for your business:
PayPal Payments Standard. Quickly create a simple payment form, then give your customers the ability to pay with their PayPal accounts. After submitting a PayPal-integrated form, including payment details, customers are redirected to a PayPal payment page to complete their transaction.
PayPal Checkout. Provide your customers with additional payment options on the payment form you created, including PayPal Credit, Venmo, and debit or credit card. Instead of being taken to a new page, customers can simply check out in a popup window that opens after clicking one of PayPal’s checkout buttons.
PayPal Payments Pro. With this option, customers don’t have to sign into their PayPal accounts to make a payment through your form. (They don’t need an account at all!) Customers can pay you directly using their credit card and, unlike the standard version, remain on your site throughout the transaction.
Regardless of which option you choose, you and your customers can transact safely. JotForm is the only online form software that is PCI DSS Service Provider Level 1 compliant, which is the highest standard in payment security. (That means we’re really secure!)
There are also no additional fees with any of these PayPal integration options. You only pay the fees PayPal normally charges.
And remember: Our forms are fully customizable. Change the logo, add or remove items, or modify the look and feel. JotForm gives you the power to choose exactly how you want to represent your business and move customers along in the purchase process — all with easy-to-use forms.
Ready to get started? Check out these PayPal-integrated templates for inspiration, or start your own from scratch!
More about your PayPal guides
Sean Dawes
Dawes is the cofounder of Modded Euros, a U.S.-based e-commerce retailer that sells aftermarket performance parts for the Audi, BMW, and Volkswagen brands. His business uses three payment processors: PayPal, Stripe, and Affirm.
“While we started out using only one payment method, we’ve grown large enough to bring on additional payment options. We want to make sure our customers have a choice at checkout and maximize conversion,” says Dawes.
John Frigo
Frigo is the digital marketing lead for My Supplement Store, a U.S.-based ecommerce retailer that sells a large variety of supplements and sports nutrition products. However, his PayPal experience comes from operating a niche e-commerce business in the collectibles space for seven years.
“PayPal provided a needed sense of trust when I first started my online store. And while I’ve had my good and bad times with the platform, overall it was quite useful,” he notes.
Peter White
White is the founder of Tenancy Stream, a U.K.-based software-as-a-service platform that helps landlords save time and money, and eliminates hassle with regard to property management. He was a developer for many years and gained technical knowledge of PayPal by helping businesses integrate PayPal and other products.
“I’ve seen PayPal from a perspective most haven’t — the backend. I’ll just say it looks quite different! But that perspective gives me some useful technical insights,” he says.
In this article I am going to take a look at the CSS writing-mode property. However this is not an article about the practical or creative application of this property. Instead, I want to demonstrate why understanding writing modes is so important, even to those of us who rarely need to change the writing mode of a page or component. The support of multiple writing modes is key to the way that our new layout methods of Flexbox and Grid Layout have been designed. Understanding this can unlock a better understanding of how these layout methods work.
What Are Writing Modes?
The writing mode of a document or a component refers to the direction that text flows. In CSS, to work with writing modes we use the writing-mode property. This property can take the following values:
horizontal-tb
vertical-rl
vertical-lr
sideways-rl
sideways-lr
If you are reading this article on Smashing Magazine in English then the writing mode of this document is horizontal-tb, or Horizontal Top To Bottom. In English sentences are written horizontally, the first letter of each line starting on the left.
A language such as Arabic also has a horizontal-tb writing mode. It is written horizontally, top to bottom, however Arabic script is written right to left, and so sentences in Arabic start on the right.
Chinese, Japanese and Korean are written vertically, with the first character of the first sentence being top right. Following sentences being added to the left. Therefore the writing mode used is vertical-rl. A vertical writing mode running from right to left.
Mongolian is also written vertically, but from left to right. Therefore, should you want to typeset Mongolian script you would use the writing mode vertical-lr.
The other two values of writing-mode are designed more for creative purposes than for typesetting vertical scripts. Using sideways-lr and sideways-rl turns text sideways – even characters normally written vertically and upright. The values unfortunately are only supported in Firefox at the moment. The following CodePen shows all of the different values of writing-mode, you will need to use Firefox if you want to see the sideways-* ones in action.
Writing Modes can be used when creating a document that uses a language written using that writing mode. They can also be used creatively, for example to set a heading vertically down the side of some content. In this article however, I want to take a look at the impact that supporting vertical languages, and the possibility of vertical text, has on CSS layout, and across CSS in general.
Before I do so, if you are interested in the use of writing modes for vertical text, here are some useful resources.
The W3C Internationalization site has a wealth of useful information. Read about RTL scripts and vertical text.
Jen Simmons wrote an excellent article about CSS Writing Modes which also includes several examples from print of these modes in use.
When we change the writing mode of a document, what we are doing is switching the direction of the block flow. Therefore it quickly becomes very useful for us to understand what is meant by block and inline.
One of the first things we learn about CSS is that some elements are block elements, for example a paragraph. These elements display one after the other in the block direction. Inline elements, such as a word in a sentence display one after the other in the inline direction. Working in a horizontal writing mode, we become used to the fact that the block dimension runs top to bottom vertically, and the inline dimension left to right horizontally.
As block and inline elements relate to the writing mode of our document however, the inline dimension is horizontal only if we are in a horizontal writing mode. It doesn’t relate to width, but instead to inline size. The block dimension is only vertical when in a horizontal writing mode. Therefore it doesn’t relate to height, but to block size.
Logical, Flow-relative Properties
These terms, inline size and block size are also used as the names of new CSS properties designed to reflect our new writing mode aware world. If, in a horizontal writing mode you use the property inline-size instead of width, it will act in exactly the same way as width – until you switch the writing mode of your component. If you use width that will always be a physical dimension, it will always be the size of the component horizontally. If you use inline-size, that will be the size in the inline dimension, as the below example shows.
The same is true for height. The height property will always be the size vertically. It relates to how tall the item is. The block-size property however gives the size in the block dimension, vertically if we are in a horizontal writing mode and horizontal in a vertical one.
As I described in my article “Understanding Logical Properties And Values”, there are mappings for all of the physical properties, those which are tied to the dimensions of the screen. Once you start to think about it, so much of CSS is specified in relation to the physical layout of a screen. We set positioning, margins, padding and borders using top, right, bottom, and left. We float things left and right. Sometimes tying things to the physical dimension will be what we want, however increasingly we are thinking about our layouts without reference to physical location. The Logical Properties and Values specification rolls out this writing mode agnostic way of working right across CSS.
Writing Modes, Grid and Flexbox
When our new layout methods landed on the scene, they brought with them an agnostic way of looking at the writing mode of the component being laid out as a flex or grid layout. For the first time people were being asked to think about start and end, rather than left and right, top and bottom.
When I first started to present on the subject of CSS Grid, my early presentations were a rundown of all of the properties in the specification. I mentioned that the grid-area property could be used to set all four lines to place a grid item. The order of those lines was not however the familiar top, right, bottom and left we use to set all four margins. Instead, we need to use top, left, bottom, right – the reverse of that order! Until I understood the connection between grid and writing modes, this seemed a very odd decision. I came to realise that what we are doing is setting both start lines, then both end lines. Using top, right, bottom and left would work fine if we were in a horizontal writing mode, turn the grid on its side however and that makes no sense. If we use grid-area: 1 / 2 / 3 / 5; as in the pen below the lines are set as follows:
grid-row-start: 1; – block start
grid-column-start: 2 – inline start
grid-row-end: 3 – block end
grid-column-end: 5 – inline end
Flexbox Rows And Columns
If you use flexbox, and add display: flex to a container, your items will display as a row as the intial value of the flex-direction property is row. A row will follow the inline dimension of the writing mode in use. Therefore if your writing mode is horizontal-tb a row runs horizontally. If the text direction of the current script is left to right then items will line up starting from the left, if it is right to left they will line up starting on the right.
Use a vertical writing mode however, such as vertical-rl and flex-direction: row will cause the items to lay out vertically, as the inline direction is vertical. In this next CodePen all of the examples have flex-direction: row, only the writing mode or direction has changed.
Add flex-direction: column, and the items layout in the block dimension of your writing mode. In a horizontal writing mode the block dimension is top to bottom, so a column is vertical. With a writing mode of vertical-rl a column is horizontal. As with the previous example, the only difference between the below flex layouts, is the writing mode being used.
Grid Auto-placement
When using auto-placement in grid, you will see similar behavior to that in flex layout. Grid items auto-place according to the writing mode of the document. The default is to place items in rows, which will be the inline direction – horizontally in a horizontal writing mode and vertically in a vertical one.
Try changing the flow of items to column as in the example below. The items will now flow in the block dimension – vertically in a horizontal writing mode and horizontally in a vertical one.
Grid Line-placed Placement
Line-based placement also respects writing mode. The lines of our grid start at 1, both for rows and columns. If we position an item from column line 1 to column line 3, and are in a horizontal writing mode with a left to right direction, that item will stretch from the left-most column line across two grid tracks horizontally. Thus spanning two columns.
Change the writing mode to vertical-rl and column line 1 will be at the top of the grid, the item spanning two tracks vertically. Still spanning two columns, but the columns are now running horizontally.
Alignment In Grid And Flexbox
One of the first places many people will have come into contact with the way Flexbox dealt with writing modes, would be when aligning items in a flex layout. If we take the flex-direction: row example above, and use the justify-content property to align all of the items to flex-end the items move to the end of their row. This means that in a horizontal writing mode with left to right direct the items all move to the right, as the end of that row is on the right. If the direction is right to left they all move to the left.
In the vertical writing mode they move to the bottom, assuming there is space for them to do so. I have set an inline-size on the components in this example to ensure that we have spare space in our flex containers to see the alignment in action.
Alignment is a little easier to understand in grid layout, as we always have the two axes to play with. Grid is two-dimensional, those two dimensions are block and inline. Therefore, you can remember one rule if you want to know whether to use the properties that begin with align- or those which begin with justify-. In grid layout the align- properties:- align-content, align-items, align-self are used to do block axis alignment. In a horizontal writing mode that means vertically, and in a vertical writing mode horizontally.
Once again we don’t use left and right or top and bottom, as we want our grid layout to work in exactly the same way no matter what the writing mode. So we align using start and end. If we align to start on the block dimension, that will be top when in horizontal-tb, but will be right when in vertical-rl. Take a look in the example below, the alignment values are identical in both grids, the only difference is the writing mode used.
The properties justify-content, justify-items,justify-self are always used for inline alignment in grid layout. That will be horizontal in a horizontal writing mode and vertical in a vertical writing mode.
Flexbox alignment is complicated somewhat by the fact that the main axis can be switched from row to column. Therefore in flexbox we need to think about the alignment method as main axis versus cross axis. The align- properties are used on the cross axis. On the main axis all you have is justify-content due to the fact that in flexbox we deal with items as a group. On the cross axis you can use align-content in cases where you have multiple flex lines AND space in the flex container to space them out. You can also use align-items and align-self to move the flex items on the cross axis in relationship to each other and their flex line.
For more on alignment in CSS layout see my previous Smashing Magazine articles:
Not all of CSS has fully caught up with this flow-relative, writing mode agnostic way of working. The places where it has not start to stand out as unusual the more you think of things in terms of block and inline, start and end. For example in multi-column layout we specify column-width, which really means column inline-size, as it isn’t mapped to the physical width when working in a vertical writing mode.
As you can see, writing modes underpin much of what we do in CSS, even if we never use a writing mode other than horizontal-tb.
I find it incredibly helpful to think about CSS layout in this writing mode agnostic way. While it is perhaps a little early to be switching all of our properties and values to logical ones, we are already in a flow-relative world when dealing with new layout methods. Having your mental model be one of block and inline, start and end, rather than tied to the four corners of your screen, clarifies many of the things we come across when using flexbox and grid.
As you could guess from the title, this tutorial is dedicated to Mavo: a new, approachable way to create complex, reactive, persistent web applications just by writing HTML and CSS, without a single line of JavaScript and no server backend.
In the tutorial, I will guide you through the entire process of building the app.
At the end of some steps, I provide suggestions for you to experiment with Mavo—to learn a bit more—and to make some enhancements to the application we are building.
In order to illustrate how Mavo enhances standard HTML, we will first create a purely static HTML page and then use Mavo to turn this static HTML into a fully-functional web application.
Let’s add some styling in order to make our HTML look more like an actual flashcards app. You can take a look at the source code and play with it here.
Getting started with Mavo
Right now, all we have is a static template. It’s time to add functionality, so it can actually work like a flashcard application. Here comes Mavo!
In order to use Mavo, we first need to include its JavaScript and CSS files in our page’s section:
To enable Mavo functionality on an HTML structure, we must use the mv-app attribute on the element that contains our Mavo app (which may even be the or element, that’s fine!). Its value is an ID for our app that should be unique in the page.
? Follow the white rabbit!
If we use mv-app without a value and there is no id or name attribute on the same element, a name such as mavo1, mavo2, etc. will be automatically generated.
However, it is strongly recommended to name your Mavo apps, because the name is used in a number of places.
Considering that the element is representing our Mavo app, let’s add the mv-app attribute to it and give our app the ID “flashcards”:
It’s time to tell Mavo what elements of our app are important, i.e., which elements we want to be editable and be saved.
Now we have two such elements, and they are the
elements. Let’s add the property attribute to those elements to tell Mavo they contain data. Elements with the property attribute are called properties.
? Follow the white rabbit!
We can put the property attribute on any HTML5 element, and Mavo knows how to make it editable. For example, for a you edit its contents, but a lets you edit its date/time via an appropriate date/time picker.
You can also expand this set of rules and make elements editable in new ways (e.g., rich text), via plugins.
Keep in mind that the value of the property attribute should describe the element, similarly to an id or class attribute:
...
<p property="source">Word or phrase</div>
<p property="translation">Translation</div>
...
? Follow the white rabbit!
If you already have a class, id, or itemprop attribute that describes the element sufficiently well, you can use property without a value, e.g.,
.
Notice any changes in our app? The Mavo toolbar with an Edit button appeared at the top of the page. The Edit button lets the user switch between read and edit modes. Now our app is in read mode. That means we can’t edit the data on the page.
? Follow the white rabbit!
The Mavo toolbar is fully customizable, as is almost all of the UI generated by Mavo: you can change its placement, remove its default styling, add custom button elements, or use your own HTML elements for it, among other things.
We will see one example of such customization later on in this tutorial.
Visit this section of the Mavo website to learn more.
Now lets us switch to edit mode by clicking the Edit button. What has changed? The text of the Edit button becomes Editing to indicate that we are in edit mode. If you hover over the paragraphs, Mavo communicates that you can click to edit them by highlighting them in yellow. Go ahead! Click the text and edit it. Wow! We can change the content of the page right in place!
? Let’s get our hands dirty!
Assume that in addition to the word and its translation, the flashcard should have an example of the word’s usage in a sentence. Enhance the app by adding the appropriate elements to the flashcard.
At this point, we have only one flashcard in our app. That’s not very useful! For a working flashcard application, we need the ability to add, delete, and rearrange flashcards. How can we do that? We could create more flashcards by adding more
elements to our code, but then how does an end user create and delete flashcards?
Fortunately, Mavo has something to offer that makes this a breeze: the mv-multiple attribute, which tells Mavo that certain elements can be multiplied. It converts the element it’s used on to an editable collection of items and generates (customizable) UI for adding, deleting, and rearranging items.
? Follow the white rabbit!
If mv-multiple is used on an element without a property attribute, Mavo automatically adds property="collection" to it (or collection2, collection3, etc. so that the name is unique). However, it’s recommended to also use a property attribute, to name your collection and make sure its data is preserved if the HTML changes.
Let’s use the mv-multiple attribute in our app to convert our lonely flashcard into a collection of flashcards:
It is also possible to specify the property name as a value of mv-multiple, like so:
.
The mv-multiple attribute goes on the element that will be multiplied, not the container of the collection. It’s a common mistake for people to do
instead of and can often go undetected for a while until the element is inspected or the styling makes it obvious.
Now switch the app to edit mode. Note that below the flashcard, there is now an Add flashcard button. Let’s give it a try: create a few flashcards with the help of that button. Now we can dynamically add new elements right in the app, even though there are no corresponding elements in the HTML. But that is not all!
? Follow the white rabbit!
Note that the property attribute on
does not actually make the entire element editable, but instead acts as a grouping element. This happens when you use the property attribute on elements that contain other properties.
Try hovering over a flashcard and notice the three buttons that appear near its top right corner for adding, deleting and rearranging elements via a drag and drop handle. And by hovering over any item bar button, we can understand which flashcard they correspond: Mavo highlights it. Isn’t that amazing?
? Follow the white rabbit!
You can customize any UI element generated by Mavo, e.g., you can create your own drag handle by using an mv-drag-handle class.
? Follow the white rabbit!
The buttons added by Mavo to every item in a collection are also keyboard accessible. Even reordering: you can focus on the drag handle and use the arrow keys to move the item.
Now that we have the basic UI in place, let’s try the following:
Switch to edit mode (if you haven’t already done so).
Edit the first flashcard’s source word and translation. Add a couple more flashcards too.
Switch the app back to read mode.
And finally… refresh the page.
What?! Where did our data go? Wasn’t Mavo supposed to save it? What happened?
Actually, we never told Mavo if or where to store our data!
To do so, we need to use the mv-storage attribute. What options do we have? Well, Mavo opens great possibilities for us, and Mavo plugins open up even more!
In our application, we are going to store the data in the browser’s localStorage, which is one of the simplest options available, so it’s good for our first Mavo app. We just need to add the attribute mv-storage with the value local to the element with the mv-app attribute (also called the Mavo root).
Have a look at the Mavo toolbar. Notice something? Another button appeared—the Save button.
Try to edit the app data one more time. Note that the Save button is now highlighted. Hover over the Save button, and Mavo will highlight the properties with the unsaved data. Isn’t that cool?
Click the Save button and refresh the page (there is no need to switch to read mode before refreshing the page). Is your data still there? Great! We are one step closer to our goal—a fully-fledged flashcard application.
The mv-autosave attribute
Now we have to click the Save button every time we need our data to be saved? That may be safer, to prevent destroying valuable data, but it can often be inconvenient. Can we just save the data automatically? Sure! To save the data automatically every time it is changed, we can use the mv-autosave attribute on our Mavo root. Its value is the number of seconds to throttle saving by. Let’s add mv-autosave="3" to the root element of our app:
If mv-autosave="3", Mavo can only save at most once every three seconds. This can be especially useful for backends which keep a change history (e.g., GitHub, Dropbox) to prevent flooding which would render that history useless.
To disable throttling and save immediately, we can use mv-autosave="0" or just mv-autosave, which will also remove the Save button from the UI (since it serves no purpose in that case).
Change the data one more time and have a look at the Save button. See? In the beginning, it was highlighted but after 3 seconds–it is not. All our data is now saved automatically!
So, now the main part of our app would look like that:
We are almost done with the alpha version of our app. Now it’s your turn to make the app even better. No worries, you have all the knowledge you need.
Enhance the app so as flashcards could be organized by end users in different groups related to various topics, e.g., the users could gather all the flashcards corresponding to clothing in one group, all the flashcards associated with kitchen utensils in the other one, etc.
? Hints!
There are many ways to achieve that goal, and it’s up to you to decide what to follow. However, I’d like you to think about some questions before proceeding:
What HTML element would you use as a grouping element? It would be convenient for the users if they could see the name of the group of flashcards (topic name) and could collapse the group up to the title.
What Mavo attribute(s) are you going to add to that element, if any? Will the element be a property or a collection?
Will end users be able to add new topics, delete and rearrange them, change the title of a topic and move flashcards between different topics?
What if you decide not to organize flashcards in groups, but instead just label them with tags that correspond to various topics? Well, that is perfectly fine. The solution with tags is also appropriate. For the sake of practice, try to accomplish that approach too.
As our app stores the data locally, by default, the users of the app won’t be able to share their cards with other users. Wouldn’t it be great if we would let them export their flashcards and import somebody else’s flashcards? Thankfully, these features are already implemented in Mavo, and we can very easily add them to our app!
The mv-bar attribute controls which buttons are going to appear in the toolbar, if any. It’s typically specified on the Mavo root (an element with the mv-app attribute). Buttons are represented by their ids (which are very logical): edit, import, export, etc.
As we only want to add a few buttons to the default set, we can use the so-called relative syntax, which allows us to add and remove buttons from the default set without having to explicitly list everything out. All we need is to start the mv-bar attribute’s value with the with keyword.
Give those features a try: add some flashcards, try to export them in a file. Then delete existing flashcards and import the flashcards from the previously exported file.
Let’s now add some statistics to our app, such as the number of flashcards! Sounds interesting? I hoped so. ?
To do that, we need to learn something new about Mavo.
We can dynamically refer to the value of any property we have defined, anywhere in our Mavo app (including in HTML attributes), by putting its name inside brackets, like this: [propertyName]. This is an example of a simple expression, which allows us to dynamically calculate things, reactively as they change.
? Follow the white rabbit!
Mavo’s expression syntax is called MavoScript. It is similar to spreadsheet formulas and lets us perform computations and other operations (with numbers, texts, lists, etc.), but is designed to be more readable and to accommodate nested relations. You can learn more about Mavo expressions and MavoScript in the documentation.
Now let’s experiment and add a [source] expression inside the flashcard property, e.g., between two properties: the source and the translation.
...
<p property="source">Word or phrase</div>
[source]
<p property="translation">Translation</div>
...
What has changed in our app? The value of the flashcard source property is now shown on the page twice.
Switch to edit mode and try to change the value of the source property. Can you see that? The page content updates while you are changing the property value! That’s why I said earlier that Mavo lets us develop reactive web applications.
That’s indeed cool, but unfortunately, in our case, it’s not really helpful: we can’t use this expression to count the number of flashcards—we would always have only one value.
What if we put the [source] expression outside the flashcard property? We will have something like that:
How does this differ from the previous case? To see the difference add some flashcards if you haven’t done so yet. Now instead of one value we have a list of comma separated values: the source property of all flashcards. That’s exactly we were looking for: the number of items in the list corresponds the number of flashcards in the app.
Makes sense? Well, yes, but it wouldn’t it be more logical if we would count the number of flashcards, not the number of values of its source property? After all, a flashcard added exists even before we fill in its source or translation. I suggest you do the following: let’s substitute the [source] expression with [flashcard]:
Noticed the difference? We still have a list, but its values are not simple values but objects, i.e., complex values containing all data that pertains to each flashcard. The good news is that the number of these objects is equal to the number of flashcards, since there is one for each flashcard, even when it’s completely empty. So, right now we have an object for each flashcard, but how do we count them and display the total count?
Now let’s get familiar with the MavoScript functions and find the one that would let us count the number of flashcards. Remember, we have a list of flashcards, so we need to find a function that would let us count the number of items in a list. And here it is—the count() function does exactly that!
But how can we use functions in expressions? Are there any rules we need to be aware of? Well, yes, there is a couple:
Expressions are denoted by brackets.
Do not nest brackets.
Let’s try using the count() function to count the number of flashcards:
And that’s exactly what we were aiming for—now we have some statistics in our app! Isn’t that cool?
? Let’s get our hands dirty!
I hope you’ve already warmed up and ready to continue experimenting with Mavo.
Improve the application so that the statistics are displayed not only for the total number of flashcards in the app but also for the number of flashcards in each topic separately if there are any topics.
?Hint!
Want to filter a list based on some criteria? The where operator will help.
The self-evaluation feature
We already have an application that lets us create, edit and store multiple flashcards. But how do we keep track of which ones we have already learned and which ones we need to practice more? Any respectable flashcards application needs a self-evaluation feature. Let’s investigate how we can add that!
Suppose in our app we have two buttons for the self-evaluation: the Bad and the Good. What exactly do we want to happen every time an end user clicks the buttons? Well, the idea is rather simple:
Clicking the Bad button would indicate the user hasn’t learned the word yet and we want our app to move the corresponding flashcard to the beginning of the list so they could see it as soon as possible after launching the app.
Clicking the Good button would indicate the user has learned the word and the corresponding flashcard needs to move to the end of the list to let them work with other flashcards which they haven’t learned yet.
“Are you sure we can do that without JavaScript?” you may ask. Yep! Mavo is extremely powerful and is able to equip us with all the tools we need!
Now when we know what we are going to implement, let’s set the UI in place first and then move on to the next step. Our markup would look something like this:
Mavo actions allow us to create our very own controls that modify data in custom ways when the user interacts with them. Sounds promising right?
To define a custom action we need to use the mv-action attribute on an appropriate element inside our Mavo app. The action is performed every time the element is clicked. That’s exactly what we were looking for.
? Follow the white rabbit!
For elements a custom action is performed when the form is submitted.
The value of the mv-action attribute is an expression. We can use any of the expression functions and syntax that MavoScript provides to us, as well as a few more to facilitate data manipulation, such as add(), set(), move(), or delete(). It is important to note that unlike normal expressions which are evaluated reactively, these expressions are only evaluated each time the action is triggered.
? Follow the white rabbit!
Mavo expects the value of the mv-action attribute would be an expression, so there is no need to enclose it in brackets: mv-action="expression". Moreover, if we include them, they will be considered part of the expression.
So, we need to move flashcards inside the collection, and Mavo has an appropriate function that lets us do that—the move() function. Its first argument refers to the item we are moving, and the second is its position in the collection. Bear in mind that elements of the collection are numbered starting from 0.
? Follow the white rabbit!
Want to learn more about the move function (and its variants), and about custom actions in general, see the documentation.
Let’s implement the first point of the outline we discussed earlier: while self-evaluating, an end user clicks the Bad button and the corresponding flashcard moves to the beginning of the collection, i.e., it becomes the first one. So in the code, we have:
Pay attention that in the mv-action attribute we refer to the flashcard property inside the property itself, since we want to deal with the current flashcard.
If we try to implement the second point of the outline, we will face a problem. Can you suggest what problem exactly will it be?
Let’s remember that if an end user clicks the Good button the corresponding flashcard moves to the end of the collection, i.e., it becomes the last one. To make a flashcard last in the collection we need to know the number of items in it.
Thankfully, a bit earlier we’ve already solved that task and implemented the corresponding feature. But could we use that solution to solve our current problem? Unfortunately, we can’t: as we already know, we can refer to the collection of flashcards by its name (and evaluate its size) only outside the flashcard property. But in our case, we need to do that inside it: the Good button for which we need to write an expression is inside the flashcard property.
What should we do then? I’m glad you ask. Mavo has the solution.
Using the meta element to hold intermediate values
So, on the one hand, we know that the [count(flashcards)] expression gives us the number of flashcards if it is evaluated outside the flashcard property. On the other hand, we need to use that value inside the flashcard property.
To solve that dilemma, we need to evaluate the number of flashcards outside the flashcard property and somehow hold the result to be able to use it elsewhere in the app, precisely inside the flashcard property. For cases like that, in Mavo, there are so-called computed properties.
To hold an intermediate result so we can refer to it, we need an HTML element in our code. It is recommended to use the element for that purpose, like so: . The advantage of using this element is that it is hidden outside edit mode, both semantically and visually.
? Follow the white rabbit!
Bear in mind that computed properties are not saved by default.
Now let’s add the flashcardCount computed property in our app. Remember, we must place it outside the flashcard property, but then we can refer to it from anywhere:
Only one step left to finish the implementation of the self-evaluation feature: if an end user clicks the Good button the corresponding flashcard moves to the end of the collection, i.e., it becomes the last one. Let’s add the relevant action in the code of our app:
There is another way to solve that task: with the help of the $allspecial property. The $all property represents a collection itself if it is placed inside the collection. So there is no need to use any computed property in this case. Try to implement that solution on your own.
There is only one more tiny thing left that we need to fix. Remember the part where we added some stats to our app? Remember the expression we built to evaluate the number of flashcards in the app: [count(flashcard)]? Instead, we can (and should) now use the computed property we defined. Make the appropriate changes in the app.
Takeaways
So what have we learned so far? Let’s recap. In order to turn any static HTML page into a Mavo app we need to:
Include the Mavo JavaScript and CSS files in the page’s section.
Add the mv-app attribute to the Mavo root element.
Tell Mavo what elements of our app are important by adding the property attribute to them.
Place the mv-multiple attribute on the element that will be multiplied and converted into a collection.
Tell Mavo where to store our data by adding mv-storage attribute to the Mavo root.
Decide whether Mavo should save our data automatically or not. If yes, add the mv-autosave attribute to the Mavo root.
We also know that:
The Mavo toolbar is fully-customizable. The mv-bar attribute controls which buttons are going to appear there.
Expressions let us present the current value of properties in other elements and perform computations. An expression value (and type) vary depending on the place the expression takes in the code. Mavo’s expression syntax is called MavoScript.
Custom actions allow creating controls that modify data in custom ways. To define a custom action set the mv-action attribute on an appropriate element inside a Mavo app
Properties whose values are expressions are called computed properties. To hold an intermediate result to be able to refer to it elsewhere in the app, it is recommended to use the element.
Instead of an epilogue
So we built our app. Is it already perfect? Of course not, nothing is! There are so many things that can be improved, and so many features that can be added (with the help of Mavo, we can even make our app multilingual!). Go ahead, enhance it more, don’t hesitate to try something new!
What we’ve learned so far about Mavo is just the tip of the iceberg, and there is so much more. I encourage you to give it a closer look, by reading the documentation, by examining examples (on the Mavo site, or on CodePen: made by Lea Verou and a few made by myself), and by creating new stuff! Good luck! ?
Acknowledgments
I want to thank two great people. First of all, my huge thanks go to Lea Verou, who not only inspired me to write this tutorial (and helped me make it happen) but also inspires me all the time by the way she makes the world of web development a better place. I’ve never met such a gifted human being, and I am happy having an opportunity to make some stuff with her!