A new look for Go Tripod
One of the problems with being a small, independent software development agency is that we're usually so busy on client projects that we don't often get much time to devote to our own business needs.
To this end our own website has languished as a glorified holding page for quite some time. But no longer!
Today, with some helpful input and invaluable guidance from creative gurus Curious Ways, we've been able to launch a new look Go Tripod website.
In the true spirit of agile development, this initial launch covers the bare minimum content and functionality we deemed necessary. This includes a homepage that briefly outlines our business offerings, a contact page and all our previous blog posts. We'll be extending our new website to include case studies, portfolio pieces and more information on our services in good time. So, watch this space.
In the process of redesigning our website, we've also rebranded our company and plan to roll these changes out to our various social media accounts and other corporate channels over the next few days.
We're the same company on the inside, but with a fresh new look on the outside.
Dynamically generating responsive images with Timber's resize filter and the srcset attribute
Timber has loads of useful filters built in which can make all kinds of jobs much easier. One of those jobs is resizing and cropping images, for which we can use the resize filter. The syntax is simple, as with all things Twig - we simply add the filter to our image source, passing through a width or height to resize or both to crop.
The following example will resize the image to a width of 300px while retaining its aspect ratio:
{{ item.src|resize(300) }}
The following example will resize the image to a height of 300px while retaining its aspect ratio:
{{ item.src|resize(0, 300) }}
The following example will crop the image to a width and height of 300px:
{{ item.src|resize(300, 300) }}
We can then define multiple sizes and pass these into a srcset attribute to make sure we’re serving a suitable image size based on the device viewport. This is especially important for mobile devices who don’t need to download and display a full HD hero image on a 320px wide screen.
The following example defines three sizes, one for mobile, tablet and desktop - devices with a viewport width of up to 480px will get the 480px wide image and so on.
srcset="{{ item.src|resize(480) }} 480w, {{ item.src|resize(1280) }}
1280w, {{ item.src|resize(1920) }} 1920w"
If you’re new to srcset or want to delve into it a bit deeper, CSS Tricks’ article is a good read.
Improving site response times by deferring the downloading of web fonts
One of the first things I decided to tackle as part of my recent work on website response times, assuming it’d be a simple process, was render blocking web fonts. Little did I know I was opening up a right can of words (sorry)…
Numerous techniques have been developed over the past few years with varying levels of difficulty, visual effects and results as described in detail here. The two main visual effects that divide opinion are whether to go down the FOIT (Flash Of Invisible Text) or FOUT (Flash Of Unstyled Text) route. There now seems to be a general consensus within the community that FOUT is preferable for UX reasons with most research showing that it’s better to give users something than nothing - this is especially important for users on slow connections and can lead to high bounce rates.
NB: FOFT (Flash of Faux Text) is the new kid in town but I’ve not tried to implement it yet so won’t discuss here.
After some research I decided to go with Web Font Loader, a script born from a collaboration between Google and Typekit to easily load fonts from a variety of services. We want to load this script asynchronously to avoid it blocking page render so the browser will initially display the content using system fonts and apply the web fonts once they’ve downloaded. The example code below is what you’ll need to add within the head to load Open Sans:
<script async defer type="text/javascript">
WebFontConfig = {
google: {
families: ['Open Sans']
}
};
(function(d) {
var wf = d.createElement('script'), s = d.scripts[0];
wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js';
wf.async = true;
s.parentNode.insertBefore(wf, s);
})(document);
</script>
One drawback of this approach is its reliance on JavaScript - users with JavaScript disabled will be stuck with system fonts. This is a tiny number of users, around 0.2%, so we can argue this progressive enhancement benefitting 99.8% of users is worth the sacrifice. Of course, if you’re using web fonts that are wildly different to the fallback system fonts loading before them you probably won’t want to use FOUT as the change in style would be too noticeable. In extreme cases this can even lead to changes in layout so, as with all things dev, do make sure you test thoroughly - you wouldn’t want a user on a slow connection to get halfway through a sentence then find it’s moved position!
Making use of the defer attribute to easily eliminate render blocking scripts
When working on improving the response time of your site, one of the simplest optimisations to make is the deferring of scripts. In most cases, this can be done with the simple addition of the defer attribute to the script tags within your HTML:
<script src="" defer></script>
When a browser gets to a script tag in your code, its default behaviour is to pause parsing of the HTML, opting to download and execute the script before resuming. Setting the defer attribute tells the browser not to pause, but instead download the script in the background and execute it once parsing of the HTML has completed.
Another feature of using defer, which can be very useful, is that all scripts with the defer attribute will execute in the order they’re presented in your HTML. This is especially useful when writing scripts which rely on others as you can ensure these dependencies are executed first.
Scripts can also be executed asynchronously using the async attribute but bear in mind that it should only be used if the script is not relied upon or does not rely on any others and will function correctly if run before HTML has finished parsing. For a clear visual representation of the different script loading options, this article has some simple infographics I’d recommend taking a look at.
If you’re developing WordPress themes without the use of a template engine like Timber, you may not be able to edit this HTML and should instead make use of the wp_enqueue_script function within your theme’s functions.php file - you should also use this method if using any WordPress plugins which run scripts on your site’s front end.
Welcome to our new WordPress, HTML5 and CSS hero Matthew Dixon
A warm welcome to our latest team member, Matthew Dixon!
Matthew joins us as Lead Front-End Developer, and will be working to translate responsive designs into wonderful web experiences. His HTML5, CSS3 and WordPress experience will combine with our new hosting partner, WP Engine, to work with both new and existing customers!
Go Tripod go serverless with React Native and Amazon Web Services
This post was originally published on our Technical Director's personal blog.
Amazon's cloud offering, AWS, provides a wealth of resources for developers and infrastructure engineers. In this article, I'll show how Amazon Cognito can be used to record user preferences and data without having to set up a server or database. I'll build a small React Native application which allows a user to log in with Facebook and save some data to the cloud for later retrieval.
Facebook Login
Prerequisites:
- Install npm and CocoaPods if you don't have them already
- Install React Native
- Create a new Facebook iOS app in the developer centre
Let's start by creating our React Native project and entering the project directory:
react-native init FacebookAwsReactNative
cd FacebookAwsReactNative
Let's install the Facebook React Native SDK via npm, that'll give us a nice login button for free:
npm install --save react-native-fbsdkcore react-native-fbsdklogin
We need to install some native code to make this work, so let's do that with CocoaPods. First we create a Podfile:
cd ios
pod init
Edit the file which was just created at FacebookAwsReactNative/ios/Podfile and add the following:
source 'https://github.com/CocoaPods/Specs.git'
pod 'React', :subspecs => ['Core', 'RCTImage', 'RCTNetwork', 'RCTText', 'RCTWebSocket'], :path => '../node_modules/react-native'
pod 'react-native-fbsdkcore', :path => '../node_modules/react-native-fbsdkcore'
pod 'react-native-fbsdklogin', :path => '../node_modules/react-native-fbsdklogin'
pod 'react-native-fbsdkshare', :path => '../node_modules/react-native-fbsdkshare'
You may need to perform some other steps here, as per the Facebook documentation. Go and have a read of that section just in case. Let's install the pods and then we'll have to faff around in Xcode for a bit.
pod install
open FacebookAwsReactNative.xcworkspace
Notice that we now use the xcworkspace file rather than the xcodeproj file; this is required for CocoaPods to do its thing.
Xcode Is Quite Horrible Really
Expand the FacebookAwsReactNative > Libraries folder and select all of the items in there and delete the references to them. This is because we've opted to use CocoaPods for React Native (see the pod 'React' line we added to the Podfile) so the items in Libraries are duplicates.
Let's move on to configuring the Facebook SDK. Open up info.plist using Open As > Source Code, and add the follow inside the root <dict> node:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>fb{your-app-id}</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>{your-app-id}</string>
<key>FacebookDisplayName</key>
<string>{your-app-name}</string>
Next, open AppDelegate.m and add a new import:
#import <FBSDKCoreKit/FBSDKCoreKit.h>
Connect our AppDelegate to the FBSDKApplicationDelegate by adding the following to didFinishLaunchingWithOptions:
[[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
And finally, add a method to allow us to navigate back to our app from Facebook:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
return [[FBSDKApplicationDelegate sharedInstance] application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation
];
}
Wonderful. Run the project and get your simulator running because we're now ready to add our login button.
Push The Button
We need to import the button component, and at the same time we'll import another class that we'll use later. Add the following:
import { FBSDKAccessToken } from 'react-native-fbsdkcore';
import { FBSDKLoginButton } from 'react-native-fbsdklogin';
Delete all of the default stuff inside the <View> component and replace it with the button code:
<FBSDKLoginButton
onLoginFinished={this.onLoginFinished}
onLogoutFinished={this.onLogoutFinished=}
readPermissions={[]}
publishPermissions={['publish_actions']}/>
We now need to add onLoginFinished and onLogoutFinished methods to our FacebookAwsReactNative class.
onLogoutFinished() {
alert('Logged out.');
}
Simple!
onLoginFinished(error, result) {
if (error) {
alert('Error logging in.');
} else {
if (result.isCancelled) {
alert('Login cancelled.');
} else {
alert('Login success!');
}
}
}
Less simple, but pretty self-explanatory. At this point, you should be able to run the app and login via Facebook, with the various alert messages firing as appropriate.
But we want to take one more step; we want to be able to link this login to persistent data stored on Amazon Cognito. This needs two steps: firstly to get a unique token to identify the Facebook login, and secondly, to sync local data up to Cognito. Fortunately this becomes super-easy thanks to the Amazon SDK and the React Native Cognito project.
First, we need to get an access token from Facebook to use as a link between FB and Cognito. FBSDKAccessToken.getCurrentAccessToken takes a single callback argument which is passed the token we need. We then need to install (follow the instructions) and import React Native Cognito. Add this along with your other import statements:
import Cognito from 'react-native-cognito';
Next, we initialise the credentials for Cognito and sync up some data!
FBSDKAccessToken.getCurrentAccessToken((token) => {
if (token) {
Cognito.initCredentialsProvider(
awsIdentityPoolId,
token.tokenString,
awsRegion);
Cognito.syncData('testDataset', 'key', 'value', (err) => {
// success!
});
}
});
You'll need to have created a Federated Identity Pool and set up Facebook as an Authentication Provider. Populate the awsIdentityPoolId and awsRegion variables accordingly and the above code can be run at any point after a successful login.
Visit the Identity Pool in the AWS Console and you'll see a dataset called "testDataset" with a single key/value entry.
This has been a whistlestop tour on moving to a serverless setup with Facebook logins and Amazon Cognito. The full code can be found on GitHub.
Go Tripod's business development days
In years past, Google was renowned for its 20% time - a developer was allowed to allocate one day a week to working on ideas that weren't necessarily related to their normal Googley projects. Some of these ideas were even spun off into new properties for Google, and some were incorporated into existing internal and public-facing projects.
The idea of freeing employees up to do something which inspires them is clearly enticing; in fact there's been lots of research which indicates that a four day work-week is as productive - if not more productive - than a five day week.
At Go Tripod, we're constantly thinking about how to mix up our business, how to keep things fresh, and how to improve the way we work. At the same time we're a consultancy, so allocating a full day a week to something like this a bit impractical being a fairly small company.
What to do?
Once A Month
Let's compromise: Go Tripod will be taking one day a month out to work on internal projects, marketing, new ideas and exciting bits and bobs. During these days we'll only be answering support tickets. Imagine it as a staff training day, or an inset day at a British school, where the employees spend some time to take stock, plan ahead, and come up with improvements.
Internal Projects
We use tools like Basecamp, Slack and Freshbooks to manage projects, to communicate, and to invoice. Some of these don't always work as smoothly as we like, and so to improve the service we can give to our clients, we build internal tools to improve our workflow. On the GTBDD (catchy!), we'll be seeing if there's anything we can do to further these tools or if there are new ones we can build.
Products
Every consultancy would love to have some SAAS to bring in recurring revenue. We'll be examining the industries we know best and hitting the whiteboard to see if there are any tasty opportunities for us to launch a new product in 2016.
Learning
In the past year we've been working with React and React Native, both of which have given us important tools to improve the quality, and reduce the cost, of our work. This year, we'll continue to look at the latest technologies and strengthen our knowledge of our existing box of tricks, and the GTBDD will give us more of an opportunity to do so.
Fun & Games
On top of these virtuous goals, we'll also be doing some stuff to blow off steam as a team. Whether that's researching some JavaScript games framework, playing with a few Raspberry Pis, or just taking time out in Cornwall to do something a bit more outdoorsy - we'll have one day a month to do it.
Happy New Year
We hope that this is an experiment that will help both Go Tripod and our clients. We've structured it in such a way that it will cause minimal disruption to our business but we're doing it often enough for it to be of real benefit to us. Here's to an exciting 2016!
We like React Native
Colin's started playing around with the new React Native from Facebook, a way of building native-speed applications for iOS using JavaScript. It's a completely new approach and we're really excited about it - follow Colin's experiments over at his personal blog.