Friday, May 13, 2016

AngularJS and Amazon S3 & CloudFront - HTML5 mode and Social Sharing

The Setup
You have a single page AngularJS application hosted on Amazon S3 and CloudFront. You have used one of the two possible configurations, i.e. with or without static website hosting enabled on S3.

Problem
Sharing a link from your website on Facebook, Twitter, Linkedin etc does not work well, because none of them run JavaScript to understand a shared link. This is a huge problem because in a Single Page Application (SPA) you set the page titles and descriptions using JavaScript.

A minor problem is also that your website urls are not pretty and include hashbang symbols i.e. # or #!. Besides not looking nice, URLs with hashbang symbols also do not work well when links are shared on any of the social networks.

Solution
The first part of the solution requires enabling HTML5 mode in the AngularJS application. Once HTML5 mode is enabled your links will change from
http://example.com/#/path   TO  http://example.com/path
Client Side Changes
This part is simple as shown in this gist


Next make sure all the links in your app are correct
1. Change # to / in all hrefs in your app. This should be easily done via find and replace. Find matches for 'href="#' and replace with 'href="/'
2. Make sure any assets included in the apps' index.html have a href starting with /. That is change any href values from "path/to/css/ to "/path/to/css"

Server Side Changes
Now when you open the home page and use the website by clicking around everything should work fine. However, if you copy paste a link directly in the browser you will get a 404. To fix this 404 error we need some server side changes.

 - Development (Grunt)
Quite likely you are using Grunt on your dev machine. First install connect-modrewrite and then add a middleware to the livereload section as shown in this gist.


 - Production (Amazon S3 and CloudFront)
Assuming you do NOT have static website hosting enabled on S3. All you have to do is create couple of Custom Error Responses on CloudFront.



Detect JavaScript Support
We filter out the social networks by providing them with a static HTML page containing all the relevant meta tags, and also a simple JavaScript snippet that redirects JavaScript-capable browsers to the root URL, with the correct route hashed out, so that CloudFront & S3 take you to the application and Angular interprets the route correctly. An example of such a file is shown in this gist.

Now when you share the link "https://example.com/path/index.html" social networks will be able to create nice cards. When a user clicks on this link, they will be redirected to the right place.

Notice that the shared link includes "index.html", we can get rid of that if we enable Static Website Hosting on S3. More on that later...

Refrences
1. https://medium.com/@gigbloc/deep-linking-rich-social-sharing-seo-with-angularjs-and-amazon-s3-82f99cf83cb5#.fl6miptq1
2. http://www.ericluwj.com/2015/11/17/seo-for-angularjs-on-s3.html
3. http://www.ericluwj.com/2015/11/10/angularjs-with-html5-mode-on-s3.html
4. http://stackoverflow.com/questions/24283653/angularjs-html5mode-using-grunt-connect-grunt-0-4-5

Deploy a static web app to AWS Cloudfront and S3

There are two ways to deploy a static web apps to AWS CloudFront and S3.

1. Enable Static Website Hosting on S3. Once this is enabled, you can also setup CloudFront to point to S3 website endpoint. Make sure this is not the standard S3 endpoint. Here, CloudFront is simply caching the static files. All files in S3 will also be accessible without CloudFront.

2. Use CloudFront to point to the standard S3 endpoint. This way you make S3 bucket contents available only to CloudFront. In this scenario CloudFront both caches the files and is also a gatekeeper to all the files.

Tuesday, October 20, 2015

What to use for login - username, email or phone number?

It seems trivial on surface, pick a strategy and go with it. However, it can be useful to pause a think about your exact use case as each of username, email and phone number have distinct pros and cons.

If you are developing a mobile app, phone number along with a one time password is a good option to use for login. Whatsapp, Telegram and others use this strategy. The clear advantage is that most users have a phone number (people with tablets may not have a phone number), and a user does not have to remember a password. However, phone numbers can change often, especially if a user moves to a different city or country. As a result, a user can lose access to their account unless the app allows to change phone numbers by some means. Moreover, a user's phone number may have previously belonged to someone else. This may result in a user getting access to someone else's account. Users may need to provide an email or an alternate phone number to help avoid these pitfalls.

Username along with a password is a good option both for mobile apps and web apps. A user can choose a unique username and a password. Now no user can access another user's account by accident as in the case of phone numbers, and the user does not lose access to their account as long as they remember the username and password. However, remembering usernames and passwords for all the different apps is hard. An email address or phone number would be required for username and password recovery. One big advantage of usernames is that users can try your app without providing their personal information i.e. email or phone number. Also, the registration step can be really quick, if users don't have to verify their email or phone number to start using the app or wait for a one time password. Snapchat uses this strategy. At the time of registration it asks for username, password and email, but does not force you to verify the email before using the app. You can verify your email later (you may not have email setup on your phone) so that you can recover your account details in case you forget them.

For web apps, email along with a password is a good option. Emails should typically change less frequently than phone numbers. (Some people use the email from their ISPs and hence end up changing it frequently, but I suspect they are in a minority). If emails are used, users don't need to remember a username and an email is already unique, so a user does not have to spend time coming up with something unique as in the case of usernames. Recovery of account details with an email is also simple. However, it is a good idea to get a user to verify their email address. Some apps force users to complete this verification before giving them access to the app, which lengthens the registration process. On the other hand, if emails are not verified, you may end up in a situation where another user has created an account with your email address, and hence you cannot use that email address to create an account. Users on popular apps like Facebook often face this situation. Email with a password can also be used for mobile apps, however it is useful to remember that a user may not have email setup on their phone hence may not be able to verify their email right away, or access an one time password. 

Thursday, September 10, 2015

Use different email address for different Git repositories

Navigate to the repository directory, use the following commands to set user config for that repository
$ git config user.name "Deepak Azad"
$ git config user.email "deepak@example.com"
Alternatively, modify the config file of the repository directly and add the following lines to it
[user]
name = Deepak Azad
email = deepak@example.com

Tuesday, July 7, 2015

Bringing back conversations

We are a generation that relies heavily on technology to stay connected to friends. There are many alternatives that make being connected very convenient. We like sending texts over WhatsApp or Facebook Messenger, or having a fun exchange of doodled-pictures on Snapchat, or liking someone’s photos on Instagram, and so on to "stay in touch". These are convenient to use. You don’t need to give your full attention. They’re not in real-time, which means we get to edit, delete, retouch, to make it just as we want it to be. “I would rather text than talk” has become more common, but these lack the basic elements that make it an conversation - body language, eye contact, tone of voice, mood, emotions etc.

These connections end up replacing the conversations in our lives. We connect with more and more people. But in the process, we set ourselves up to be isolated because of lack of conversations. We are connected yet lonely.

Actively engaging in a conversation requires phone/voice calls, video calls using FaceTime, Skype, and likewise. They’re the next best thing to seeing someone in-person. However, they have a lot of resistance associated with them. For example, a lot of effort usually goes in scheduling of video calls, and there is always the uncertainty about how long they will take.

We decided to take on these problems by building something that brings conversations back in people’s lives, something that allows you to connect as intimately as a face-to-face conversation and as conveniently as a text message. This is our new app Knock.

Knock keeps video calls short to just 5 minutes. In our tests, we found that it's ample time to catch up if you're regularly in touch. It is easy to find 5 minutes for a quick catch-up with someone. You’re more likely to answer if you know the calls are guaranteed to be short. 

Short and timed video calls

We also allow you to Knock multiple friends at the same time to see who is available at that moment. The app queues up the knocks, and you get on a call with whoever is the first one to respond.

Knock multiple friends at the same time

When you don’t see a Knock, we delete the notification from your phone. As a result there is no notification clutter on your device, and you don't feel pressured to call back right away. But, we do make sure that you know who was "thinking of you" (you missed their Knocks). You can always open the app and check that. However, we don't show when or how many times they Knock’d, or don’t tell them you saw it when you see it. 

No notification clutter
Find out who was "Thinking of you"

It's like knocking on someone's door for a quick chat, and leaving a little note behind to let them know that you stopped by.

Putting it concisely connections are useful, but we love conversations! Knock is our try to bring back the conversations. Knock is currently in beta and is available on iOS. Download it here. Invite your friends, and Just Knock! :)

Thursday, January 30, 2014

Invalid techniques of proof

Recently I took an algorithms course which involved a lot of proofs. I used to work together with my buddies on some of the hard problems, and while trying to come up with a proof for a particularly hard problem I would often joking say to my buddies "I bet a $1000 that this is true, are you willing to take this bet?" "Proof is complete if no one takes the bet."

While searching for types of proof techniques, I stumbled across this hilarious collection of invalid proof techniques. Obviously, I had to submit my proof technique as well, which is now part of that amazing collection.

Monday, November 19, 2012

Contributing Java Editor templates via a plugin

JDT provides several editor templates. You can also add your own via the Templates View. However, if you want to share the templates between your several workspaces or with others you can also create a plugin.

As a first step, define the following extension for the extension point org.eclipse.ui.editors.templates.
   <extension
         point="org.eclipse.ui.editors.templates">
      <include
      file="templates/default-templates.xml"
      translations="$nl$/templates/default-templates.properties">
      </include>
   </extension>
The xml file just contains the template descriptors. For example, here is a template for printing the enclosing type and the enclosing method.
<template name="debugout" description="%Templates.debugout" id="com.eclipse.jdt.ui.templates.debugout" context="java-statements" enabled="true" autoinsert="true">
System.out.println("${enclosing_type}#${enclosing_method}(..)");${cursor}
</template>
You can read about the available template variables in Eclipse help.

I have also shared a plugin with the above code on GitHub.