How I Built readyforkhanacademy.com and What I Learned Applying to Khan Academy

Anthony Su
24 min readNov 12, 2014

Introduction

About 2 months ago I launched http://www.readyforkhanacademy.com/ to complement my application to Khan Academy as a software engineer. (The idea to build this site was largely inspired by previous individual work: http://readyformozilla.com/, http://florianisallin.com/). My web application was a 3D slide deck built over the course of July to September 2014. (This site is still up if you want to explore around. Use the arrow keys or mousewheel to navigate.) Here is a screen-recording of the experience.

https://vimeo.com/110128536

After launching the site, I received an opportunity to interview with Khan Academy. Although I did not end up getting hired, the whole process was a great experience. I learned a lot along the way and I got an opportunity to speak to a couple developers at Khan Academy. For the privacy of Khan Academy and myself, I won’t disclose any interview details. Instead, this post will focus on the whole process for building http://www.readyforkhanacademy.com/(research, design, implementation, and launch) and what I learned.

Motivation

Why I applied to Khan Academy

https://vimeo.com/36579366

Bret Victor’s talk Inventing On Principle helped shaped my decision to apply to Khan Academy. In his talk, Bret discusses a way to live your life by finding a guiding principle (something that you believe is important, necessary, and right) and using that you guide what you do. His guiding principle is creators need an immediate connection to what they’re creating and I was impressed by way how well his work reflected his principle. While I felt like I didn’t have enough life experience yet to pinpoint my guiding principle, I decided that I wanted to help out Khan Academy’s mission: changing the world for the better by providing a free world-class education for anyone anywhere.

I was also particular interested in Khan Academy because their work is very involved in grade-school education and they had been already been testing out the flipped classroom model at local schools.

Handling Risk

Applying to Khan Academy was definitely a stretch goal. Considering the relatively small size of the company and the talent of both full-time employees and interns, the application pool is likely very competitive. I wasn’t sure how unique my custom site would be because applicants had also submitted custom projects in the past. Also creating a campaign site would at best help me get an interview, so I still needed to perform better among other candidates also interviewing. Accounting for these risks, I needed to realistically be prepared for handling rejection. I decided that I would document and blog about the project and also make the repository publicly available, so that I could keep track of what I learned and potential employers could get a good assessment of my interests, my coding ability, and how I thought about building things.

Research and Conceptualization

Understanding the Target Audience

My first step before building anything was to understand the audience for my project: the people at Khan Academy. I first read Salman Khan’s book, The One World Schoolhouse : Education Reimagined , to get a understanding of his opinions about education. Reading his book helped me understand how Khan Academy’s platform related to the notion of a flipped classroom. I also liked his idea of a “creative portfolio” as a central part of a student’s “transcript” especially as mind jobs are becoming more prevalent. The last sentence of the chapter Future Transcripts summarizes this idea best:

More than any data, grades, or assessment, someone’s actual creative product is the best testament of his or her ability to create from scratch, to make a solution out of an open-ended problem.

Khan’s ideas of redefining summer were also thought-provoking as he discussed ways to potentially mitigate unlearning that often occurs during summers.

Next, I began reading more about the developers at Khan Academy. One of the great things about Khan Academy is that they encourage their developers to blog and share their knowledge. By reading their blogs I got good view of their interests and the particular engineering challenges that were being tackled at Khan Academy. I found Stephanie’s story about how hard she worked to get into Khan Academy also quite inspiring.

Be Specific

I also thought about particular areas I may be interested in working at at Khan Academy and my how my qualifications pertained to these interests. I was/am especially excited Khan Academy’s Computer Science team because of their focus of introducing programming visually (via ProcessingJS) through JavaScript. (Check out John Resig’s blog post about the platform). I believe that JavaScript was a great choice because of the low barrier to entry (all you need is a browser) and flexibility of the HTML5 API(Canvas, WebGL, WebSockets, Audio, Video, etc). Mike Bostock also wrote about Visualizing Algorithms which I thought may be interesting to incorporate as the curriculum moved towards more advanced topics.

Understanding the Platform

Abstract Car I built for KA CS Project: Public Transportation

Having narrowed down my focus to Khan Academy’s CS platform, I began playing around with Khan Academy’s programming environment to get a better understanding of how their lessons are structured. (I would also recommend reading John Resig’s Redefining the Introduction to Computer Science). The lessons are structured like a “video walkthrough”, but under the hood a code editor is synced with audio from SoundCloud. This is pretty awesome because it allows the viewer to pause the “video stream” and edit the code in place. Bret Victor also wrote a thoughtful critique, Learnable Programming, on Khan Academy’s platform which was an interesting read because his work was cited as inspiration for Khan Academy’s CS Platform.

The Concept

So I decided I was going to try applying directly for Khan Academy’s CS(Computer Science)Team. I think an important aspect of Computer Science education is providing context to the student. It may be difficult for individuals to be engaged with the curriculum if they are unable to relate to what they are learning. But if you can imbue an individual with a sense of wonder by showing them something that resonates with them, that curiosity will carry them through an adventurous path of learning (Take a look at these stories from MadeWithCode). I decided to build a slide deck featuring projects demonstrating polished usage of HTML5 technologies around the web (Audio, Web Sockets(Networking), Video, WebGL(Graphics) because these were the technologies I was interested in possibly expanding upon for the Khan Academy CS curriculum. I also built a small demo for visualizing Depth First Search, an algorithm for traversing trees, graphs, or similar structures(like mazes).

The projects I referenced were:
1. Keylight: an audio rhythm experiment by Hakim El Hattab
2. Chrome Racer: Mobile web experiment demoing web sockets and other technologies by Google, Active Theory, Giorgio Moroder, and Plan8
3. Aaronetrope: Interactive Video Zoetrope by Aaron Koblin and mrdoob
4. Hello Racer: Car Simulation in WebGL by Hello Enjoy

Lastly, I decided that I would tweet the link of my site directly to the developers on the CS Team as a casual introduction.

Design

Layout

http://vimeo.com/77925978

The layout for my slide deck was inspired by Michael Sevilla’s work on MyLifeIn20Years. Since my slide deck consisted only of one row of slides, I decided to build my deck with the perspective origin coming diagonally from right side of the viewport, so that the leading line would draw the viewer’s eye to the first visible slide. As the slide in front begins to go out of view it rotates to reveal the slide behind it. I also made the opacity of each slide inversely proportional to its distance from the viewer (similar to the visibility of objects as they are coming from dense fog or a dark tunnel).

Slide Deck Prototype
Slide Deck

Selecting Typography

I used Squarespace Logo as a starting point for selecting my typography. I wanted to use type that captured a friendly and playful ethos to echo a similar ethos on Khan Academy’s CS Platform. After experimenting around, I decided to strike a balance between playfulness and professionalism. I ended up pairing Londrina with Roboto Condensed .

Londrina Sketch / Sniglet , Londrina Solid / Sniglet , Luckiest Guy / Sniglet
Londrina Solid / Sniglet, Londrina Solid / Robot Condensed , Another Londrina Solid / Roboto Condensed

Typographic Art Sketches

I created some typographic art to introduce each project that I was featuring. Since many of these projects actually cover a breadth of technologies I wanted to make it clear what aspects I wanted to highlight from these projects. The work I produced literally spells out each letter and tries to capture the essence of each word. The idea for using geometric shapes to represent “GRAPHICS” was inspired by the two.js logo, and the idea for breaking down “VIDEO” into bits was inspired by Shape Shifter and this article about Interactive Typography in HTML5.

lower case concept for graphics (left) / Networking visualized with arrows to describe direction of motion(right)

Typographic Art Compositions

Aside from the video graphic (created/animated with HTML5 canvas), I created my visuals as vector graphics. I’m still quite a beginner working with SVGs. At the time I didn’t visually understand how to work with control points on bezier curves, so my rudimentary solution to fix this problem was to build more complex shapes by “playing” connect the dots, and then using simplify path to smoothen out the curves.
Who knew playing connect the dots in grade school could be so helpful? Not long after I released my project the bezier game was released by Method of Action. I would advise playing this game if it’s your first time working with bezier curves. I have since been able to sharpen my bezier skills.

Technical Implementation / Learning

The tools I used for implementation were Grunt (JavaScript task runner),a little bit of NodeJS(server-side JavaScript), Jade (templating language for NodeJS), RequireJS(JavaScript File and Module Loader), and SCSS(one of many CSS preprocessors). The application is written in Vanilla JavaScript, HTML5, and CSS3 and the full source is available here: https://github.com/radialglo/readyforkhanacademy.

Objectives

I wrote down some technical objectives I wanted achieve. These objectives can be summarized as building interfaces out of my comfort zone and preparing production ready code(create a scalable/maintainable architecture, ensure device compatibility, optimize performance, etc).

  1. Incorporate CSS3D
  2. Apply Motion/Animation and develop a better understanding of easings
  3. Make the Design Responsive
  4. Browser Compatibility
  5. Scalability
  6. Performance
  7. Have Fun

1. CSS3D

Learning CSS3D
David Desandro
wrote a great introduction to CSS3D transforms. If you’ve worked with OpenGL before, CSS3D behaves quite similarly with a few caveats.

Left Hand Rule and Positive Clockwise Rotation

Coordinate System for CSS3D Transforms

Physics and OpenGL use the right-hand rule and most coordinate systems adopt a right-hand oriented system. CSS3D uses the same rule applied with a left handed orientation. First, point your thumb outward in the positive direction of the the z-axis and orient your fingers parallel to the x-axis. Your palm should be facing in the positive direction of the y-axis. Finally, curling your fingers into your palm gives you the direction of positive rotation (clockwise). Although these conventions may appear odd at first they make sense because they are analogous to the top and bottom properties used for positioning elements in a website.

Matrix Concatenation and Order Matters

From the css3-transforms specification: If a list of transforms is provided, then the net effect is as if each transform had been specified separately in the order provided. For example,

<div style=”transform:translate(-10px,-20px) scale(2) rotate(45deg) translate(5px,10px)”/></div>

is functionally equivalent to:

<div style=”transform:translate(-10px,-20px)”>
<div style=”transform:scale(2)”>
<div style=”transform:rotate(45deg)”>
<div style=”transform:translate(5px,10px)”>
</div>
</div>
</div>
</div>

That is, in the absence of other styling that affects position and dimensions, a nested set of transforms is equivalent to a single list of transform functions, applied from the outside in(read from left to right). The resulting transform is the matrix multiplication of the list of transforms.

Transformation Order Matters(this image uses a right hand oriented system but is conceptually the same as CSS3D transforms)

Order matters, so rotating then transforming is not equivalent to translating then rotating. You can think of each matrix multiplication as a change in the coordinate system. So

transform: rotate(45deg) translate(10px, 10px);

rotates the coordinate system clockwise by 45 degrees and then translates 10px along the rotated y and x coordinate axes.
whereas

transform: translate(10px, 10px) rotate(45deg);

translates the coordinate system 10px along the x and y axes before rotating the object 45 degrees around the origin of the new coordinate system.

Here are a couple experiments I created based off what I learned.

Hello World — CSS3 Transformations

Checkout the Hello World source here: http://codepen.io/radialglo/pen/ydKki.

Left (My CSS3 Rendition of Matt Divito’s Light Cube) / Right (Matt Divitos’ Light Cube)

Check out the light cube source here: http://codepen.io/radialglo/pen/rnkhG.

Applying CSS3D
The main use of CSS3D for my project was translating each slide along the z-axis and modifying the perspective origin.

2. Motion/Animation

Learning About Easings

Before the introduction of HTML5 and smartphones, Flash was one of the primary technologies for developing rich interactive applications and animations on the web. Now there are HTML5 animation libraries like GSAP.

The animations I intended to create were relatively simple tweens, so I used CSS3 Transitions for my primary mode of animation. I heard of using bezier-curves to model the acceleration of CSS3 Transitions, but I didn’t understanding the nuances between different easings(models for acceleration).

Luckily I discovered Robert Penner’s Easing Functions! I first heard of Robert Penner when I was browsing the source for Matthew Wagerfield’s CSS3 Mixins, and learned Penner’s functions were very influential for animating programmatically. After further googling, I found that Robert Penner also provides a nice set of resources for learning about his easings functions.

For further reading on motion I would recommend the following resources:

  1. 12 Principles of Animation and related video explaining these principles The illusion of life
  2. Robert Penner Easing Resources
  3. Google Material Design(This is the visual language of Google presented at Google I/O 2014)
  4. Google Web Fundametals on Easing
  5. Motion and Animation, A new mobile UX Design Material

Watching Motion

http://vimeo.com/99876106

To get a better feel of motion, I also watched some film from motion designers.

Soldifying Understanding of Easings

I analyzed the motion of Flickr and Google Glass’ website.

To test the understanding of my knowledge I wrote a blog post(Understanding The Intution of Easing) where I describe in detail the mathematical relationships between all of Robert Penner’s Easings, explain how to select different kinds of easings, and analyze https://www.flickr.com/ and https://www.google.com/glass/start/ to explain how their easings were implemented and why their easings make sense.

Animating Khan Academy’s Logo

I applied Material Design Principles on Meaningful Transitions in animating the logo. I wanted to animate the hand tree growing, so my animation hierarchy starts at the root of the tree (the hand) and then animates the leaves radially row by row. Notice the circular motion of the leaves. I used a variation of easeOutBack easing to give the leaves a bounce.

Khan Academy Logo Animation
Linear motion: Maze (left), V I D E O(right)

Animated SVG

Xbox One SVG Animation

I first read about this technique from Jake Archibald’s post: Animated line drawing in SVG. On the left is an example of SVG animation from Polygon’s Xbox One Review. The core idea for svg animation is to to set the SVG path’s attributes stroke-dasharray and stroke-dashoffset, to the full length of the path. A path is broken into dashes. In its basic form, stroke-dasharray contains two values: the length of each dash and the length of the gap between each dash. Visually, this behavior is similar to the dashes you see on paper coupons. Stroke-dashoffset specifies the distance into the dash pattern to start the dash. So if you you set dash length, gap, and dash offset to the full length of the path, all you end up seeing is the gap because the offset skips the full length of the dash. Setting the dash offset to 0 brings the fulldash back into view. Finally adding a transition on the dash offset animates the dash being “drawing” out. The outline of the code works like this.

https://gist.github.com/radialglo/ad96cbc4b0dfc898a541

A small caveat of this technique is that you need to explicitly trigger a reflow/layout(recalculation of geometric properties) on the svg path. If you modify the same style twice in the same JavaScript execution without forcing a layout in between the two styles only the last one counts.

Start Screen

The start screen for my application combines the use of animated SVGs and easing.

Networking Animated SVG

If you were curious about arrows for the typographic sketch for Networking, they were used to describe the direction of the lines for the SVG Animation presented here.

3. Responsiveness

Media Queries

I adapted Zurb Foundation’s media queries for targeting responsiveness. Their framework provides a good set of breakpoints for targeting various screen sizes.

// Small screens @media only screen { } 
/* Define mobile styles */
@media only screen and (max-width: 40em) { }
/* max-width 640px, mobile-only styles, use when QAing mobile issues */
// Medium screens
@media only screen and (min-width: 40.063em) { } /* min-width 641px, medium screens */
// …
// …
// XXLarge screens
@media only screen and (min-width: 120.063em) { } /* min-width 1921px, xxlarge screens */

For convenience, I converted these media queries to a series of SCSS Mixins.

@mixin mq-small-only() { 
@media #{$small-only} {
@content;
}
}
// Sample usage
@include mq-small-only {
.aspect-ratio {
// make aspect ratio 1:1 for slides on smaller screens
padding-bottom: 100%;
}
}

Scalable Typography

To make my typography scalable, I scaled all my type relative to the root element (the html tag) using rem(root em).

To apply this technique, set the font-size of the root element to the browser’s default font-size by using 100% and then converting the desired pixel values to rem.

html {
font-size:100%; /* flexible baseline, approximately 16px*/
}
p {
font-size: 1.25rem; /* 1.25rem relative to a 16px baseline on the html will result in a 20px font size */
}

I used Zurb Foundation’s SCSS rem-calc mixin, so that I could still write my desired values in pixels and let SCSS do the heavy lifting. For further reading, I would recommend reading Sara Soueidan’s article Techniques for Responsive Typography.

Padding Hack and Maintaining Aspect Ratio

One of my challenges was maintaining the aspect ratio for the slides. The straight forward solution would be to programmatically update the dimensions of each slide whenever the window resizes, but I wasn’t content with the idea of doing in JavaScript or having the aspect ratio fail when JavaScript is disabled. Thierry Koblentz wrote a great article Creating Intrinsic Ratios for Video that describes maintaining aspect ratio through CSS.

The trick is that when padding (and margin) are set to percentages, the value is calculated with respect to the width of the containing block. So in order to maintain aspect ratio, you can create a wrapper around the element whose ratio you want to maintain that has a height of 0, a percentage based off the height-to-width ratio for padding-bottom, and a position of relative(For historical purposes, the reason why padding-bottom is specifically used over padding-top is because IE5 removes the “space” created via padding-top from the flow.) Then you change the element’s position to absolute, stretch it to the container by setting width and height to 100%, and set the top and left properties 0 to set it flush against the edges of the container.

<div class="wrapper-with-intrinsic-ratio>
<div class="element to stretch">
</div>
</div>
.wrapper-with-intrinsic-ratio {
position: relative;
padding-bottom: 20%; // this is height to width ratio
height: 0;
}

.element-to-stretch {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Media Queries in Action (left) / Slides on mobile have a 1:1 aspect (right)

Mobile Emulation
If you’re looking for a way test on multiple devices, an inexpensive way to test is to use mobile emulation, which is shipped with Chrome. This doesn’t beat out having a device lab, but is great nonetheless.

4. Browser Compatibility

I made the assumption that my target audience, the folks at Khan Academy, would be using a modern browser, but provided a fallback for WebGL, CSS3D-Transforms, and other modern features. To increase browser coverage, I opted for using feature detection over user-agent sniffing.

Feature Detection

Feature Detection is checking for the existence of specific methods or properties in a browser. You may have seen such techniques being used for cross-browser event registration:

function addEventListener(el, type, fn) {
if (el.addEventListener) {
el.addEventListener(type, fn, false);
} else if (el.attachEvent) {
el.attachEvent("on" + type, fn);
} else {
el["on" + type] = fn;
}
}

Modernizr is a great library that performs feature detection, stores boolean values for features in the Modernizr object, and also adds a class onto the html element with the name of the CSS property if it is supported or prefixes with “no” otherwise.

if (Modernizr.csstransforms3d) {
// Do Something
}
// SCSS
// Modernizr adds no-csstransform3d class to html element if CSS Transforms 3d is not supported
.no-csstransforms3d {
// slide deck should be a simple scrollable page
.slide {
position: relative;
@include transform(none !important);
opacity: 1 !important;
width: 100%;
padding: 1.25em;
@include box-shadow(none);
border-radius: none;
}
}

I also used this addWheelListener from Mozilla for cross-browser scrolling and some polyfills.

5. Scalability

My overall strategy for scaling up my HTML, CSS, and JavaScript was to be consistent and create by abstracting: start with a concrete case and gradually generalize, level by level, so that you fully understand the codebase at each level of abstraction.

HTML
I used Jade as my templating language and ExpressJS to serve static files during development. For production, I compiled the files down into a single index.html. The main index.jade includes a header, the start screen, slide-deck, and footer.

https://gist.github.com/radialglo/a8780cb3609733b90fe6

The slide-deck.jade includes each slide wrapped around the world/slide deck.

https://gist.github.com/radialglo/9a085b9e5eee91f1e877

In terms of markup for each slide, I created a generic slide.jade and used extends/block for template inheritance to create more specialized slides (slides for iframes, slides that are blue, etc).

CSS
This year a lot of people have writing about how CSS works at their organization. I would recommend taking a look at their posts: Github, Medium, Trello, CodePen, Groupon, Ghost, Lonely Planet.

My code base was influenced by elements of Zurb Foundation. I adapted their _functions.scss to use rem-calc(for creating scalable typography) and the export method(to ensure that certain modules don’t get included multiple times).

I created a base SCSS file that I imported to other SCSS files. The base file included things like cubic-bezier values for easing, media query mixins, typography, and utility functions. Then I created modules for the slide deck, slide themes, slide specific styles, and the start screen.

My main SCSS file imported all of these modules.

https://gist.github.com/radialglo/a8a4fbbc874ef0f35890

JavaScript

The organization of my JavaScript codebase was largely influenced by the organization of jQuery’s codebase: use AMD conventions (to group code into modules and resolve dependencies) and have a build task (to strip AMD scaffolding and compile the source into a single file). I wrote about these findings on my blog. There’s a npm package, amdclean, which also compiles AMD code into JavaScript.

I spent some time modeling generic slide objects for my slide deck.
I ended up creating these classes based off common functionality:

SlideView — static slideAnimSlideView — slides with animation that terminatesPersistentAnimSlideView — slides with an infinite animation loopIframeSlideView — slides that are loaded from external sources via iframesWebGLIframeSlideView — iframes that need feature detection for WebGL

Creating these abstractions helped me keep the code very terse. I was able to initialize slides with minimal code.

https://gist.github.com/radialglo/171bccbcaf2689cf9531

Structuring my codebase via AMD, my main file came out to less than 100 lines which solely handled the initialization of the slide deck. Altogether the compiled down source was around 1400 lines of code.

https://gist.github.com/radialglo/dd776175b15b49b09b4e

6. Performance

Serving of Github Pages/CDN

Github allows you to host static pages on their site(called github pages) by creating a gh-pages branch for your repository. Since my content is static I compiled my templates into a single into html file. Github also lets you configure custom apex domains and subdomains. However using custom subdomains over apex domains are more advantageous because subdomains give your site the benefit of github’s Content Delivery Network and also load faster because Denial of Service protection can be implemented more efficiently. I ended configuring both readyforkhanacademy.com(apex domain) and www.readyforkhacademy.com(subdomain) because github automatically redirects the apex domain to the subdomain.

Here are github-specific links for further reading:

About Custom Domains for Github Pages

Configuring a Subdomain With Your DNS Provider

Configuring an A Record With Your DNS Provider

Image Compression

I compressed my images in two passes. First I used TinyPNG to perform a lossy compression for my pngs and then ran the images through ImageOptim to perform lossless compression (compression without affecting quality).

JavaScript Debouncing
JavaScript Debouncing is the process of coalescing several temporally close signals into one signal. If we are ideally targeting 60 frames per second for rendering that means each frame you draw has roughly 16ms to get everything done. If you don’t do any management of user input events such as scrolling then many events that we’re interested in will get fired multiple times inside a single frame. This is bad because you will force the browser to do work that will never be seen by the user. For example, if there are three scroll events dispatched, then the visual work done for the first two is essentially wasted time. This extra work extends the life of the frame, effectively lowering the fps rate. Another important characteristic of events are that they are handled out of sync with the browser’s rendering pipeline. That means that developers should decouple the animation(rendering) from the handling of user inputs(events). To do this have an input handler store the latest state of parameters needed for animation, and perform animations only when an animation frame from the rendering pipeline is available. Here is sample code from this article: Leaner, Meaner, Faster Animations with requestAnimationFrame.

https://gist.github.com/radialglo/86849c9635a647145ec7

I applied the same technique to scrolling and keyboard input on my web application.

Simulating Play Pause

As we have discussed, frames must take up to 16ms to render to achieve 60fps and avoid a janky experience. That means that I could not let slides that are continuous(anything with an infinite animation loop) run concurrently, so I needed to simulate playing(when a slide is the first visible slide) and pausing. For code that was hosted on my own domain I could “play” via requestAnimationFrame and “pause” code via cancelAnimationFrame.

Since most of the projects I featured on my slide deck were embedded via cross-domain iframes I wasn’t able to directly manipulate their animation loops. To solve this problem I changed the iframe source to “about:blank” to simulate pausing and set the iframe back to original source when playing. I’d seen a similar technique for replaying demoes on Codepen.io. Since the request for the iframe is already cached by the browser this also avoids overloading cross-domain hosts with additional network requests. To account for the unpleasantness of having a blank page when a slide is paused or waiting for iframes to load, I gave these slides a poster(similar to posters you see for videos on Youtube or Vimeo).

HTML5 Web Workers
Web Workers help mitigate problems with JavaScript’s single threaded nature. I used web workers to process the image data for the VIDEO slide which I manipulated to create the oscillation effect on the text.

Efficient CSS / Minimizing Reflow

CSS Selector Performance has improved significantly over the years, but you should still be reasonable for your selectors. Additional if you are trying to improve CSS speed you should investigate the cost of reflows(layout) and repaints. Here are some strategies I used

  1. If you make complex rendering changes such as animations, do so out of the document flow. Use position-absolute or position-fixed to accomplish this. Each slide is positioned using position absolute. https://developers.google.com/speed/articles/reflow
  2. Favor CSS3 Transforms over animating top or left to make use of hardware acceleration.
  3. Aim for classes over everything else and avoid unnecessary nesting to improve reflow/repaint performance.

Optimizing Google Fonts

I used link instead of import for including my CSS files, so that my stylesheets would download in parallel.

The Google Fonts API also provides a batch method to load CSS fonts by specifying the font family with | as the delimiter.

So you can combine

<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans">
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Lobster">

into one request.

<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid +Sans|Lobster">

For further reading, I would highly recommend Google’s blog post on Optimizing use of the Google Font API.

7. Fun / Easter Eggs

Many organizations such as Khan Academy, Mozilla, and Soundcloud leave easter eggs in the browser development console as a fun invitation to apply to work for them (Checkout Mozilla’s ASCII art!). After poking around an ASCII generator I discovered that Khan Academy was using the Lean ASCII font. I wrote an easter egg with the same font and added a brief response to their easter egg questions. Adding the easter egg was a nice subtle touch to show that I was also peeking under their hood and curious about Khan Academy’s code worked.

Khan Academy and Mozilla Easter Egg
Soundcloud Easter Egg
Ready For Khan Academy Easter Eggg

Launch

I launched my site on September 11th, 2014 (The date was just a coincidence and I seriously considered pushing launch back another day).

Prelaunch on Codepen

I added links to and uploaded individual components of this site onto CodePen. That way visitors to my site could not only read its source code, but could also interact with it in a live environment.

While I was uploading the pens(project names on CodePen are called pens) I was humbled to learn that Chris Coyier had liked a couple of my pens.

To my surprise a few pens were also selected to be featured on the front page which was encouraging.

My work on the front page of Codepen.

Tweet

After adding links to the individual pens for my last slide and pushing out my last commit, I was finally ready to apply to Khan Academy. I submitted my application and tweeted to Khan Academy and the CS Team!

https://twitter.com/radialglo/status/510155353837674498

Conclusion

A couple days later I was invited to interview with Khan Academy and after a couple rounds of interviews I learned that I would not be moving forward

Yay! Growth Mindset!

with the interview process. Of course I was sad, but I didn’t let it affect me for too long.

The Takeaway

One of the core tenets of Khan Academy is the idea of growth mindset (Check out Khan Academy’s recent YouCanLearnAnything Campaign). Growth mindset, coined by Carol Dweck, a psychology professor at Stanford University , is the belief that capability and intelligence can be developed through effort, struggle and failure, while fixed mindset is the belief that our abilities are fixed traits (I would highly recommend reading Dweck’s book: Mindset). For some time researchers have shown that the brain is like a muscle. The more you use it, the more it grows.

A telling sign of one’s mindset is how they cope with failure. Do they take ownership for their own failures or do they impute blame on other people or things? Are they willing to embrace failure and learn from mistakes? Can they persists despite setbacks? Failure helps one develop grit and tenacity.

Another important aspect of growth mindset is being able to calibrate one’s current ability and circumstances. One shouldn’t let other people success define or limit themselves, but instead they should focus actively on improving themselves little by little everyday.

Practicing growth mindset has helped me learn a lot through the application process and helped me accept and learn from my rejection. Even if I did not get the position at Khan Academy, I can continue getting better as a developer and actively contribute to education by writing and sharing my knowledge.

If you are only going to remember one thing from this post remember growth mindset. Your abilities are in your control. Be a proactive learner, improve from failure, and strive for progress over perfection.

If you’re interested in hiring a front end developer or UI Engineer or want to say hello, you can reach me at anthonysu@radialglo.com or on Twitter: @radialglo.

If I’ve piqued your interest in working at Khan Academy, you should seriously consider applying.

Thanks!

--

--