The Enyo Blog

Oct 13

Update on Enyo Updates

It has been a while since we last posted, so we thought we’d drop in for a quick update.

We’ve been busy since the last official release of Enyo (Version 2.4, back in April, for those of you keeping track). Much of our focus has been on improving the new data layer, updating documentation, fixing bugs, and enhancing the Moonstone UI libary. We’re getting close to our next public release and we’ll provide more detail on each of these topics when the announcement goes out. In the meantime, feel free to check out the latest source from GitHub.

In parallel, we have also begun investigating what the next generation of Enyo will look like. We’ll have more to say about this, too, but for now, please start thinking about what you’d like to see in your next-gen framework, and drop us a line in the forums or on the mailing list to share your thoughts.

Aug 04


Our last post about the new hardware accelerated spinner, which has all of the benefits and none of the drawbacks, went over really well with our internal teams, but we kept getting the same question: “We really love the fluidity of this, but what if we want to animate something more complex than this just as smoothly?” Fear not! We’ve got that technique covered for you here, too.

This time, we’ll discuss how to hardware-accelerate a sprite animation, which in our case will have translucency. First, we should start by saying what a “sprite” is. A sprite is a sequential arrangement of individual cels or frames of animation combined into one image file, like if you took all of the frames of animation that make up a cartoon and laid them all out next to each other. In traditional animation, a cel (which makes up a single frame of animation) is drawn on a sheet of transparency paper (historically, celluloid) so the page doesn’t occlude the background behind it. A stack of cels, when viewed one at a time in rapid succession, creates the “animation”. This metaphor translates well to what we’ll be doing today with our sprite PNG image file, since it, too, will have translucency, which will allow it to overlay cleanly on top of our background. Unlike traditional animation, our frames will all live together on one large image file (a sprite sheet), instead of a separate image file for each frame. To simulate animation between them, we, in rapid succession, slide the sprite sheet past a sort of picture frame that hides everything outside of it, so that only one cel is visible at a time, much like a film strip moving through a movie projector. This sliding is what we can hardware-accelerate.

Getting Started

We’ll first need a sprite-sheet to animate.

Everyone likes explosions, right? Here’s one from this article on sprite explosions.

Sprite Sheet of EXPLOSIONS!

You’ll notice that this sheet has each of the frames laid out in a horizontal approach, each progressive frame lives to the right of its predecessor, until the edge of the image, when it wraps around to the next “line” or row. When we shift this image around using our animation’s keyframes, we’ll need to remember and account for this vertical shifting as well as the horizontal one. Each of our sprites measures 93 pixels wide by 100 pixels tall, for a total dimension of 930x400. We’ll also need these measurements in our calculations later.

CSS Keyframes

If we were just sliding an element (DIV tag) from point A to point B in a hardware accelerated way, it would look like the following (Note the usage of translateZ(), which tells the browser to render this as if it were a 3D transform, which will be hardware accelerated):

@keyframes slide {
    0%   { transform: translateZ(0) translateX(0); }
    100% { transform: translateZ(0) translateX(-930px); }

.move-me {
    animation: 2s slide infinite linear;

For sprite animation we really don’t want a smooth animation, we need a stepped animation, one that has several stop-points along the way, and jumps from one part to the next. For this, we can use the steps() animation timing function. This does just what we need, stepping the animation one section at a time, and if we put the number of frames per row into this function, it will do all our work for us, like this:

@keyframes slide {
    0%   { transform: translateZ(0) translateX(0); }
    100% { transform: translateZ(0) translateX(-930px); }

.move-me {
    animation: 2s slide infinite steps(10);

We would be practically done if we only had one row of frames, but we have four. We need to jump down to the start of the next line, quickly, then animate across, jump down to the next, etc. until we’re done. Putting two keyframe percentages which are almost the same in value next to each other causes a quick jump. Below is what we’d need for our four rows. It’s important to note that the steps() function only refers to the number of steps between any two keyframes, not the entire animation. So, in our case, that relates to the number of columns we have, not the total number of frames.

keyframes-tv slide {
    0%     { transform: translateZ(0) translateY(0) translateX(0); }
    25%    { transform: translateZ(0) translateY(0) translateX(-930px); }
    25.01% { transform: translateZ(0) translateY(-100px) translateX(0); }
    50%    { transform: translateZ(0) translateY(-100px) translateX(-930px); }
    50.01% { transform: translateZ(0) translateY(-200px) translateX(0); }
    75%    { transform: translateZ(0) translateY(-200px) translateX(-930px); }
    75.01% { transform: translateZ(0) translateY(-300px) translateX(0); }
    100%   { transform: translateZ(0) translateY(-300px) translateX(-930px); }

.move-me {
    animation: 2s slide infinite steps(10);

All of the positioning translate numbers we’ve been using up to now have been negative numbers. This is because our frames are typically laid out left-to-right, top-to-bottom; and since we measure from the top left corner, we must subtract each time we want our sheet to move left or up. Our goal is to get each frame’s top left corner to be in the top left corner of its containing element on every step of the animation, so the sprite sheet’s cels look like they are animating. We’ll also need to “clip” off the parts of the sprite sheet we don’t want to see at the moment. This is easier than it sounds: simply add a wrapper tag around your sprite-sheet tag, set its dimensions to the size of one frame, and set it to overflow: hidden. Here’s an example:

<div class="explosion frame">
    <div class="sprites"></div>

/* Pretend we're using the keyframes from the previous example */
.explosion {
    height: 100px;
    width: 93px;
    overflow: hidden;
.explosion .sprites {
    animation: 2s slide infinite steps(10);

Demo: And here’s an example of this in practice. Space ships added for dramatic effect.

Demo: See how it works in slow motion.

Enyo Sprites

In Enyo, we’ve made this much easier so you can focus on building cool stuff. We’ve added some helpers to more easily accomplish this for you. Most importantly, enyo.SpriteAnimation which lets you declare all of the necessary properties in one kind.

{kind: "enyo.SpriteAnimation", name: "sprite1", src: "", width: 320, height: 240, rows: 5, columns: 4, duration: 2000},

Demo: See the enyo.SpriteAnimation class in action

This kind also allows for additional properties like iterationCount, which lets you specify how many times this animation should run; cellOrientation, which lets you change the orientation of your sprite, in case it’s column-centric instead of row-centric; and offsetTop and offsetLeft, which lets you specify how far from the top left corner of the image your sprite range actually starts – this is useful if you have several different sprite animations in one image file.

To support enyo.SpriteAnimation, we’ve also added a new kind (enyo.Style) and a new mixin (enyo.StylesheetSupport), which you may find useful on their own.

StylesheetSupport Mixin

The new enyo.StylesheetSupport mixin can be applied to any UiComponent control and will dynamically generate and insert a side-car stylesheet that lives next to the control’s node in the DOM. It’s associated with the control, and can be updated at any time by appending-to, replacing, or deleting the contents of the stylesheet. The mixin adds a stylesheetContent property and an addStylesheetContent() method to your control. The stylesheetContent is primarily how you’d set and reset the CSS in the stylesheet, while the addStylesheetContent() method lets you append additional styles to the end of the stylesheet without replacing the existing styles in it.

For some context, here’s how it’s used in the SpriteAnimation kind:

components: [
    {kind: "enyo.Image", name: "spriteImage", mixins: ["enyo.StylesheetSupport"], sizing: "cover", styles: "background-size: initial;"}
updateKeyframes: function() {
    this.$.spriteImage.set("stylesheetContent", this._generateKeyframes());
_generateKeyframes: function() {
    return 'some really cool CSS returned as a string';

Style Kind

Our last new addition is enyo.Style, which is much simpler than the last two. Its job is just to accept CSS stylesheet code and render it into a <style> tag, wrapping the content with proper HTML comments. Simple, but something you may find useful.

We’re reviewing the enyo.Style kind for elaboration, too; adding new functions like insertRule and deleteRule with a supplied index so you can have a much finer grained control over your dynamic stylesheets. What do you think? Is this an awesome feature, something you’d use, something that’s utterly useless? What could you come up with to take advantage of it?

We’re looking forward to seeing what sorts of cool stuff you can come up with to build. Feel free to drop us a line via twitter @EnyoJS or in the comments to show off your creations! We love seeing your hard work (and ours) come to life!

Jun 13

What’s Spinnin’?

What do you do if you need to tell someone that you’re busy? In the web world, we’ve determined that an indeterminate radial progress indicator is the way to go. What is an “indeterminate radial progress indicator” you ask? Just a fancy way to say “spinner”. You know, one of those little animated spinning things. It lets the user know that 1. we’re busy, 2. we would like for them to wait patiently, 3. we don’t know exactly how long they’ll have to wait.

While developing our Moonstone UI library, we naturally needed to create one of these spinners. This post describes our implementation and what we learned in the process, which we thought might be useful to you as well.

So, let’s get to it!


We have an amazing user interface team that produces interaction and visual designs for all of our controls. They came up with a great design for our spinner, but its requirements presented some interesting implementation challenges. The requirements were as follows:


Often times, you’ll see implementations of this using an Animated GIF since it’s quick to load, easy to build, universally supported and highly customizable when you’re designing it. The downsides are that you only get one-bit worth of transparency (the image is either completely opaque or it’s not, no partial transparency), which means it’s harder to overlay it on top of any random thing and have it “just look nice”; you have a limited color palette to work with, since GIFs only get to use a maximum of 256 colors for each frame; their size and load-time can start to become a problem if you want a very smooth animation or have many frames, since each frame is its own rasterized image, they can add up quickly; and once the CPU gets really busy, GIF animations are temporarily halted, which completely negates their purpose for our needs. We need animation while the CPU is busy.

Example moon.Spinner Animated GIF:

GIF Spinner

Alternatively, you’ll see this implemented as a series of PNG images all globbed together in one image file, like a film-strip, which is then shifted around in rapid succession, jumping from one cell to the next, in a frame just large enough for one of the cells to be visible, to create an animation. This is called a sprite image, and sprite animation. This technique does solve some of the problems of animated GIFs, like true translucency (8-bits), and an expanded full 24-bit color, which when combined, create a 32-bit translucent PNG; and sometimes, we can even compress this down to be a little smaller than an animated GIF. But typically, this animation, stepping through the coordinates of each frame, is handled by JavaScript (we’ll discuss alternate methods in a later post). So what’s the problem? Isn’t JavaScript just always running? Well, this is where it gets a little more technical. Sure, JavaScript is (almost) always available, but JavaScript runs on a single thread, a single channel of instructions, one after the other. If something is filling up the pipe, other things can’t just pass it, since there is no fast-lane, just one lane. So if we have an animation that requires some new instructions every 100 milliseconds, like to jump to the next cell, and the CPU is busy, it’s not going to be able to process our animation instructions until it’s unburdened again. The visual effect of this is that our beautiful animation stops, just when we need it the most. This doesn’t suit our needs either.

An Example Sprite Sheet:

Sprite Sheet

After we had implemented both of the previous solutions, we still weren’t satisfied since that last requirement wasn’t met. And after some discussions with our WebKit engineering team, and some brainstorming, we came up with a method that would give us everything we needed and more.

The Solution

What if we could reconstruct the animation that the UI team came up with, using only DOM elements (plain, simple HTML tags), then animate it using CSS keyframe animations, and pass that animation off to the GPU (a separate processing thread that works really fast). We set off to do just that. Based on the level of complexity of the animation, we determined that our animation could be reconstructed using 4 DOM nodes (DIV tags): an outer DIV and 3 DIVs inside it.

First, we break down the animation that the UI team came up with. It’s composed of 61 frames for the complete loop. The keyframe mechanism supports 0% -> 100%, keyframes tied to percentages of the animation; so we’ll have to convert each keyframe to its relative percentage to most accurately reconstruct the animation. We’ll need to take each animation frame number, and divide it by the total number of frames (61). If you want to avoid thinking at all, drop it into a spreadsheet: set the rows from 1-61 in column A, then in column B, set it to column A/61 and “fill down”. You’ll get a little cheat-sheet of frame-numbers to keyframe percentages.

Our spreadsheet, with frame-numbers in the left column and keyframe percentages in the right:

Example Spreadsheet

Now that we have our cheat-sheet, we can pick out the significant parts of the animation, for a single ball’s complete journey through the animation. Since each ball does the same thing, we can apply the same animation to each one of them, offset by 0, 1/3 and 2/3 respectively. I say “significant”, because we don’t have to keyframe every frame, just the ones where the ball changes direction or speed, because we can let the browser tween everything else. In our animation, the keyframes will be, in order:

There’s one last step before we can start writing this as CSS. Since our positioning will be determined by rotating each ball from the center of our container, we must determine the angle that the center of the ball is at, relative to the center of the main container, at each of these keyframes. I just eyeballed it, but you could take the slightly more accurate approach and hold a protractor up to the screen and do some rough measurements.

Angle Measurements

Here’s the result: (written using LESS)

// The width of our ball, in position, measured in degrees.
@moon-spinner-ball-angle: 17deg;

@-webkit-keyframes spinBall {
    0%        { -webkit-transform: rotateZ(@moon-spinner-ball-angle); }
    /* Slow down toward the top */
    15%       { -webkit-transform: rotateZ(160deg); }
    25%       { -webkit-transform: rotateZ(200deg); }
    /* Speed back up as the ball falls */
    30%       { -webkit-transform: rotateZ(225deg); }
    /* Impact at last ball */
    33%       { -webkit-transform: rotateZ(360 - (@moon-spinner-ball-angle * 3)); }
    39%, 67%  { -webkit-transform: rotateZ(360 - @moon-spinner-ball-angle); }
    /* Small bounce forward */
    72%       { -webkit-transform: rotateZ(360 + @moon-spinner-ball-angle + 10); }
    79%, 100% { -webkit-transform: rotateZ(360 + @moon-spinner-ball-angle); }

And here’s our HTML

<div class="moon-spinner">
    <div class="moon-spinner-ball moon-spinner-ball1"></div>
    <div class="moon-spinner-ball moon-spinner-ball2"></div>
    <div class="moon-spinner-ball moon-spinner-ball3"></div>

The rest of the CSS

If we only needed the above, we’d be all set, but we need some additional CSS to do the following: tell each ball how far from the center of the container it is; specify the width of the ball in degrees, with respect to how far away it is from the center (so each ball doesn’t overlap the next); define the size, shape, and color of each ball; and style our container.

I’ve defined some variables to make the later calculations easier. Here are the five we are working with:


@moon-spinner-time: 1.83s;
@moon-spinner-ball-height: 15%;
@moon-spinner-ball-width: @moon-spinner-ball-height;
@moon-spinner-ball-distance: 20%;
@moon-spinner-ball-angle: 15deg;

You’ll notice everything is measured in percentages; that way, everything is proportional so the spinner can be whatever size it needs to be with no extra CSS. The end result can have its size set via pixels, character height, inches, etc, and it will keep lookin’ good.

Ball CSS

The ball sizing and positioning is a little trickier, because it does the math to make these variables meaningful.

.moon-spinner .moon-spinner-ball {
    position: absolute;
    text-align: center;
    font-size: 80%;
    border-radius: 50%;
    line-height: 0.4em;
    height: @moon-spinner-ball-height;
    width: @moon-spinner-ball-width;
    left: (50% - (@moon-spinner-ball-width / 2));
    bottom: (50% - @moon-spinner-ball-height - @moon-spinner-ball-disatance);
    -webkit-animation: spinBall @moon-spinner-time linear infinite;
    -webkit-transform-origin: center ((@moon-spinner-ball-disatance / @moon-spinner-ball-height) * -100);

The Demo

Enough talk, you say? Let’s see where we ended up. We’ve produced two fiddles that demonstrate the final result: one containing the raw HTML / CSS implementation, and another demonstrating the use of the finished Moonstone widget.

First, the raw HTML and CSS:

This fiddle includes 4 versions of the spinner: standard, with no background, with descriptive text, and a special bonus huge spinner. Feel free to fiddle with the fiddle and explore some of the capabilities or add your own!

For some extra fun, try uncommenting some of the commented lines in the fiddle to explore the alternate variations. To get a better idea of what each of the ball animations look like individually, try removing balls 2 and 3.

And now, the Moonstone sample:

As this fiddle demonstrates, you can add a spinner to any Moonstone app by using the moon.Spinner component, like so: {kind: "moon.Spinner"}, or {kind: "moon.Spinner": content: "Loading..."} for a spinner with an integrated label.

That’s it — we hope you enjoyed the spin! Let us know if you have questions, comments, suggestions, or if you want to share your own “indeterminate radial progress indicator” war stories.

Apr 14

Enyo 2.4 General Availability

In February, we pulled the covers off of a huge body of work the Enyo team has been building out over the past year in our Enyo 2.4 preview announcement.  This included a new data layer with two-way bindings, models, collections, sources, and data-aware controls, allowing for fully declarative model-driven views.  The other exciting announcement was around our new TV offerings: a new UI library called Moonstone designed by the vaunted webOS User Experience team specifically for developing immersive lean-back TV experiences, as well as a focus manager called Spotlight, which takes the headache out of developing TV apps that need remote-control based 5-way navigation.

Today, we’re announcing that Enyo 2.4 is now officially released for general availability.  We’ve completed our cross-platform testing of all of the standard Enyo libraries (core, Onyx, layout, etc.) across our Tier 1 platform matrix, which we recently updated to address new devices and platforms released since Enyo 2.2.  For now, the Moonstone library is officially supported only for the LG webOS TV, but we plan to ramp up cross-TV testing of Moonstone, so stay tuned for announcements about expanded TV support in the future.

Two great references for getting started with Enyo 2.4 are a new set of documentation for the data layer, as well as a new tutorial that takes you from soup-to-nuts through developing a data-driven application using the new Moonstone UI library.

For a full set of changes, see the Enyo 2.4 release notes, or head to the download page to grab the code and get started.

Apr 03

Releasing Mochi

Back in January, The Verge published a story called The Lost Secrets of webOS, which lifted the veil on some forward-thinking webOS hardware and software products that unfortunately never saw the light of day. Featured prominently in that article was Mochi, a striking new design language that the webOS UX team had been working on for the next generation of webOS phones and tablets before everything abruptly and famously screeched to a halt.

In the transitional period before we were acquired by LG, our designers continued to work on Mochi. We worked closely with them, implementing many of the Mochi widgets in the form of a new UI library for Enyo 2 — but we had to put this work in progress on the shelf in early 2013 when we shifted our focus to TV and started pouring most of our energy into Moonstone and Spotlight.

When the Verge story hit, however, it understandably sparked some interest in Mochi. While we don’t have any immediate plans to resume our Mochi work, we would be thrilled to see the community pick up where we left off. With that in mind, we showed Mochi off in an online hangout session in January, and since then — in our copious spare time — we’ve been working toward a public release. This work has included lining up community members to act as maintainers, fixing font licensing issues, and gathering up the internal design documents that would let our community developers understand the ideas behind the UI and see what’s yet to be implemented from the original vision.

Today, we’re pleased to announce that Mochi is now open source and available under the Apache 2.0 license, just like the rest of the Enyo source. The Mochi GitHub repo is now public, and we’ve started putting up some documentation in the Mochi wiki. Of particular note is our list of design documents which includes the PDFs and PNGs that were developed internally to guide Mochi’s development. Not only can this guide future work, but it shows just how much thought went into how these widgets work together. It also points to features that are yet to be implemented.

As maintainers for Mochi, we have two members of the webOS Ports community: Herman van Hazendonk (Herrie82) and Tom King (ka6sox). They will be handling reviewing pull requests and maintaining the code, with the Enyo team at LG providing guidance. Thanks, Herman and Tom, for stepping up!

It’s fun to have Mochi out in the open after all this time. Give it a spin, let us know what you think, and — if you’re so inclined — work with Herman and Tom to move it forward.

Apr 02

Enyo meetup

Continuing our renewed outreach to the Enyo community the Developer Relations and the Enyo teams hosted our inaugural Enyo JS meetup at LG’s-Silicon Valley Lab in Santa Clara on wednesday night.

With LG’s new webOS TV’s (powered by Moonstone, Enyo’s new “made for TV” UI) released, this was a great opportunity for the core engineering to share with the community the hard work that has been done and discuss the road ahead.

We had a good turn out of both experienced Enyo developers and novices, making for a fun and lively exchange of Q&A’s. Some of which came from our youngest attendee who at 13 had some great questions and made the Enyo team earn their pizza! It was great to see some new faces and we hope to continue growing the community as we do more of these meetups in the coming months,

If there are any topics you would like to go over, or any questions, send us a message to .  We are also thinking about hosting a meetup in the San Francisco area or in other cities.  Give a shout out and gather a crowd and let’s get another one going in a city near you!

See you soon!

Mar 18

Bay Area Enyo JS Meetup on March 26th

If you’re in the SF Bay Area, you’re invited to a in-person meetup for Enyo developers featuring many of the engineers at LG Electronics who work on the framework and support it with the development community. It’s at the LG Silicon Valley Lab office near Great America in Santa Clara, California starting at 5:30PM on Wednesday, March 26th.

Pizza and drinks are provided, and there should be some nice show-and-tell of the work that we’ve been doing over the last year.

Details and RSVP at

Mar 06

Guest Post: Greenius Web App - Enyo and Clojure Stack integration

From time to time we come across an app built with Enyo that piques our interest. When we heard about Greenius and read a little bit about how it was put together we definitely wanted to know more. We reached out to the team at Greenius and asked if they could talk a little more about how they used Enyo with their back-end systems. They are very enthusiastic about Enyo and Greenius’ Aseir Galdos happily prepared this guest post. Take it away, Aseir:

Greenius is a smart platform that brings together people who love growing their food in their gardens, farms or balconies.

More and more people are getting into fresh and local food (farm to table movement, organic farming, slow food) for health and ethical reasons, and many of them grow their own food. These tech-savvy and connected gardeners want to learn more or share their experience about the passionate process of growing their own food. Greenius gives them an easy, fast and cool platform to connect to other gardeners and farmers.


The underlying technology we use for Greenius is built with Enyo and Pure on the client side and the “Clojure Stack” on the server side: Clojure language, Ring and Compojure libraries, and the time-based immutable Datomic database.

Enyo offers us a cross-platform, extensible, lightweight and fast JavaScript framework, and with Clojure we can leverage the benefits of functional, dynamic programming and data immutability, as well as Java’s robust runtime and libraries (it is hosted on the JVM). 

So, how is all this technology wired?

Communication is an exchange of pure data structures between both sides, client and server, using JSON format. In Enyo we submit web requests using the Ajax wrapper; in Clojure we use Ring for request and response plumbing and Compojure for routing.

In Greenius, gardeners can follow and be followed by other users, as in a social network. Let’s dive into the client/server communication paradigm with the example of the “Follow” function:


First, we create a Kind (i.e.: onyx.Button) that ‘ontap’ triggers the Ajax call to the server:

 new enyo.Ajax({
            url: '/api/follow',
            method: 'PUT',
            contentType: 'application/json',
            cacheBust: false,
            postBody: {
                action: action,
                user: “Mike”,
                followee: “Sarah”

On the server, we have composed hierarchies of routes with Compojure, one of them being ‘/api/follow’, so now we can handle it as follows:

(defroutes api-routes
 (PUT "/api/follow" {:keys [params db conn]}
    (follow params db conn)))

Ring represents the request as the following Clojure map:

{:keys [{"followee" "Sarah", "user" "Mike", "action" "follow"} datomic.db.Db@2066c0a4 #<Connection {:db-id "greenius-29bc7792-ccdf-4597-abf5-85d91d54b58d", :unsent-updates-queue 0, :pending-txes 0, :next-t 1931, :basis-t 1930, :index-rev 0}>]}

- “params” represents the postBody of the enyo Ajax call

- “db” represents the Datomic database

- “conn” represents a specific Datomic database connection

Then, we process the Follow action with a private function and we return a Ring response with a given body (in this case a boolean) and no headers to the client, so that Enyo can handle this response.

(defn- follow
  [{:strs [action user followee]} db conn]
  (if (= action "follow")
    (response (success (social/follow-user db conn user followee)))
    (response (success (social/unfollow-user db conn user followee)))))

And this is the gist of it. No added complexity, just pure data structure exchange.

It has been and is being truly exciting to build Greenius with this technology stack, as we can achieve the scalability, flexibility and simplicity we need to minimize risks and maximize results. It has allowed us to focus on the core business problems and -we hope!- build a useful and elegant Web App that will foster the green lifestyle for present and future generations.


Feb 25

Enyo at Apps World Hackathon

A few weeks ago, we unveiled the upcoming Enyo 2.4 release and the new Moonstone and Spotlight libraries, setting the stage for developers to create next-generation apps for smart TVs.

The backdrop for our announcement was the Apps World conference at Moscone Center in San Francisco. We had a full contingent in attendance to meet developers and spread the word about Enyo. We had a booth on the exhibition floor, gave a talk and joined in on a great panel discussion — but undoubtedly one of the highlights of our Apps World experience was our participation in the two-day hackathon.


Kevin Schaaf, one of the leaders of the Enyo team, kicked off the event by introducing Enyo, Moonstone and Spotlight. During the event Enyo and DevRel engineers were on hand to answer questions and help the teams.


The response was amazing! In total there were 5 projects featuring Moonstone presented to the judges at the end of the event. After conferring, the judges unanimously agreed that Learn TV, one of the Moonstone projects, was the winner. Learn TV is a brilliant concept requiring adolescent viewers to earn “credit” before gaining access to TV content. Credit is earned by completing academic exercises within the app. The app also looked beautiful, showcasing the strength of Moonstone’s elegant UI and design patterns.

As well as taking the hackathon’s top prize, LearnTV also won Enyo’s sponsor prize and will be able to view their app on one of the first LG webOS TV’s to roll off the production line.

Also collecting Enyo prizes for their Moonstone apps were mobiTV who won an LG GPad for their parental Monitor and notification app and BetTV who picked up an LG G2 for their social betting app.

Congratulations to Learn TV and everyone that took part! We look forward to seeing the completed apps on our TVs in the future.


A lot of hard work went into developing Moonstone and the Enyo team really enjoyed mingling with developers and seeing first hand the fruits of their labor. Stay tuned for more events; we’re working on putting together an Enyo meetup for the near future.

Feb 05

Introducing Moonstone, Spotlight and Enyo 2.4

It has been an exciting few months for the Enyo team. First, late last year, we broke a long silence with the public release of Enyo 2.3.0-pre.10. Then, in January we celebrated the unveiling of the webOS-powered 2014 LG Smart TV at CES. Today, we’re thrilled to finally give everyone a closer look at what we’ve been working on for the last year.



In conjunction with the rebirth of webOS as a platform for smart TV, we’ve built Moonstone: an innovative, beautiful, full-featured UI library for building TV apps. Moonstone features a comprehensive set of UI widgets optimized for TV and a fresh take on the panel-based navigation that has been a hallmark of Enyo since Enyo 1. Moonstone panels support two distinct user interaction patterns — an “always viewing” pattern for lean-back experiences, and an “activity” pattern for more active engagement with an app. Moonstone comes out of the box with light and dark themes and is easily customized to make your app stand out. It also has robust support for internationalization, including widgets that work in both left-to-right and right-to-left contexts.


To go along with Moonstone, we’ve developed Spotlight, a library enabling apps to support key-based navigation — a must for TV, where users often have nothing more than simple up-down-left-right controls. Spotlight uses a nearest-neighbor algorithm to automatically determine where to move focus each time the user presses a key, minimizing developer effort. That said, it’s fully customizable, giving you fine-grained control over how users interact with your app. Spotlight switches seamlessly between pointer-based and key-based navigation, ensuring that users have the best possible experience on devices that support both modes. Spotlight support is baked into Moonstone widgets, but Spotlight has been designed to work with any Enyo UI library.

Cross-Platform and Open-Source

Moonstone and Spotlight will of course power the core apps for the next generation of LG Smart TVs and be the centerpiece of the forthcoming webOS TV SDK — but they’re not just for LG or webOS. In keeping with our deep commitment to supporting cross-platform development, Moonstone and Spotlight are open-source and available for use on any platform.

With CES behind us, today we’ve made the GitHub repositories for Moonstone and Spotlight public. Continuing work on Moonstone and Spotlight will be done in full view, just as it is for Enyo and its other libraries. We’ve not yet had a chance to do extensive testing or optimization on non-webOS platforms, but we’ve been developing with cross-platform support in mind and are excited to see Moonstone apps running on all types of big screens.

Enyo 2.4

In addition to flipping the GitHub repos public, we’ve prepared another pre-release (version 2.4.0-pre.1) of Enyo and its libraries so that you can easily explore docs and samples on the Enyo site. We’ve also updated our Bootplate starter kit and created a Moonstone-specific version of it, so you can grab a mobile-centric or a TV-centric Enyo distribution directly from the site if you’re so inclined.

While Moonstone and Spotlight are certainly highlights of Enyo 2.4, you may be just as interested in the robust new data-layer support you’ll find in this release. Enyo 2.4 has support for observers, one- and two-way bindings, computed properties, models and collections, and a set of new data-aware UI controls.

Astute observers will note that we’ve skipped straight from a 2.3 pre-release to a 2.4 pre-release. Moonstone, Spotlight and the new data-layer support will technically debut in Enyo 2.3, which is in its final release-candidate stage as we speak — but the schedule for Enyo 2.3 is tightly bound to the release and production schedule for the LG webOS TV and therefore has a life of its own. As we continue to shepherd Enyo 2.3 through this process, we’ve decided to move forward with Enyo 2.4 and make that release our primary focus for the cross-platform Enyo community.

We hope you’ll be as excited as we are about Enyo 2.4, Moonstone and Spotlight, and we’re eager to get your feedback. Here are some quick links for exploring what’s new:

If you’re in the San Francisco area today or tomorrow, be sure to stop by Apps World at Moscone Center West and say hello. You’ll find us alongside our webOS colleagues in the LG booth.