Tutorial: Create a Twitter app with Vue.js, Framework7 and PhoneGap

In my last post I showed you how to kick-off a new project with Framework7, VueJS and Webpack. So, I thought in the next video I could show you a real-world example on how to create an app based on these technologies.

In this screencast we will create a Twitter client for iOS and Android that will let you search for tweets through the official Twitter REST API.

Keep in mind that this is the first episode of a series since we won’t be able to create a full Twitter app in only one episode. Instead, we will cover one topic in each video. The series topics will probably look something like this:

  1. Setup project + Call Twitter search API methods (This video)
  2. Authenticate users using oauth + Render personal timeline
  3. Post tweets, retweet and replies
  4. Deploy as native app using Phonegap/Cordova

Enjoy the video series! :-)

Source code

How we became the 2nd fastest online retail shop in Germany

Dynatrace Performance Benchmark about website performance

Source: Dynatrace Performance Benchmark

I’ve been working for my client HSE24 for quite some time now on optimizing their website’s load performance with their team. In this article I’d like to share how and what we optimized to become the 2nd fastest retail online shop in Germany according to Dynatrace Performance Benchmark.

Actions to improve website performance

Disclaimer: This isn’t a comprehensive list. It’s just what I could remember we’ve been working on for the past 2,5 years.

Remove unnecessary event listeners

We removed all bindings to the document for scroll, touchmove, touchstart, touchend and tap as these are fired constantly while using the site.

Remove unused and unnecessary JavaScript libraries

Since Webkit supports fast clicks on mobile now, we were able to remove libs like Fastclick.js. Also, browsers nowadays have support for many advanced features like e.g. sticky positioning which makes libs like Sticky.js redundant.

Use lazy loading

We use lazyloadxt.js to load images only when they become visible to the viewport.

Hardware-accelerate animations via GPU

jQuery’s $.animate() method is convenient but very slow. We replaced as many animations with CSS3 translate3D(x,y,z) as possible. This will force the device to render via GPU and will thus be much smoother than with software rendering.

Reduce CSS effects like gradients and transparency

Both have a huge impact on performance. Use with care and remove as much as possible. Talk to your designer. Explain this in a friendly way and he or she will understand.

Reduce the amount of HTTP requests

Nowadays, bandwidth on mobile devices is no problem due to HSDPA+ and LTE. The bottleneck is latency on mobile networks. Thus, you have to reduce the number of HTTP requests to a minimum. Put all your JS code into one file, same for CSS (unless you’re on HTTP/2).

Reduce the amount of setInterval() and setTimeout()

Just don’t use these at all if possible.

Init carousels on demand

We have a lot of carousels to show our products. Some are hidden behind tab components and are thus not visible unless you click on one of them. Hence, we only initialize those which can be seen in the first place. When the user clicks a tab, we init carousels on demand.

Use frameworks/libs which care about performance

We replaced OwlCarousel with Swiper.js. What a huge difference!

Drop support for legacy browsers

Optimizing for older browsers has a huge impact on the possibilities to improve performance. Thus, we dropped support for Internet Explorer versions older than 11. Also, on mobile we only support Chrome and Safari. Buggy browsers like Android Stock Browser or Samsung’s built-in desaster is not supported.

Reduce the amount of reflows

It’s a little old but the legendary Paul Irish did a great video about reflows. Drop everything you’re doing and watch it NOW!

Load as few external scripts as possible

Scripts from external sources are a nightmare. They cause additional DNS resolution calls and you make your site dependent to external servers which can lead to slowdown and sometimes even malfunction. Thus, we try to host as much on our own as possible. We do not use CDN’s even if they have some advantages but we like to keep our destiny in our own hands.

Reference Scripts at the end of the document

Never reference your scripts in the head section of your html document. Put them at the end of <body> if possible. Also, try to use defer or async. Use with caution though!

Remove dead JavaScript code

JavaScript is a nightmare to maintain. You never know which functions are still called and which are not. Thus, we created a logger which writes all function calls during runtime to a database via Kibana. With this list we’re able to determine if a function is still called or not and remove it.

Develop for the weakest devices

Go to eBay and buy an iPhone5 as well as a Samsung Galaxy S5 (or S4 if you wanna go hardcore). When you’re done developing a feature, test it with these two devices. If everything runs smoothly, you’re good because faster devices will run it at least as good as your minimum testing devices.

Reduce images size

Our CMS is able to scale down uploaded images. So we defined templates for screen sizes of width 320px, 480px, 768px, 1024px, 1280px and 1920px. Anything beyond this will be scaled down. Also, JPEG should be compressed with setting “85” (equals 15% compression) which is a good trade-off between image size and quality.

Switch from Apache to NGINX

NGINX is great at delivering many small static files in a short period of time. You should use it, if you can.

Use a static subdomain

We deliver all our static media (scripts, stylesheets, fonts, images…) via an own subdomain static.hse24-dach.net because we do not set any cookies for it (static media does not require cookie information at all). Hence, the cookie overhead for each request should be 0.

Improve cache configuration

We set max-age to 30 days in the HTTP headers for all static media to optimize browser caching. When a file changes, we also change the reference URL to notify the browser that it should get a fresh copy of the ressource. For example, if foo.jpg has changed, we automatically also increment our cid parameter: <img src="foo.jpg?cid=2">

Pre-generate images

We used to have a web application which generates scaled variants of images on demand. This is to slow because the application has to be called for every request and server caching is quite tricky in this case. Thus, we pre-generate all scaled versions of the images we have and deploy them statically on our NGINX servers which is blazing fast. This requires multiple terabytes of data but remember that storage these days is cheap compared to CPU power.

Improve the build process

We cleaned up our Grunt build file and optimized it to get the fastest performance possible. Also, we replaced our SASS compiler which was based on Ruby with a much faster C++ version. This doesn’t have direct impact on website load performance, but the faster devs can work, the faster and better you get the job done. Also, it’s more fun :-)

Use server side includes for static HTML

We use SSI to include static HTML (like e.g. header, footer, navigation..) into our templates in order to be able to cache these HTML snippets. We only render the part of the HTML which is dynamically created by our web application server like e.g. personalized content. This is way faster than composing the whole page for each request.

Simplify content

We used to have a lot of content on our homepage. It’s still not as lightweight as I think it should be but it got much better. Check all components on your page and ask yourself: Do I really need this? Does it benefit either me or the user? If not, trash it.

Care about performance

Our technical lead used to be a developer, so he cares about performance which is a good thing. If you’re looking for a new job, I can highly recommend to check the background of your next supervisor. It’s much easier to work with a technical person than with a manager type guy.


You have to keep pushing forward. Don’t rest. When you stop optimizing your site will end in a big slow mess in a few years since requirements for new features continue to grow which usually eats more CPU power as well as network bandwidth. There are still many more things we’re working on to push load times even faster, like e.g. removing dead CSS code. Unfortunately this is not an easy task and there are no best practices that I’m aware of. If you have any suggestions, let me know :-)

Why I am still in love with Framework7

Disclaimler: First of all, let me state clear that I am not involved into the Framework7 project. I am not getting paid for this post. This is just my honest, personal opinion as a mobile developer.

Early steps

The first framework I used when I started mobile development was jQueryMobile. I was used to jQuery coming from Desktop programming so I thought: “Hey, it says jQuery, so I guess it must be good”. It sucked balls, just like any other Framework I tried like KendoUI, SenchaTouch or Ionic. They either sucked regarding performance, sucked about look & feel or simply sucked monkey ass ballz! Excuse me for my language but for years I couldn’t believe that it was true that there is no HTML5-framework that can deliver anything close to a native app, so I always believed that it simply wasn’t possible.

And then I discovered Framework7

Oh, boy was I blown away when I saw the first demos for iOS on their website. This was just what I was looking for. The way these apps looked, feeled and performed was 99.9% accurate to what I am used from native apps. I couldn’t believe it and so I tipped my first steps in. I quickly found out that Framework7 was not only easy to use, it just worked™. You create a few lines of HTML markup and boom, that’s it. Framework7 will take care of the rest. The looks, the page transitions all works out of the box. I couldn’t believe it and why hadn’t I heard about it before? I don’t know but since they also released a new Material Design option for Android I am absolutely convinced: This is it. The best framework you could possibly use for mobile app development with HTML5, CSS3 and JavaScript. Throw that all into a PhoneGap/Cordova container and you should be fine.


framework7 demo screenshot


For iPhone open this.
On Android open this.

The future

The biggest problem I see with Framework7 is that it doesn’t get enough attention. For years I didn’t hear anything about it and when I talk to other devs they never saw it before until I show em and they’re all completely blown away.

Also, if you search for “best html5 mobile framework” on Google you will get shitloads of so called comparison websites like “Top 10 mobile frameworks” and barely I see F7 mentioned or even find their main website in the search results. So, if you like F7 and you’d like to support, go tweet about it right now!

I just hope that developers haven’t given up on HTML5 for apps yet. Since the hype of Facebook’s React framework many people seem to transition there.

Oh, boy I need to go back coding. This is so much fun <3

How to add dots every 3 digits in currency values with JavaScript

If you’re European like me, you’re probably used to this notation:
€ 366.432 instead of 366,432 or 366432.
In order to get this done in JavaScript you want to do the following:

// Number
var money = 366432;
// Convert to String and add dots every 3 digits
var moneyDots = money.toString().replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1.");
// Set in HTML
$('.anywhere').text('€ ' + moneyDots);

Keep in mind that moneyDots is a String from now on! It’s not a number anymore!


I wanted to create a similar experience to those cards that you can swipe left and right in Tinder, but with web technology. So I did. There are already 2 libs that do this but they’re based on Ionic which I didn’t want to have a dependency on. Tindercards.js only requires jQuery and Hammer.js.

The result looks like this:

Video demo

On YouTube: https://youtu.be/LqZ3wqvvZwE


Tindercards.js demo screenshot

Live Demo

Works best on iPhone: http://www.timo-ernst.net/misc/tindercardsjsdemo/


Tested on

  • iOS Safari

API Documentation

There are just two components that you need. A prototype object called Tindercardsjs.card and a method called Tindercardsjs.render. The signatures are like this:

 * Representation of 1 card on the stack.
 * This is a prototype object! Initialize with "new" keyword
 * @param {String} cardid Pass a unique id for each card so you know later which card is which
 * @param {String} name The name of the person on the card
 * @param {String} description The description text of that person
 * @param {String} imgpath The path to the img
Tindercardsjs.card(cardid, name, description, imgpath)
 * Renders the given stack into the given jQuery element.
 * This is a method, just call it. Parameter "cards" must be an
 * array of Tindercardsjs.card
 * @param {Array} cards An array of cards (@see Tindercardsjs.card)
 * @param {jQuery} target The target in which the stack should be rendered to
 * @param {function} onSwiped Callback function when swipe has occurred. Will pass an event object as parameter with properties event.cardid (the card id), event.card (The jQuery object that contains the card dom element) and event.direction ('left' or 'right').
Tindercardsjs.render(cards, target, onSwiped)

How to use

  1. Make sure you have hammer.js und jQuery referenced
  2. Then, add tindercards.js from /lib
  3. Initialize like this:
var cards = [
  new Tindercardsjs.card(2, 'Geordi Laforge', 'I like big butts', 'gfx/pics/01.jpg'),
  new Tindercardsjs.card(1, 'Agro Picard', 'Hates Klingons, likes beer.', 'gfx/pics/02.jpg'),
  new Tindercardsjs.card(0, 'Jean-Luc, Worf & William', 'Swipe right if you also like funny hats like us :D', 'gfx/pics/03.jpg')

And pass them to Tindercards.js like this:

Tindercardsjs.render(cards, $('#main'), function (event) {
  console.log('Swiped ' + event.direction + ', cardid is ' + event.cardid + ' and target is:');

The stack will then be rendered to a HTML container that has id “main”. You can of course change that to some other name if you want.


The html container (in this case #main) should have either position:absolute or position:relative!

Download lib & example code

Grab it on GitHub