angr

writings from zac anger, who is not all that angry

Notes from the AngularJS Utah Meetup

April 24, 2016 — Zac Anger

So what with my last computer dying, getting a new phone, trying to find a job, preparing to maybe move, and all the other nonsense going on, I haven't really blogged at all lately. Oh well.

My to-do list is gigantic, like a whole huge directory tree of several gigabytes full of unfinished stuff.

Somewhere in there, there's rewriting my entire website.

I've just switched from GoDaddy's hosting to my own VPS (a droplet), since GoDaddy's cost was going up by about 110%. This means I have a LOT more available to me, now. Not quite as much space, but I can run whatever I need to on my server now, so... I think it's time to finally update everything. I plan on leaving most things as just plain old static sites (because, let's be honest, no one cares how flashy this crap is if it takes a year to render it on an old phone). The blog might change a bit, though. I'm still using that same old script (based originally on BashBlog, heavily modified over the past almost-year). Nothing against that script, it does its job and everything, but a 1300-line shell script to basically turn Markdown into HTML is absurd -- ESPECIALLY since it doesn't include the parser.

Anyway, here are some notes from the NG-JS meetup a couple of weeks ago. They were lost on my old laptop, but the SATA-to-USB thingy came in the mail the other day, so I can finally just do something with these.

read more...

tags: rxjs, immutable, js, utah, meetup, notes

so, tweet it?  

FP in JS

April 03, 2016 — Zac Anger

Notes taken while going through this guy's videos.

You should watch them all. He's great.

'use strict'

//
// HOF
//
// Higher Order Functions
// functions are values
// const something = function > function something
// obvs functions passed into functions
// composition yay
// example: filter (method on array, takes another function as action)
// filter's should return true or false to determine whether item belongs in arr
let something = [{foo : 'bar'}, {quux : 'baz'}, {whatever : 'target'}]
let newArr
for (let i = 0; i < something.length; i++) {
  if (something[i].what === 'target') {
    newArr.push(something[i])
  }
}
// vs
let newArr = something.filter(thing => {
  return thing.what === 'target'
})
// or, using reject
let isTarget = something => thing.what === 'target'
let notTarget = something.reject(isTarget)
// note: there's also find. that returns just the first item that matches.

//
// Map
//
// map's cb returns a transformed object to put into array
let peeps = [
  {name : 'geordyn', relationship : 'bffl'                   }
, {name : 'erin'   , relationship : 'number one bro'         }
, {name : 'ryan'   , relationship : 'nemesis. also, the one.'}
, {name : 'andrew' , relationship : 'special mormon'         }
, {name : 'sarah'  , relationship : 'grandma'                }
]
// non-functional way of doing getting an array of the names
let names = []
for (let i = 0; i < something.length; i++) {
  names.push(something[i].name)
}
// vs
let names = peeps.map(peep => peep.name)
let about = peeps.map(peep => peep.name + ' is my ' + peep.relationship + '.')

//
// Reduce
//
// map, filter, reject, and find are fairly specific list transformations.
// reduce is is more of a swiss-army knife. it can do just about anything.
// reduce wants an object, though. (yes, it's a method on the array prototype.)
let stuffToSum = [
  {amount : 4   }
, {amount : 16  }
, {amount : 1024}
, {amount : 4096}
]
// so...
let total = 0
for (let i = 0; i < stuffToSum.length; i++) {
  total += stuffToSum[i].amount
}
// vs
let total = stuffToSum.reduce((sum, stuff) => sum + stuff.amount, 0)
// this is adding stuffToSum[0].amount to sum (which is initialised at 0)
// and returning that sum, then going again with stuffToSum[1].amount and
// the current sum (4), and so on.
//
// let's say we have some file in TSV format, like below. (i'm using 4 spaces
// to represent a tab here, since tabs = 2 spaces in all my editors, and 2 spaces
// isn't large enough to clearly distinguish fields here, i think.)
// miss lady    an item    7    20
// miss lady    a thing or two    75    2
// some dude    another product    33    9
// some dude    some product    100    1
// we need to transform this into a nice looking object (containing two objects,
// one for each person, each containing an array of objects that are the items bought).
import fs from 'fs'
let contents = fs.readFileSync('./thatFile.tsv', 'utf8')
.trim()                        // remove trailing newline
.split('\n')                   // split into array of strings at newlines
.map(line => line.split('\t')) // \t is a tab character
.reduce((persons, line) => {
  persons[line[0]] = persons[line[0]] || []
  persons[line[0]].push({
    name  : line[1]
  , cost  : line[2]
  , quant : line[3]
  })
  return persons
}, {})
console.log('contents: ', JSON.stringify(contents, null, 2))

//
// Closures
//
function sendReq(){
  let reqId = 'asdf'
  $.ajax({
    url : '/someurl'
  , success(response){
      console.log('request ' + reqId + ' returned')
    }
  })
}
// see, we don't have to pass stuff around here. reqId is going to be 'asdf'
// no matter when jquery's ajax finishes whatever it's doing. nice.
// there's also this classic example:
function makeAdder(x){
  return(y => x + y)
}
let
  add4 = makeAdder(4)
, add8 = makeAdder(8)
console.log(add4(16))
console.log(add8(64))

//
// Currying
//
// so, you've got some arguments. you could have a function that
// takes your bunch of arguments and does stuff with them. or you could
// have a function that takes your first argument and winds up returning
// a function that takes your second argument which returns a function
// that takes your third argument... etc., you get the idea.
let self1 = (name, age, language, location) =>
  `Hi, I'm ${name}, age ${age}. I speak ${language} and live in ${location}.`
console.log(self1('zac', 26, 'english', 'utah, i guess'))
// vs
let self2 = name => age => language => location =>
  `Hi, I'm ${name}, age ${age}. I speak ${language} and live in ${location}.`
console.log(self2('zac')(26)('english')('utah, i guess'))
// why? maybe i don't know everything about myself yet, but my app will find
// out some of this information later. so i call self('zac'), have a birthday,
// call self(27)('english') because it's been another year and i still only
// speak one language, and then i call self('texas??') because i've moved.
// now, finally, i have the return value (the introductory sentence)!
// what about self1? we could always use something from some library to
// transform it, like wu.js's autoCurry, or whatever. for the sake of familiarity,
// try lodash (first npm i -S lodash):
import _ from 'lodash'
let me = _.curry(self1)
console.log(self1('zac'))
// yay! okay, another example.
let
  guitars = [
  {brand : 'ovation'    , type : 'acoustic' }
, {brand : 'silvertone' , type : 'acoustic' }
, {brand : 'esp'        , type : 'electric' }
, {brand : 'teton',     , type : 'acoustic' }
, {brand : 'danburn'    , type : 'electric' }
, {brand : 'homemade'   , type : 'cigar-box'}
]
, isType    = (type, obj) => obj.type === type
, electrics = guitars.filter(x => istype('electric'), x)
console.log(electrics)
// okay, so using the same guitars array:
import _ from 'lodash'
let isTypeCur = _.curry((type, obj) => obj.type === type)
  , acoustics = guitars.filter(isTypeCur('acoustic'))

//
// Recursion
//
// recursion is not at all a difficult idea. won't even
// bother laying it out here, really. a function calls itself
// until it's done calling itself. it's a super useful way to
// program, especially in actual functional languages.
// es6 makes recursion a lot nicer. we can get rid of the
// if statement in the below function in es6 because we won't
// end with a 'RangeError: Maximum call stack size exceeded
// or whatever.
let countDown = num => {
  if (num === 0) {
    return
  }
  console.log(num)
  countDown(num - 1)
}

//
// Promises
//
function loadStuff(url, cb){
  let img = new Image()
  img.onload = () => {
    cb(null, img)
  }
  img.onerror = () => {
    let msg = 'failed loading ' + url
    cb(new Error(msg))
  }
  img.src = url
}
export default loadStuff
// with
import loadStuff from './loadStuff'
let addThing = src => {
  let el = document.createElement('img')
  el.src = src
  document.body.appendChild(el)
}
loadStuff('/thing/to/load.png', (err, img) => {
  if (err) {
    throw err
  }
  addThing(img.src)
  loadStuff('/thing/two.png', (err, newImg) => {
    if (err) {
      throw err
    }
    addThing(img.src)
    // etc
  })
})
// vs
function loadThing(url){
  return new Promise((resolve, reject) => {
    let img = new image()
    img.onload = () => {
      resolve(image)
    }
    img.onerror = () => {
      let msg = 'failed loading ' + url
      reject(new Error(msg))
    }
    img.src = url
  })
}
export default loadThing
//with
import loadThing from './loadThing'
let addThing = src => {
  let el = document.createElement('img')
  el.src = src
  document.body.appendChild(el)
}
Promise.all([
  loadThing('/path/one.png')
, loadThing('/path/two.png')
// , etc
]).then(images => {
  images.forEach(img => addThing(img.src))
}).catch(err => {
  throw err
})

tags: functional-programming, javascript, js, fp, functional, notes, examples, map, filter, reduce, promises, closure, closures, recursion

so, tweet it?  

basic auth

February 12, 2016 — Zac Anger
  • Basic HTTP:
    • restricted based on system user/pass
    • http://zacanger:encryptedpassword@zacanger.com
  • Form-based:
    • restricted based on cookies
    • success = stored cookie on client
    • POST whatever.com/login (headers)
  • Token-based:
    • requests with auth token
    • https://foo.bar/whatever?auth_token=asdfghjkl123456789
  • OAuth
    • rate limited, expired, revoked server-side
  • Passport
    • this is, clearly, the preferred method, both with devmtn and with express in general, i feel

read more...

tags: auth, node, js, passport

so, tweet it?  

ES-Next Notes

February 05, 2016 — Zac Anger

That is, es-next-next notes. Like, es7-or-whatever-we're-calling-it-today, and es-the-number-after-that notes.

What ~~will~~ might we get?

Array.prototype.includes // so, for example, instead of:
if(someArr.indexOf(val) > -1) // we can do:
if(someArr.includes(val))

// you know how we have destructuring with arrays in es6? what about objects?
let {x,y,...z} = {x:1,y:2,a:3,b:4}
x // 1
y // 2
z // {a:3, b:4}
// and...
let q = {x,y,...z}
q // {x:1,y:2,a:3,b:4}

// decorators (for modifying/annotating classes on creation)
function foo(target, name, descriptor){
  descriptor.something = whatever
  return descriptor
}
class Bar {
  @foo
  quux() {return `this thing is ${this.baz} asdf lkadjfklal`}
}
// so, quux is gonna conform to whatever we said in foo()

// we get exponents!
Math.pow(x,y) // no more! now just
x ** y

// simd! (limited to 128 bits though--256 and maybe 512 in the future?)
let foo = SIMD.float64x2.load(oneArr, 0)
let bar = SIMD.float64x2.load(twoArr, 0)
let res = SIMD.float64x3.add(x,y)
SIMD.float64x2.store(treArr, 0, res)
// this will make calc with typed arrs & typed objs sooo much faster

// es-next-next (es8?) may have type annotations!
// oh, and macros?! howlly craaeep.

// async functions and generators, with possible syntax like:
async function* whatever(){
  yield 1
  yield 2
  yield 3
}
async function things(){
  for(var asdf on whatever()){
    console.log(asdf)
  }
}
// Object.values, Object.entries, Object.getOwnPropertyDescriptors
// Typed Objects, so like
var Asdf = new StructType({
    x : int32
, y : int32
})
var Ghjkl = new Asdf({
  x : 99
, y : 120
})
// trailing commas... which is kinda dumb, actually, in a few ways.
// .toJSON (Set.prototype)
// String.prototype.at
// String.prototype.padLeft, .padRight, .trimLeft, .trimRight
// Regexp.escape ?!
::forEach(x => return(x)) // BINDING/METHOD EXTRACTION!

tags: es7, es8, ecmascript, js

so, tweet it?  

Closures

February 02, 2016 — Zac Anger

A closure is a local variable for a function, which sticks around after the function has been returned.

(Or, a closure is a stack-frame which is not deallocated when the function returns [as if a 'stack-frame' were malloc'ed instead of being on the stack!]. Whatever that means.)

Here, let's explain in Javascript.

function sayHi(name){
  var text = 'hi ' + name // (local var)
    , say  = function(){
    console.log(text)
    return say
  }
}
var sayIt = sayHi('zac')
sayIt() // returns 'hi zac'

So here, a function is returned as a variable.

What we're doing here is putting a function inside a function. And we're getting something accessible outside of that enclosing function, right?

Hence closure.

In most descendants of C, after a function returns, its local variables are gone. The stack-frame is gone.

In JS, functions that are inside other functions can still be accessed outside of (after) that parent function. Try using the above code, and then doing sayIt.toString(), and you'll see that the variable say is returned -- which is a function that references text, which is a variable local to sayHi().

function oneMore(){
  var i     = 1
    , logIt = function(){
    console.log(i)
  }
  i++
  return logIt
}
var logStuff = logIt()
oneMore() // 2

Make sense? Here's a slightly more complex example pulled straight from the interwebs.

var logNumber, increaseNumber, setNumber
function setupGlobals(){
  var i = 4
  logNumber = function(){
    console.log(i)
  }
  increaseNumber = function(){
    i++
  }
  setNumber = function(x){
    i = x
  }
}
setupGlobals()
increaseNumber()
logNumber()     // 5
setNumber(8)
logNumber()     // 8
var oldLog = logNumber
setupGlobals()
logNumber()     // 4
oldLog()        // 8

Local variables from a closure will be overwritten if you call that outer function again. Don't forget this, because you can get some really screwy stuff going on if you do!

There is a closure for every function call, not for every function declaration. This example might help demonstrate this.

function newClosure(fooInt, barRef){
  var num     = fooInt
    , quuxArr = [1, 2, 3]
    , ref     = barRef
  return function(x){
    num += x
    quuxArr.push(num)
    console.log('num: ' + num +
      '; quuxArr: ' + quuxArr.toString() +
      '; ref.bazVar: ' + ref.bazVar)
  }
}
obj = {bazVar: 4}
fn1 = newClosure(4, obj)
fn2 = newClosure(8, obj)
fn1(1)     // num:5; quuxArr:1,2,3,4,5; ref.bazVar: 4
fn2(1)     // num:9; quuxArr:1,2,3,8; ref.bazVar: 4
obj.bazVar++ // 4
fn1(2)     // num:7; quuxArr:1,2,3,5,7; ref.bazVar:5
fn2(2)     // num:11; quuxArr:1,2,3,9,11; ref.bazVar:5

So... a quick recap?

When a function is used inside another function, you've used a closure. This includes eval(). (Note that using a constructor, as in new Function(), does not create a closure.)

Every time you call a function with a closure, it makes a new set of those local variables.

Closures can definitely be nested.

read more...

tags: js, closures, notes, closure

so, tweet it?  

REACT NOTES

January 25, 2016 — Zac Anger

This is all such a mess, and so unsorted, so, sorry about that in advance.

This is also almost entirely notes from very early on in trying to learn React, so not all of it will be completely valid, probably. Okay. So.

Enjoy.

REACT NOTES (yeah, again):

There's no if...else in JSX. Doesn't work. Don't try it (in your JSX).

Don't try <!doctype> either. It'll break stuff.

Same with HTML comments. Not worth the trouble, I guess. No one reads them, anyway, so whatever.

Don't try to use your own code style. JSX needs to be written the way the docs say to. Doing React means doing React their way, so screw your purely stylistic preferences, they don't matter anymore. Which, unfortunately, means semicolons everywhere. Gross.

Every single XML tag needs to be closed. That means that <br> is invalid, but <br></br> is... totally valid. Also, self-closing tags (which literally do not even exist in HTML anymore) work just fine, so <div /> is valid. What the hell.

In JSX, everything in {} will be evaluated as Javascript. So you can do some things there, if you need to. (But not if...else!)

Any JSX over multiple lines needs to be wrapped in parens. If it's single-line, you don't need them.

Evidently it's better to indent all the stuff going in your tags just inside the tag, rather than even with the first whatchamacallit. This is what I mean:

<input type="text"
       value={whatever.stuff}
       onChange={this.foo.bar} />

...is apparently NOT the way to do it. Instead, we want to do:

<input
  type="text"
  value={whatever.stuff}
  onChange={this.foo.bar} />

which, personally, I find more annoying and less readable, but apparently that's how the React community does, so whatever. Oh, and as to the closing of the tag, no matter what it's gonna be hideous, so I don't know or care whether it should be on a newline. Probably not, because that's just even more lines, but I have seen a lot of this:

<input type="text"
  value={whatever.stuff}
  onChange={this.foo.bar}
/>

which is really even more annoying, but whatever. Lastly, as far as style goes, I'll just put what would make the most sense to me, personally. Note how clean and lined up things are? Yeah. Much better, to my eyes. Still ugly af, though.

<input type="text"
      value={whatever.stuff}
   onChange={this.foo.bar} />

read more...

tags: react, webpack, js, notes, redux

so, tweet it?  

Isomorphic Apps in React

January 25, 2016 — Zac Anger

I don't know for sure that this deserves its own file... we'll see.

We'll be processing several requests simultaneously, so we should deal with a global state (dependent on user) (like flux stores state, or whatever).

About 90%, really, of the client and server code, should be shared.

Which parts should be isomorphic?

  1. view
  2. styles
  3. routing
  4. data fetching
  5. config
  6. i10n

The view is already there, really. Just gotta use ReactDOM.renderToString instead of ReactDOM render.

Inline styles better than individual sheets in the dirs, for this architecture. React supports them. That said, one should emulate pseudo attributes (:hover, :active, and :focus, for example) in your Javascript. Handle your own prefixes (grooosss). Emulate your media queries in Js, too. Gotta eventually merge the CSS somehow; http://stack.formidable.com/radium/ isn't half-bad for that.

Because there's so much Js to bundle up and load, it's actually okay to but the bundle at the end of your markup for this case. But we want to split things out in the webpack.config.js, so that we've got CSS on its own and can load that first the way we used to. Here's a sample webpack.config.js:

var webpack = require('webpack')
var ExtractTextPlugin = require('extract-text-webpack-plugin')

module.exports = {
  entry: "./src/app.js",
  plugins: [
    new webpackDefinePlugin({
      "process.env": {
        BROWSER: JSON.stringify(true),
        NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
      }
    }),
    new ExtractTextPlugin("[name].css")
  ],
  output : {
    path: __dirname + '/public/build/',
    filename: 'bundle.js',
    publicPath: 'build/'
  },
  module: {
    loaders: [
      {
        test: /\.css%/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader")
      },
      {
        test: /\.less$/,
        loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader!less-loader")
      },
      {
        test: /\.png$/,
        loader: "url-loader?limit=10000&mimietype=image/png"
      },
      {
        test: /\.jsx$/,
        loader: "react-hot!babel!eslint-loader",
        exclude: [/node_modules/, /public/]
      },
      {
        test: /\.js$/,
        loader: "babel!eslint-loader",
        exclude: [/node_modules/, /public/]
    ]
  },
  eslint: {
    configFile: '.eslintr`^c'
  }
}

React Router works well for isomorphic stuff. Here's an example of using it with server-side rendering:

import {renderToString} from 'react-dom/server'
import {match, RouterContext} from 'react-router'
import routes from './routes'

serve((req, res) =>
  // req.url would be full url path from original request, including query string
    match({routes, location: req.url}, (error, redirectLocation, renderProps) => {
      if (error){res.status(500).send(error.message)}
      else if (redirectLocation){res.redirect(302, redirectLocation.pathname + redirectLocation.search)}
      else if (renderProps){res.status(200).send(renderToString(<RouterContext {...renderProps} />))}
      else {res.status(404).send('404 not found')}
  })
)

Redux in an isomporhic app: better than a singelton flux store. With Redux we can use react-redux's react context. Using redux store's API makes dumping and restoring store state easy. Check the code of https://github.com/WebbyLab/itsquiz-wall for a really good, in-depth, production app using all of the above tech in an isomorphic app.

Here's a simple api example that works both server- and client-side:

'use strict'
import apiFactory from './api'

const api=apiFactory({
  apiPrefix: 'http://pharoah.js.org/api/v1'
})
const promise = api.users.list()

Here's a promise-pased client: https://www.npmjs.com/package/axios

Here are two that use Fetch (which are fine in Mozilla and Chromium, now): https://www.npmjs.com/package/isomorphic-fetch and https://www.npmjs.com/package/node-fetch

So, here's what we might do on the client:

  • render react components
  • show spinners
  • fetch component-dependent data
  • update the page

And on the server:

  • preload all the data
  • render the page to a string
  • send html to the client

How to do this isomorphically? Check that itsquiz app again, it's so much easier than typing out an example here.

For a full-on tutorial using React and Redux to make an isomorphic app (Todos, of course...), check here: https://medium.com/front-end-developers/handcrafting-an-isomorphic-redux-application-with-love-40ada4468af4

tags: isomorphic, react, js

so, tweet it?  

Meteor Notes

January 21, 2016 — Zac Anger

General Notes, from that time I played with Meteor

{{#with foo}} is a template tag that takes arg (foo). that is the data context for the block in that tag. being a tag, it needs to be closed later ({/with}).

{{#each}} also takes an argument, usually a 'cursor' such as the result of Collection.find().

Includes are like so: {{> foo bar}} which will bring in the bar from foo.

meteor's blaze will soon just be a thin templating layer over react.

iron router is meteor's primary routing package. its 'data' method helps with data contexts.

in meteor there are html templates and js template helpers, in which data context is accessible via this. an example:

<template name="profile">
  <h3>profile</h3>
  {{#with profile}}
  <img src="{{avatarPath}}" />
  {{#with name}}
  <p>{{fullName}}</p>
  {{/with}}
  {{/with}}
</template>


Template.profile.helpers({
  profile: function(){
    return Users.findOne(Session.get('userId'))
  },
  avatarPath: function(){
    return 'images/' + this.avatar
  },
  fullName: function(){
    return this.first + ' ' +  this.last
  }
})

a dedicated {{log}} helper can be more useful than console.log(this)

Template.profile.helpers({
  log: function(){
    console.log(this)
}})


<template name="profile">
  {{#with profile}}
  {{log}}
  <!-- etc -->
  {{/with}}

the .. keyword in helpers is to access a parent. That's pretty fucking rad, actually. And the ../.. also works exactly as expected (eg {{blah ..}} and {{blahblah ../..}}).

Reactivity in Meteor

Reactive computation: block of code (inside of a function) that re-runs when a reactive data source inside it changes.

Template.hello.helpers{(
  counter: function(){
    console.log('counter helper is running')
    return Session.get('count')
  }
)}

Here, counter re-runs whenever count changes (count is retrieved by Session.get('count_')).
Session variables are reactive sources. Template helpers are reactive computations.

Reactive variables in Meteor:

  • Session variables
    • defined with Session.set()
    • retrieved with Session.get()
    • global to the app, and reactive
  • Cursors
    • what you get when querying db
    • (via Collection.find())
  • Subscription's ready() method
    • subscription.ready() is when the client has received all data
  • some others, including:
    • Meteor.user()
    • Meteor.userId()
    • Meteor.status
    • Meteor.loggingIn

Reactive computations:

  • template helpers (eg {{something}} in a template, duh)
  • iron router (third party) hooks are reactive
    • route functions and most hooks are run in a reactive computation

Custom reactivity in meteor:
reactive-var (third party package) enables defining own reactive variables.
these don't have global names (like Session.get('foo')'s foo), more like this.foo.get()
declared like new ReactiveVar().

var count = new ReactiveVar(0)
count.set(1)
count.get() // 1

There's also ReactiveDict. That's a thing.

Custom reactive computations:
Tracker.autorun(function(){})
Read the full Meteor manual for more on that, I guess.

Reactivity can be passed on through composition, eg var getCount = function(){ return Session.get('count') } -- getCount is a reactive data source, by virtue of Session.get('count'), which is itself a reactive data source.
SO...

Template.hello.helpers({
  counter: function(){
    console.log('counter helper is running')
    return Session.get('count')
  }
})

IS THE SAME AS

var getCount = function(){
  return Session.get('count')
}

Template.hello.helpers({
  counter: function(){
    console.log('counter helper is running')
    return getCount()
  }
})

both ways, counter reruns whenever count session variable changes.

composition only applies to functions. not variables.

tags: meteor, js

so, tweet it?  

meteor and react

January 21, 2016 — Zac Anger

anything in <template>is a _meteor_ template</template>; include in html by {{> thatTemplate}}, or in js with Template.thatTemplate. (not doing that at all with react as view.)

React.createClass defines a new view... class. why are components classes? props are attributes that allow compnents/classes to inherit data.

render() (react) gets a description of the markup to show. html's inside jsx, so get used to angle brackets in your scripting, yay.... jsx: className instead of class. jsx, not templating lang... just compiles to plain old js.

jsx can use es6 (what about esnext-next?). this includes const & let, methodShorthand(){...}, and =>.

collections: how meteor stores persistent data. aka mongo. lol duh. accessible from server and client.

collectionName = new Mongo.Collection("collection-name") to make that happen. that makes a new mongo collection on the server, and cache on the client.

tags: meteor, react, js

so, tweet it?  

BaconJS

January 19, 2016 — Zac Anger

Note: this post references 'the snake game' a lot. That's over
https://github.com/zacanger/extras/tree/master/bacon, now.

Bacon is a JS lib for FRP, like Rx, but not MS.

Here's some jQuery, because I don't know why.

var go = $('#clickMe').asEventStream('click')
go.onValue (
  () => $('#output').append('clicked!'))

Is it just me or is this tutorial using typescript? Eww, it totally is! Gross.

scan combinator is kinda like reduce, except async and produces multiple values. So, there's an initial value, and a function to combine them. Returned stream contains the aggregate.

var clicks = $('#example button').asEventStream('click')
  , counter = clicks
      .map(1)
      .scan(0, (x,y) => x + y)
counter.onValue(x => $('#example .output').html(x))

Ohh, okay, so the 'take' and 'skip' combinators are new. They do what they sound like. Basically like slicing arrays, but with streams.

read more...

tags: bacon, js, frp, streams, events, functional, programming, reactive

so, tweet it?  

Front-end Engineer's Manifesto

January 18, 2016 — Zac Anger

A somewhat modified version of the document fount here

  • USERS are the most important part of what I do.
    • The users' needs come first.
    • What I want, as a developer, is much less vital.
  • Progressive enhancement is the most important phrase I know.
    • WIthout JS, without Webkit, without even CSS, what I build will still function.
  • Simplicity is respect.
    • Unnecessary complexity, whether in code or in design, should always be fought.
    • Simple interfaces mean minimal mental overhead.
    • Complicated interactions and designs are taxing.
  • Choices matter; I will help the people I can influence make good ones.
    • Web browsers are not all created equal.
    • Software that does not implement web standards, or which is not responsive to the advancement of the web, should be recommended against.
    • The choice of browser is especially important on mobile devices, where Safari will result in broken websites.
  • I believe in the openness of the web.
    • Flash should be fought, tooth and nail.
    • Proprietary formats should never enter my work.
    • Device-independent content first.
  • Performance is critical.
    • I understand that HTTP requests mean latency, and latency means frustrated and lost users.
    • I understand that my hardware is not representative of the real world, and will be mindful of limited hardware and low bandwith.
  • I will never stop educating myself.
    • I will learn from the root, rather than beginning with abstractions: Javascript before jQuery, CSS before Sass, et cetera.
    • I will better myself not just in code and maths, but also in art, music, design, research, and the study of usability.
    • I understand that I cannot learn everything, and will be mindful of what I do not know.
  • I believe that Free and Open Source code and software are the future of the web.
    • When considering file formats and media codecs, open is always better.
  • I will never underestimate the importance of accessibility.
    • Users who may have trouble differentiating colours or difficulty reading small fonts are not all of accessibility.
    • Users who prefer to use the keyboard, or print content, or browse on limited devices, matter too.
  • I will contribute.
    • Giving back to the community, in the form of bugfixes, workarounds, polyfills, snippets, raised issues, documentation, and any other form is imperative.
    • This is how the web grows. This is how the development community grows.
  • I accept responsibility for view-source:
    • I will use future-safe code.
    • I will always prefer feature detection over user-agent sniffing.
  • My code is portable.
    • Overzealous CSS specificity and the polution of the global Javascript namespace will be avoided.
    • I will be mindful of browser quirks.
  • I will choose the right tool for the job.
    • Whether a choice between large frameworks, or small libraries, or languages, or even preprocessors, I will educate myself.
    • I will learn from the mistakes others have made to help me make the right choice for my project.
  • I will create applications with security in mind.
    • My code will be properly escaped to help prevent XSS and CSRF.
    • I will not store sensitive information in cookies.
    • I will avoid cookies unless there are no alternatives.
    • I will use HTTPS wherever appropriate.
    • I will be responsive in correcting any issues that may harm the users of my code.

tags: design, front-end, manifesto, list, js, css

so, tweet it?  

EVERYTHING IS A STREAM, or Notes On FRP

January 18, 2016 — Zac Anger

IT ALL MAKES SENSE NOW.

Promises are Observables. Promise++, specifically. Note that that means Observables are not Promises/A+ compliant. A Promise would be an Observable with one single emitted value. Our streams return many values.

Listening to streams is Subscribing. We return new streams, hence the term Immutability, which is regarding the original (unchanged, unchangeable) streams.

We do things like mapping, filtering, and scanning. Simple functions applied to streams that return new streams.

A map(f) takes input stream, applies f(), produces value on output stream.

If one creates what we will call a 'metastream' we're basically making a stream of POINTERS. WHY DOES THIS ALL MAKE PERFECT SENSE?!

RxJS has a .flatMap() which is brilliant, it flattens said 'metastream' and emits on a trunk stream everything that would be emitted on the branch streams.

Okay, following the tutorial, I'm going to move these notes over to the actual rx-js/frp directory....

There's a .startWith() that does EXACTLY what it sounds like. No matter the input stream, the output of startWith(x) will have x at the beginning.

It looks to me like everything about FRP makes a lot more sense if graphed/charted first. ASCII can work for this pretty well. Example:

  streamyInput: -1---2---3---45->
   inputStream: ----a----b--c--->
  dostuffThing: -----X-----X---->
  outputOfThat: ---------E----E->
streamPostWhat: ----Q---IDK----->

Hurray, streams!

In Rx there's a combineLatest() that takes two input streams and joins the two most recently emitted values from both streams, like:

A: ---a-------e----i------->
B: -----b--c----d------q--->
//////combineLatest(f)//////
-----AB--AC---EC-ED-ID--IQ->

Huh. I don't actually know why this isn't working, exactly.

OH WAIT DUH, I forgot jQuery. Thank goodness. I really was hoping I wasn't gonna have dumb problems. YAY THIS IS NICE!

read more...

tags: rxjs, reactive, js, frp

so, tweet it?  

ES6 Notes

January 18, 2016 — Zac Anger

(These are some random notes from a lecture on ES6.)

let = var, but block scoped, finally. this means no leaks. Let can't be redeclared outside of its block, because it doesn't exist outside of there.

const = var, but it's a constant, finally. this means variables you can't fuck with, man! for simple things, that is. const x = 2; x = 3 does not work. however, parts of a const are mutable; that is, const y = [0, 1, 2, 3]; y[0] = 7 does work. Constants can be global or local, that's just up to how you declare it. Const and let behave the same no matter where you declare them; the difference is that const can't be defined again, whereas let can be redefined. Neither of them can be declared again.

read more...

tags: js, javascript, ecmascript, es6, es2015

so, tweet it?  

Electron and NW.js

January 15, 2016 — Zac Anger

Electron (formerly known as Atom Shell) and NW.js (formerly known as Node Webkit) are similar projects that bring Javascript to the desktop. They're both based on browser runtimes. Electron is sponsored by Github, and uses libchromiumcontent and Webkit 537 (as of Autumn 2015). NW.js is sponsored by Intel and uses Chromium and Blink/Webkit 537. They both use the V8 JS engine (from Chrome), are fully open source (MIT Licensed), can access a variety of open and licensed codecs, work on Unix-like systems (and, with a little extra work, on Windows), and can use Flash (in Electron's case, through the Pepper plugin). The biggest difference I've had in working with them is that Electron, being currently more popular (likely because of the Github support, and the popularity of the Atom editor, which is built on Electron) is usually closer to the current version of Chromium, and NW.js is usually a few versions behind. Electron seems to have a lot more community activity around it right now, too, so there are a lot of useful NPM packages like Electron-Prebuilt (and a lite version) and Electron-Packager (and an interactive version!). Electron also needs a Javascript entry point, which looks something like this:

var app           = require('app')  
  , BrowserWindow = require('browser-window')  
require('crash-reporter').start()  

var mainWindow = null  

app.on('window-all-closed', function(){  
  if(process.platform != 'darwin'){  
      app.quit()  
  }  
})  
app.on('ready', function(){  
  mainWindow = new BrowserWindow({  
    width                : 1200  
  , height               : 800  
  , 'accept-first-mouse' : true  
  , 'title-bar-style'    : 'hidden'  
  , 'node-integration'   : false  
  })  
  mainWindow.loadUrl('http://127.0.0.1:9090')  
  mainWindow.on('closed', function(){  
    mainWindow = null  
  })  
})  

That 'node-integration' line is really important if you want to use certain client-side libraries like Angular or jQuery that use the word 'module;' your stuff will just completely break without it.

NW.js, on the other hand, can just be pointed at your index.html, and that's enough to get started. That's really convenient, but for my own uses I've found that Electron has a lot more options. Its binaries are significantly larger, but there are evidently ways to cut them down. Don't count on being able to build an Electron app in less than a hundred megs, though.

If you're doing something small, like a text editor or some other little widgety kind of app, you'd probably still be better off with Qt or GTK--you can write a full text editor in GTK-Webkit with Python in less than 16kb, and that's if need a full rich-text interface with buttons and such. But for larger apps, and especially for apps you've already written for the browser, NW.js and Electron are both really great options. If you're going to be relying on a lot of the Node environment, Electron's got a better interface to Node because of its separated rendering and browser engines, but you do have to keep in mind that you'll be limited as to what client-side libraries you can use.

tags: nwjs, electron, desktop, js, javascript, apps, node

so, tweet it?  

Elm (notes)

January 14, 2016 — Zac Anger

Differences from JS:

  • Elm has multiline string support, with triple sets of quotes, eg """multiline string"""
  • Elm cannot use single quotes for strings. Elm uses single quotes to denote characters.
  • Booleans are uppercase.
  • Objects use = instead of :, so {key: value, key2: value2} in JS would be {key = value, key2 = value2} in Elm.
  • point.x = 42 in JS would be {point | x = 42} in Elm.
  • Functions are greatly simplified. function(foo, bar){return foo+bar} in js would be \foo bar -> foo + bar in Elm.
  • Math is a little simpler: Math.max(2,4) is just max 2 4. Same with min. Math.pow is just ^, eg Math.min(1, Math.pow(2, 4)) is min 1 (2^4).
  • numbers.map(Math.sqrt) would be List.map sqrt numbers. points.map(function(p){return p.x}) becomes List.map .x points.
  • 2 < 4 ? 'WHAT' : 'how?', if 2 < 4 then "WHAT" else "how?"
  • var foo = 72; let foo = 72 in...
  • No return statements; everything is an expression.
  • String.length "asdf" rather than 'asdf.length'

Mostly it looks pretty neat, but there's virtually nothing out there for actually learning it, so I'm already kind of over it....

Note that the 'EventLog.elm' in this directory doesn't actually need the start-app package anymore; turns out it's really easy to just wire the damn thing up all on your own.

read more...

tags: js, haskell, functional, programming, javascript, elm, lang, language

so, tweet it?  

SystemJS and JSPM

January 14, 2016 — Zac Anger

SystemJS is a module loader. It works with ES6 modules, AMD (the sort that RequireJS brought to the browser), CommonJS (the kind that most people are more familiar with, the synchronous sort), Node (which basically just uses CommonJS), and global scripts. It's basically the es6 module loader polyfill on hella steroids. Using plugins, you can load in assets (styles, images, whatevers).

To use it in the browser, you'd do something kinda like

System.config({baseUrl: '/app'})  
System.import('main.js')  

assuming we've got SystemJS coming from a CDN in there somewhere. That doesn't sound at all exciting, since we're just loading in 'main.js' from the '/app' directory, but we can do some cool things with it, like

System.config({
  baseUrl: '/app'
, transpiler: 'babel'
, babelOptions: {
    // etc.
  }
})

so, y'know, that's actually pretty super cool. We could write in ES6 and have it just work.

SystemJS uses Promise and URL. If they're not available, it'll load in an external polyfill file. Probably needed for IE. If we're using a CDN instead of bundling, load a window.Promise and window.URLPolyfill in, before SystemJS.

To get up and rolling, we need to do a tiny bit of boilerplate.

var System = require('systemjs')  
System.transpiler = 'babel'  
System.import('./app.js').then(function(m){  
  console.log(m)  
})  

That assumes we're installing with NPM, and not using JSPM at all. We should think about using it, though.

var System = require('jspm').Loader()  
System.import('someLibrary').then(function(things){  
  console.log(whatever)  
})  

So, with JSPM, we'd be handling almost everything in JSPM's own config file.

tags: bundler, build-tools, systemjs, jspm, browser, js

so, tweet it?  

Algorithms & Big-O

January 14, 2016 — Zac Anger

Algorithms and Problem Solving in One Hour or Less.

Why use algorithms? Because they're a structured set of rules to use for calculations of any type, duh. They let you loop over arrays, etc., in a more functional and portable manner.

Common uses: sorting, searching, solving.

Implementations: recursive, logical (which is exact opposite of recursive), prl/distr/etc * binary starts with a sorted list * EVERY recursive function should start, straight away, with a CYA * eg, if (searchArray.length = 0) return exit status 1 * because infinite loops are dumb

read more...

tags: algorithms, big-o, sort, math, js

so, tweet it?  

UI

January 13, 2016 — Zac Anger

UI

Systems

  • Modular is good
  • Cards are good
  • Systems are good
  • Consistency is good

Future Trends:

  • Design systems
  • Designing for change
  • Designing personalized experiences

Systems mean fast iteration means success.

Elements

Interfaces are composed of small components, which are composed of small primitives.
This lowest granular level only consists of a few elements:

  • Buttons
  • Forms
  • Lists

Everything else is usually a superset of these elements.

Trends

Don't buy into the hype. Not everything is a good thing. A lot of things are actually
really bad things, especially for the users you might not be considering.

  • Parallax -- good for flashiness, bad for a11y, users, browsers
  • Card -- good all around, for the right application
  • Media object -- an example of the elements way of doings, the 'poster child of oocss'
  • Infinite scroll -- again, looks cool, but all around actually a very bad thing to do
  • Smooth scroll -- it's not necessarily harmful, but it's not exactly fantastic, either

Natural Language Form

Forms that aren't just inputs. Mad-libs style, so one doesn't have a giant box of empty
boxes to fill in, but instead something like I want my username to be {username} and my password to be {password}, or I'm looking for {restaurant} in {city} at {time}.

Empty States

tags: ui, design, guidelines, ux, css, js

so, tweet it?  

Notes

January 13, 2016 — Zac Anger

So, I have a lot of notes that I've taken over the course of the last couple of months. Seeing as they're not doing me a whole lot of good sitting in a pile of Markdown files, I'm gradually going through them, cleaning them up, and I think I'll just post them all as sort of blog posts. Why not? So here's a little list of the topics I'll be covering over the next few weeks:

  • Unicode
  • SystemJS (and JSPM)
  • Go
  • UI
  • Github Organizations
  • Functional Reactive Programming (and RxJS)
  • Elm
  • Browserify
  • Bash Builtins
  • Firebase
  • ES6
  • Pusher
  • Styleguides
  • Passport (and problems getting errors out of Express)
  • React (and Webpack)
  • Isomorphic React
  • Flux
  • Meteor
  • All the reasons I kind of dislike Angular
  • Bacon.js
  • Basics of webmastering (which is totally not a word)
  • Functional programming (in general)
  • Effective web design
  • Mongo (and Mongoose, and MongoJS, and Mongolayer)
  • Ruby, maybe a little bit
  • Electron (formerly Atom Shell)
  • NW.js (formerly Node Webkit)
  • Gulp
  • Node in general
  • Probably a good bit of Node stuff, really
  • I like Node a lot
  • Maybe a little bit of jQuery?
  • The developer hiring process
  • Maybe a little bit of that Javascript language, or something?
  • Probably not much at all on HTML, because HTML doesn't need... notes... really
  • CSS... lol, CSS.
  • People, and the experience of dealing with people on a regular basis
  • What it's like to live with the people I live with
  • What it's like to actually find myself liking human beings, and wanting to be around them, especially certain ones, quite a lot. (It's weird!)

tags: blogs, personal, notes, education, react, js, electron, flux, meteor, elm, gulp, css, es6, ruby, mongo, bash, unicode, go, ui, design

so, tweet it?  

Express vs Koa vs Hapi

December 30, 2015 — Zac Anger

Express vs Koa vs Hapi

Quick little comparison of the three. Express is clearly the most commonly used, but I'm inclined to jump to Koa whenever I can. The simple fact that the guy who initially started Express passed that off to a company to maintain and instead works on Koa, now (which he also started), says to me that maybe Koa's the right way to go.

Okay, so all three are Sinatra-alikes for Node.

Express was started in 2009, and is now maintained by StrongLoop, the Node API company.

Koa was started in 2013, and rather than a 'server-side web development framework build on node.js' (that's Express), Koa is 'expressive middleware for node.js using generators ... to make writing web applications and REST APIs more enjoyable.' It's super small, too--around 400 SLOC.

Hapi was started in 2011, and was originally built on Express. The original author still maintains it, backed by the original company (...Wal...Mart...). It's no longer Express-based, because 'configuration is better than code ... business logic must be isolated from the transport layer...', so, there's that.

Making things happen:

    // express
    const express = require('express')
      , app = express()
      , port = 3000
    // etc, we already know all this
    app.listen(port) // http.createServer() basically

    // koa
    const koa = require('koa')
      , app = koa()
      , port = 3000
    const server = app.listen(port, function(){
      console.log('listening on ' + port)
    }) // well, THAT looks super familiar, huh?

    //hapi
    const Hapi = require('hapi')
      , server = new Hapi.Server()
    server.connection({port:3000})
    server.start(() => {
      console.log('server over yonder on ', server.info.uri)
    }) // that takes a weee bit more work, there.
    ```

    routing:
    ```javascript
    app.get('/', function(req, res){res.send('hi')})

    app.use(function *(){this.body = 'hi'}) // so, koa uses es6 generators.
        // the context (this) is node's `request` and `response`, wrapped up
        // `this.body` can be string, buffer, stream, object, or null

    server.route({
      method : 'GET',
      path: '/',
      handler: function(request, reply){
        reply('hi') // holy boilerplate, batman
      }
    })

read more...

tags: express, koa, js, hapi, server, node, framework

so, tweet it?  

Front-End Performance Notes

December 28, 2015 — Zac Anger

Performance matters. That's just a thing. I really don't care all that much about the browser-side stuff, personally, and I'm a wee bit sick of a lot of the client-side frameworks that have most of the market, because they mean you really have to care about using a lot of JS in the browser... because that's where you're doing most of the work. Things like Angular really show off this kind of horrible way of building apps. Putting all the work in every person's browser sure makes a lot of sense if you've got one tiny SPA and you're serving it from a home netbook or whatever... but come on, people. Stop hurting users. Be realistic. It's not even about doing what's probably actually the right thing to do... it can, if you want, just be about the dollar. Users don't want to wait. No one wants to wait. Sending out a whole bunch of scripts to a three-year-old knockoff tablet from China that's running on DSL out in the country and then figuring that user is okay with waiting while their device slowly loads it all in and slooowly runs the scripts and then finally starts showing them the goddamn site they're trying to see... that's how you lose people. There are truckloads of studies out there about the negative impact of every millisecond, so I won't keep rambling, and will start getting down to some note-taking and summarizing.... Oh, right. I'm reading through this little guide, right now, so that's what sparked this. I know I've read it before, but I'm really hardcore procrastinating learning Redux right now, so I figured I'd do something else. This is actually in my school notes directory, but it may end up as a blog post. Certainly sounds like it. Who knows?

read more...

tags: performance, front-end, speed, browser, client, javascript, js, css

so, tweet it?  

My Problem With React

December 28, 2015 — Zac Anger

There's this post kinda making the rounds lately. It's a nice post. Everything in there, I agree with, for sure. Especially as someone who feels a lot more comfortable with Node than with, say, Angular's mostly ungrokable API. I get why people like React. I get React. It's not exactly hard to pick up, anyway. It's very logical and intuitive. And I really do like the concepts behind React. But I still have problems with it.

read more...

tags: react, frameworks, libraries, riot, vue, js, javascript, angular, components, jsx, mithril, design

so, tweet it?  

things learned dealing with electron and the mean stack

December 16, 2015 — Zac Anger

In the interest of blogging the little things, I want to write down a couple of things I learned while struggling through my project. Nothing major, but a few things that I really had to dig to find answers to, buried way underneath unrelated issues in Github and whatnot.

read more...

tags: javascript, js, electron, angular, mean, school, css

so, tweet it?  

Automatic Semicolon Insertion

December 13, 2015 — Zac Anger

This is a simplified version of the section from the spec that deals with ASI, because I'm really tired of all the idiocy and debate about this. It's not a big deal whether you use semicolons everywhere or don't, but the vitriol from those who use them everywhere really needs to end, and from what I can tell it's almost entirely based on this idea that ASI is complicated. ASI is really simple, and its rules are a lot easier to remember than stupidity like ++foo vs foo++, or the rules for this. The actual spec's ASI section is less than two pages, but it can be simplified further, into probably less than a page.

read more...

tags: js, asi, semicolons, rant

so, tweet it?  

Thanksgiving Week, Projects, Fun Times, and The Future

November 27, 2015 — Zac Anger

Jesus fuck it's been an interesting week. I've learned so much this week, and managed to get almost nothing done. Markvi is up to version 0.3.0, because it now actually has the keybinds it was always meant to have. The tentatively titled Whiteboard is stuck in planning, because I kind of stopped caring about it, though I really need to get that one done since it's the main project that actually matters, here. The other project (the thing that has to do with documentation, and making money) is stalled, but I'm so ready to get moving on that because it's super exciting.

read more...

tags: school, personal, wiki, projects, vue, mithril, js

so, tweet it?  

Now things get real.

November 19, 2015 — Zac Anger

Just about done the first week of real, solid, mostly back-end funtimes. Which means, personal projects are about to start. On the one hand, I have ten thousand ideas and twenty thousand technologies I want to try. (Actually, about five Javascript frameworks that I think would be suitable, and three major ideas.) Given the amount of time I've spent on it thus far, I believe I'll be running with the 'Tinder for Jobs' concept. I'd never even seen the swipe-whatever-way thing until tonight. Now I've downloaded Tinder, swiped left, tapped on things, accidentally swiped right, tried sliding things, was thoroughly disappointed with the super Web 2.0 look and feel, and taken a lot of notes.

read more...

tags: projects, mobile, js

so, tweet it?  

React Meetup, 17 Nov, 2015

November 17, 2015 — Zac Anger

React: - Good at managing state. - which is to say, dynamism - Components, just like... everything else these days, so that's totally irrelevant. - virtual dom, which is not exactly facebook's anyway. - unidirectional data flow, which is a mouthful. - that is, the loop. - more boilerplate to run that... less boilerplate-replacer built into react?

read more...

tags: react, meetup, php, xml, js, school, meteor

so, tweet it?  

DevMountain, Week Six

November 16, 2015 — Zac Anger

Howdy. I've been here for six weeks, now. I find that totally beyond belief.

I can't remember the last time I slept for more than four hours. Or was in any reasonably okay sort of mental state. It's not the school, of course. It's just everything, and me, and needing to be all, like... not myself, I guess.

I think maybe I'm so used to the act that it just is who I am, maybe, sort of. Some of it, anyway. Apparently I'm good enough at pretending to know shit about programming that I'm actually not totally horrible at it. Still horrible at fitting in with conservatives... still horrible at socializing, or ever even having conversations with the religious, or masculine. Which is definitely sometimes a problem. Oh well.

This won't be a long post. I'm mostly only posting because (while I certainly hope no one actually reads this blog, because I say horrible things about everyone here), at some point I want to be able to keep track of what I was doing, here.

About to start the back-end stuff. That's actually really exciting, for me, personally. Nothing against front-end stuff--I really love design (though not designers, usually), and of course that's where all the flashy fun is anyway. But goddammit I just cannot justify, in my head, the idea of extensive client-side rendering. I know, everything runs Javascript, and that's chill and all, but when over 80% of the connected mobiles on the planet are Androids, and the vast majority of those are extremely low-end Chinese knockoffs that just really want to be like their Korean betters... when there are people (even people I know) who still use IE8 on Windows XP with a half gig of RAM... I just really don't think it's a grand idea to bog down those clients with all the work. Which is why I couldn't put my heart into Angular (though Angular2 will be better... but too little, too late). And goddammit, ui-router is just a whole pile of steaming useless shit, really. I've never known anything to be so bad at working with file paths. Ever. At least, not quite that inconsistent in how it was bad. Goddamn.

Actually, I'm thinking for the 'real' project (I suppose our personal projects, the ones where we actually do anything server-side, are essentially our showpieces, so the idea is to put a whole fucking lot of effort into them and hope they are employment-worthy)--anyway, for that, while I can already hear the comments about the technology-hipster-ism, I might try out basically... not that. Specifically, I'd like to work with mostly ES2016 (ES7) Node and Koa, and Aurelia for an MV* (apparently it's perfectly fine as HVVM, which would be nice to learn). And, while the guy who wrote it has probably the worst attitude of any BDFL/whatever in front-end dev (which is saying a lot, since I'm pretty nice compared to some of the stuck-up turds in JS), I'm thinking Vue would be good. Every time I see a Vue project, even some half-finished toy repo, I remember that it looks really interesting and I ought to find an excuse to check it out.

Bigger problem, right now, is figuring out what the fuck I should actually attempt to build, I guess.

Oh, speaking of which, I built a think, and it doesn't suck. npm i markvi. It's not what I want it to be, but what I want it to be isn't probably all that marketable, so it can just chill there for a while, I guess, while I figure out some super flashy idea that will win over the masses of employers that are apparently just standing around, fidgeting, waiting to hire anyone who can remember what 'fizzbuzz' means.

Iiiii should probably sleep.

tags: js, sleep, sleeeep, sleep, sleep-is-good

so, tweet it?  

zac anger?