Pete Corey Writing Work Contact

My Meteor Hello World - countwith.me

Written by Pete Corey on Dec 8, 2014.

I decided to make a very simple webapp to get my feet wet with the Meteor framework. The result is countwith.me! The site is basically just a real-time, anonymous counter. Users can submit the next number in the sequence. If their number is incorrect, the count resets to 1. Even though it’s a mind-numbingly simple app, I learned quite a bit from it.

Using Grunt

My first instinct when building out a front-end for a project is to use Grunt and Bower. In order to prevent Meteor from trying to process and bundle all of my Grunt and Bower resources and dependencies, I decided to keep them in a hidden directory called .grunt, which Meteor ignores. Gruntfile.js is set up to watch scss for SASS changes, and then dump the compiled css file in the root directory. I have a grunt copy target set up to manually copy select resources (lodash.min.js, moment.min.js) out of .grunt/bower_components into js. Meteor finds these css and js resources and bundles them.

From what I’ve seen, using Grunt and Bower in this way isn’t the “Meteor way” of doing things. Instead, I should be using meteor packaged versions of the tools I need, like meteor-scss, meteor-lodash and meteor-moment. I’m not sure how I feel about this. I keep see the benefits of using things that only exist within the Meteor ecosystem, but at this point it seems like we’re just adding an extra, unnecessary layer of package management.

Subscription onReady

One of the first things I did was set up a template to iterate over a Counts collection and display the number in a span:

<template name="numbers">
    {{#each counts}}
        <span class="number {{#if wrong}}wrong{{/if}}">{{number}}</span>
    {{/each}}
</template>

As the collection began to grow, I was surprised to see that the data in the DOM would be initially incorrect when the app first started or was refreshed. A quick search led me to a StackOverflow answer that suggested not displaying data until the subscription onReady callback is called. A quick check of the docs made it pretty clear how the onReady callback works. By setting a session variable when the subscription was ready, I was able to hide the collection’s DOM elements until they were ready to be seen:

<section class="numbers {{#if notReady}}not-ready{{/if}}">
    <span class="number" contenteditable>???</span>
    {{> numbers}}
</section>

Publish/Subscribe and MiniMongo - Ohhhh, Now I Get It

As my Counts collection grew in size, I was beginning to have some severe performance problems. I spent several hours slamming my head against the Chrome Dev Tools trying to track down what I thought was some kind of memory leak. If only I had ready the Understanding Meteor Publications & Subscriptions article, I would be 3 hours richer.

Initially, I was using auto-publishing and setting up my sorting and limiting Counts query on the client:

if (Meteor.isClient()) {
    ...
    counts: function() {
        return Counts.find({}, {sort: {timestamp: -1}, limit: 30});
    },

After removing autopublish, I wanted to move that logic to the server, so I did just that:

if (Meteor.isClient()) {
    ...
    counts: function() {
        return Counts.find();
    },
...
if (Meteor.isServer()) {
    Meteor.publish('counts', function () {
        return Counts.find({}, {sort: {timestamp: -1}, limit: 30});
    });

However, after my client refreshed itself, I noticed that my data was not being updated when I submitted new numbers. I was under the impression that this server-side Counts query was not returning a reactive collection to the client. In a desperate attempt to fix the problem I removed the sorting and limiting from the server and moved them to the client. This worked, and I went about my business, oblivious to my impending doom.

if (Meteor.isClient()) {
    ...
    counts: function() {
        return Counts.find({}, {sort: {timestamp: -1}, limit: 30});
    },
...
if (Meteor.isServer()) {
    Meteor.publish('counts', function () {
        return Counts.find();
    });

Hours later, after reading through the previously linked Understanding Meteor article, I realized the errors of my ways. I also realized that the data being passed to the client was reactive, it simply didn’t look like it was updating because the default sort order was placing the new counts at the bottom of the list, out of sight. The ultimate fix was to sort and limit on the server, and sort on the client.

if (Meteor.isClient()) {
    ...
    counts: function() {
            return Counts.find({}, {sort: {timestamp: -1}});
        },
...
if (Meteor.isServer()) {
    Meteor.publish('counts', function () {
        return Counts.find({}, {sort: {timestamp: -1}, limit: 30});
    });

Conclusion

Check out countwith.me. Also check out its github repo. Ultimately, I’m very happy with how the project turned out. I never thought that such an incredibly simple webapp would teach me so much about a framework. Every little thing I learned about the framework gave me glimpses into much deeper topics that I’m anxious to explore. It’s interesting how such a seemsly simple framework can be so deeply nuanced.

Meteor First Impressions

Written by Pete Corey on Dec 2, 2014.

Recently I’ve been trying out the Meteor platform. Needless to say, I’m pretty pumped about it:

But seriously, from what I’ve read and experienced so far, I’m very excited about what Meteor has to offer. Going through the tutorial and seeing realtime data binding happening from the HTML template all the way up to the database is mind-blowing! In a previous post I wrote about my love for Firebase and my dreams for a realtime system architecture. Meteor seems like an amazing step in that direction. I’m looking forward to doing a lot more work with it in the near future!

Thinking Out Loud About Screencasting Platforms

Written by Pete Corey on Nov 21, 2014.

One of my goals over the past few months has been to start live streaming/screencasting my development sessions. I’ve been watching Izac Filmalter’s Twitch stream for the past few days and I think it’s fantastic! Streaming can benefit both the streamer (me) and the community at large (you). Developing to an audience would force me to polish not only the products I create, but also the process I go through to create them. Explaining what I’m doing to you would reinforce my understanding of the topic, and hopefully provide you with some value as well. Plus, in a pinch I can use you as a rubber ducky.

Current Options

There are a few existing options when it comes to streaming services and platforms, but all of them have their drawbacks.

  • On Air Hangouts - Google’s On Air Hangouts are essentially hangout sessions that you can broadcast to any number of viewers for free. Unfortunately, On Air stream quality maxes out at 720p.

  • Twitch.tv - Twitch.tv is a video game streaming platform with a fantastic community. Twitch supports source resolution streaming, but requires that you stream your content directly to their RTMP servers, which can be a barrier to entry. Their terms of use also state that only video game related streaming is allowed. If it weren’t for this policy, I would say that twitch is currently the best streaming option available.

  • Youtube Live - Youtube Live is the best alternative to Twitch. They support up to 1080p streaming, but like Twitch, they require that you manually stream your content directly to their RTMP server.

While configuring OBS or FMLE to stream to Twitch or Youtube Live’s RTMP ingestion servers is relatively straightforward, it’s an unneeded barrier to entry when technologies like WebRTC exist.

So, what’s a developer to do when he wants to screencast differently?

BYOPWWRTC (Build Your Own Platform With WebRTC)

WebRTC is a newly emerging browser technology that (among a huge number of other things) allows for the capture and streaming of video and audio directly within the browser. Since WebRTC works directly within the browser, no external streaming software is required. WebRTC can set up to peer-to-peer streaming directly to a small number of viewers, or the stream can be routed through a centralized server (MCU) to be broadcast to a wider audience. Building a screencasting platform on WebRTC seems like an obvious choice. We get the ease of use of browser based streaming, up to 1080p quality, and the possibilities of both peer-to-peer and centralized architectures.

Imagining the finalized product, peer-to-peer streaming would always be free as it puts no load on the system (other than page views). Depending on your machine/network capabilities, you will have a limited number of viewers to whom you can effectively peer-to-peer stream. After that limit is reached, the system would suggest you start using a centralized streaming model. This may need to be a paid service to support the MCU infrastructure.

Since this would be a platform targeted towards developers, I can imagine a variety of cool features like Github/Bitbucket integration, similar screencaster discovery (based on stack, framework, language, project, etc…), in-chat syntax highlighting, and many others.

Inspiring Resources

Final Thoughts

At the moment this is nothing more than an idea. I am by no means a WebRTC expert. I’ve only recent started researching this topic, but WebRTC seems like an ideal solution for this problem. In the very near future, I will hopefully start building out a proof of concept of the peer-to-peer streaming system. Once that’s up and running I would be able to stream the continued developement of the project. Stay tuned!