diff --git a/circle.yml b/circle.yml
new file mode 100644
index 0000000..9cf2b94
--- /dev/null
+++ b/circle.yml
@@ -0,0 +1,11 @@
+dependencies:
+  pre:
+    - sudo apt-get install libgif-dev
+
+machine:
+  node:
+    version: 6.7.0
+
+test:
+  override:
+    - npm run lint
diff --git a/js/constants/colors.js b/js/constants/colors.js
index 53b6da1..1c22588 100644
--- a/js/constants/colors.js
+++ b/js/constants/colors.js
@@ -1,16 +1,16 @@
 const head = {
-    brick: [0, 62, 53],
-    yellow: [48, 100, 64]
+  brick: [0, 62, 53],
+  yellow: [48, 100, 64]
 }
 const bg = {
-    forest:     '#006375',
-    green:      '#63D6A3',
-    blue:       '#358EFF',
-    salmon:     '#FF9B7A',
-    coral:      '#F96854',
+  forest: '#006375',
+  green: '#63D6A3',
+  blue: '#358EFF',
+  salmon: '#FF9B7A',
+  coral: '#F96854'
 }
 
 module.exports = {
-    head: head,
-    bg: bg
-};
+  head: head,
+  bg: bg
+}
diff --git a/js/fox.js b/js/fox.js
index a249124..e0d63b5 100644
--- a/js/fox.js
+++ b/js/fox.js
@@ -1,95 +1,91 @@
-const Chance = require('chance');
-const colors = require('./constants/colors.js');
+const Chance = require('chance')
+const colors = require('./constants/colors.js')
 
 const hsl = function (h, s, l) {
-  return "hsl(" + h + "," + s + "%, " + l + "%)";
+  return 'hsl(' + h + ',' + s + '%, ' + l + '%)'
 }
 
 const Fox = function (IMG_WIDTH, IMG_HEIGHT, seed) {
-  if (seed) {
-    chance = new Chance(seed);
-  } else {
-    chance = new Chance();
-  }
+  const chance = seed ? new Chance(seed) : new Chance()
 
   // origin: head top left corner
   const kappa = chance.floating({min: 0.2, max: 0.45})
 
   const headColor = (function () {
-      const level = chance.floating({min: 0, max: 1});
-      const result = [];
-      const min = colors.head.brick;
-      const max = colors.head.yellow;
-      for (let i=0; i<min.length; i++) {
-          result.push(min[i] + (max[i] - min[i]) * level)
-      }
-      return hsl.apply(null, result)
-  }) ()
+    const level = chance.floating({min: 0, max: 1})
+    const result = []
+    const min = colors.head.brick
+    const max = colors.head.yellow
+    for (let i = 0; i < min.length; i++) {
+      result.push(min[i] + (max[i] - min[i]) * level)
+    }
+    return hsl.apply(null, result)
+  })()
 
   const head = {
     width: 0.6 * IMG_WIDTH,
     height: 0.6 * IMG_HEIGHT,
     kappa: kappa,
-    color: headColor,
+    color: headColor
   }
 
-  const origin = {x: IMG_WIDTH / 2 - head.width / 2, y: 0.5 * IMG_HEIGHT - head.height / 2};
+  const origin = {x: IMG_WIDTH / 2 - head.width / 2, y: 0.5 * IMG_HEIGHT - head.height / 2}
 
   const ears = (function (origin, headWidth, headHeight, headColor) {
-    const offsetX = chance.floating({min: 0.17 * headWidth, max: 0.2 * headWidth});
-    const angle = chance.floating({min: 0.05 * Math.PI, max: 0.2 * Math.PI});
+    const offsetX = chance.floating({min: 0.17 * headWidth, max: 0.2 * headWidth})
+    const angle = chance.floating({min: 0.05 * Math.PI, max: 0.2 * Math.PI})
     return {
       color: headColor,
       kappa: 0.9 * kappa,
       left: {
-        x: origin.x + (headWidth/2) - offsetX,
+        x: origin.x + (headWidth / 2) - offsetX,
         y: origin.y + (0.15 * headHeight),
         angle: angle,
         width: 0.4 * headWidth,
         height: 0.8 * headHeight
       },
       right: {
-        x: origin.x + (headWidth/2) + offsetX,
+        x: origin.x + (headWidth / 2) + offsetX,
         y: origin.y + (0.15 * headHeight),
         angle: -angle,
         width: 0.4 * headWidth,
         height: 0.8 * headHeight
       }
-    };
-  }(origin, head.width, head.height, head.color));
+    }
+  }(origin, head.width, head.height, head.color))
 
   const eyes = (function (origin, headWidth, headHeight) {
     // TODO: color
-    const offsetY = chance.floating({min: -0.05 * headHeight, max: -0.025 * headHeight});
-    const offsetX = chance.floating({min: 0.13 * headWidth, max: 0.25 * headWidth});
+    const offsetY = chance.floating({min: -0.05 * headHeight, max: -0.025 * headHeight})
+    const offsetX = chance.floating({min: 0.13 * headWidth, max: 0.25 * headWidth})
 
-    const eyeHeight = chance.floating({min: 0.08 * headHeight, max: 0.13 * headHeight});
+    const eyeHeight = chance.floating({min: 0.08 * headHeight, max: 0.13 * headHeight})
 
     return {
       height: eyeHeight,
-      width: eyeHeight/2,
+      width: eyeHeight / 2,
       style: 'ellipse',
       // style: chance.pickone(['ellipse', 'smiley']),
       left: {
-        x: origin.x + (headWidth/2) - offsetX,
-        y: origin.y + (headHeight/2) + offsetY
+        x: origin.x + (headWidth / 2) - offsetX,
+        y: origin.y + (headHeight / 2) + offsetY
       },
       right: {
-        x: origin.x + (headWidth/2) + offsetX,
-        y: origin.y + (headHeight/2) + offsetY
+        x: origin.x + (headWidth / 2) + offsetX,
+        y: origin.y + (headHeight / 2) + offsetY
       }
     }
-  }(origin, head.width, head.height));
+  }(origin, head.width, head.height))
 
   const nose = {
-    x: origin.x + (head.width/2),
+    x: origin.x + (head.width / 2),
     y: (eyes.left.y + chance.floating({min: 0.2, max: 0.4}) * (origin.y + head.height - eyes.left.y)),
     width: chance.floating({min: 0.03, max: 0.04}) * head.width,
     height: chance.floating({min: 0.03, max: 0.04}) * head.width
   }
 
   const mouth = {
-    x: origin.x + (head.width/2),
+    x: origin.x + (head.width / 2),
     y: (nose.y + chance.floating({min: 0.2, max: 0.35}) * (origin.y + head.height - nose.y)),
     width: chance.floating({min: 0.08, max: 0.15}) * head.width,
     height: chance.floating({min: 0.03, max: 0.06}) * head.width,
@@ -100,20 +96,20 @@ const Fox = function (IMG_WIDTH, IMG_HEIGHT, seed) {
     width: chance.floating({min: 0.5 * IMG_WIDTH, max: IMG_WIDTH}),
     height: chance.floating({min: 1.7 * (IMG_HEIGHT - eyes.left.y), max: 1.85 * (IMG_HEIGHT - eyes.left.y)})
   }
-  head.mask = mask;
+  head.mask = mask
 
   return {
     canvas: {
       height: IMG_HEIGHT,
       width: IMG_WIDTH,
-      color: chance.pickone(Object.keys(colors.bg).map(function (key) {return colors.bg[key];}))
+      color: chance.pickone(Object.keys(colors.bg).map(function (key) { return colors.bg[key] }))
     },
     head: head,
     ears: ears,
     eyes: eyes,
     nose: nose,
     mouth: mouth
-  };
-};
+  }
+}
 
-module.exports = Fox;
+module.exports = Fox
diff --git a/js/render-fox.js b/js/render-fox.js
index a244451..ee51983 100644
--- a/js/render-fox.js
+++ b/js/render-fox.js
@@ -1,151 +1,150 @@
 const renderFox = function (canvas, opts) {
-    const width = opts.canvas.width;
-    const height = opts.canvas.height;
-    const ctx = canvas.getContext('2d');
+  const width = opts.canvas.width
+  const height = opts.canvas.height
+  const ctx = canvas.getContext('2d')
 
-    ctx.fillStyle = opts.canvas.color;
-    ctx.fillRect(0, 0, width, height);
-    renderEars(ctx, opts.ears);
-    renderHead(ctx, opts.head);
-    renderEyes(ctx, opts.eyes);
-    renderNose(ctx, opts.nose);
-    renderMouth(ctx, opts.mouth);
+  ctx.fillStyle = opts.canvas.color
+  ctx.fillRect(0, 0, width, height)
+  renderEars(ctx, opts.ears)
+  renderHead(ctx, opts.head)
+  renderEyes(ctx, opts.eyes)
+  renderNose(ctx, opts.nose)
+  renderMouth(ctx, opts.mouth)
 
-    shift_canvas(ctx, width, height, 0, 0.06 * height);
-};
-
-function shift_canvas(ctx, w, h, dx, dy) {
-  const topImage = ctx.getImageData(0, 0, w, h);
-  const bottomImage = ctx.getImageData(0, h - dy, w, h);
-
-  ctx.clearRect(0, 0, w, h);
-  ctx.putImageData(bottomImage, 0, 0);
-  ctx.putImageData(topImage, dx, dy);
+  shiftCanvas(ctx, width, height, 0, 0.06 * height)
 }
 
-function renderHead(ctx, opts) {
-    ctx.save();
-    ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2);
-    ctx.rotate(Math.PI / 4);
-    drawEllipseByCenter(ctx, 0, 0, opts.width, opts.height, opts.color, null, opts.kappa);
-    ctx.restore();
-    ctx.clip();
-    drawEllipseByCenter(ctx, ctx.canvas.width / 2, ctx.canvas.height, opts.mask.width, opts.mask.height, '#fff', '#fff', 0.5);
+function shiftCanvas (ctx, w, h, dx, dy) {
+  const topImage = ctx.getImageData(0, 0, w, h)
+  const bottomImage = ctx.getImageData(0, h - dy, w, h)
+
+  ctx.clearRect(0, 0, w, h)
+  ctx.putImageData(bottomImage, 0, 0)
+  ctx.putImageData(topImage, dx, dy)
 }
 
-function renderEars(ctx, opts) {
-    const offset = {
-        x: ctx.canvas.width/2,
-        y: ctx.canvas.height/2
-    }
-    ctx.save();
-    ctx.translate(offset.x, offset.y);
-    ctx.rotate(-opts.left.angle);
-    drawEllipseByCenter(ctx, opts.left.x - offset.x, opts.left.y - offset.y, opts.left.width, opts.left.height, opts.color, null, opts.kappa);
-    ctx.restore();
-
-    ctx.save();
-    ctx.translate(offset.x, offset.y);
-    ctx.rotate(-opts.right.angle);
-    drawEllipseByCenter(ctx, opts.right.x - offset.x, opts.right.y - offset.y, opts.right.width, opts.right.height, opts.color, null, opts.kappa);
-    ctx.restore();
+function renderHead (ctx, opts) {
+  ctx.save()
+  ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2)
+  ctx.rotate(Math.PI / 4)
+  drawEllipseByCenter(ctx, 0, 0, opts.width, opts.height, opts.color, null, opts.kappa)
+  ctx.restore()
+  ctx.clip()
+  drawEllipseByCenter(ctx, ctx.canvas.width / 2, ctx.canvas.height, opts.mask.width, opts.mask.height, '#fff', '#fff', 0.5)
 }
 
-function renderEyes(ctx, opts) {
-    switch (opts.style) {
-      case "ellipse":
-        drawEllipseByCenter(ctx, opts.left.x, opts.left.y, opts.width, opts.height, "black", null, 0.5);
-        drawEllipseByCenter(ctx, opts.right.x, opts.right.y, opts.width, opts.height, "black", null, 0.5);
-        break;
-      case "smiley":
-        ctx.strokeStyle = "black";
-        ctx.beginPath();
-        ctx.moveTo(opts.left.x - opts.width, opts.left.y + opts.height);
-        ctx.bezierCurveTo(opts.left.x - opts.width, opts.left.y + opts.height, opts.left.x, opts.left.y, opts.left.x + opts.width, opts.left.y + opts.height);
-        ctx.lineWidth = 2;
-        ctx.stroke();
-        ctx.closePath();
+function renderEars (ctx, opts) {
+  const offset = {
+    x: ctx.canvas.width / 2,
+    y: ctx.canvas.height / 2
+  }
+  ctx.save()
+  ctx.translate(offset.x, offset.y)
+  ctx.rotate(-opts.left.angle)
+  drawEllipseByCenter(ctx, opts.left.x - offset.x, opts.left.y - offset.y, opts.left.width, opts.left.height, opts.color, null, opts.kappa)
+  ctx.restore()
 
-        ctx.beginPath();
-        ctx.moveTo(opts.right.x - opts.width, opts.right.y + opts.height);
-        ctx.bezierCurveTo(opts.right.x - opts.width, opts.right.y + opts.height, opts.right.x, opts.right.y, opts.right.x + opts.width, opts.right.y + opts.height);
-        ctx.lineWidth = 2;
-        ctx.stroke();
-        ctx.closePath();
-        break;
-      case "none":
-        break;
-    }
+  ctx.save()
+  ctx.translate(offset.x, offset.y)
+  ctx.rotate(-opts.right.angle)
+  drawEllipseByCenter(ctx, opts.right.x - offset.x, opts.right.y - offset.y, opts.right.width, opts.right.height, opts.color, null, opts.kappa)
+  ctx.restore()
 }
 
-function renderNose(ctx, opts) {
-
-  ctx.strokeStyle = "black";
-  ctx.beginPath();
-  ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2);
-  ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2, opts.x, opts.y - opts.height, opts.x + opts.width/2, opts.y - opts.height/2);
-  ctx.bezierCurveTo(opts.x + opts.width/2, opts.y - opts.height/2, opts.x + opts.width/2, opts.y + opts.height/2, opts.x, opts.y + opts.height/2);
-  ctx.bezierCurveTo(opts.x, opts.y + opts.height/2, opts.x - opts.width/2, opts.y + opts.height/2, opts.x - opts.width/2, opts.y - opts.height/2);
-  ctx.fillStyle = "black";
-  ctx.fill();
-  ctx.stroke();
-}
-
-function renderMouth(ctx, opts) {
-  ctx.strokeStyle = "black";
-  ctx.lineWidth = 0.01 * ctx.canvas.width;
-  ctx.beginPath();
+function renderEyes (ctx, opts) {
   switch (opts.style) {
-    case "smirk":
-      ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2);
-      ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2,
-        opts.x - opts.width/2, opts.y + opts.height/2,
-        opts.x + opts.width/2, opts.y
+    case 'ellipse':
+      drawEllipseByCenter(ctx, opts.left.x, opts.left.y, opts.width, opts.height, 'black', null, 0.5)
+      drawEllipseByCenter(ctx, opts.right.x, opts.right.y, opts.width, opts.height, 'black', null, 0.5)
+      break
+    case 'smiley':
+      ctx.strokeStyle = 'black'
+      ctx.beginPath()
+      ctx.moveTo(opts.left.x - opts.width, opts.left.y + opts.height)
+      ctx.bezierCurveTo(opts.left.x - opts.width, opts.left.y + opts.height, opts.left.x, opts.left.y, opts.left.x + opts.width, opts.left.y + opts.height)
+      ctx.lineWidth = 2
+      ctx.stroke()
+      ctx.closePath()
+
+      ctx.beginPath()
+      ctx.moveTo(opts.right.x - opts.width, opts.right.y + opts.height)
+      ctx.bezierCurveTo(opts.right.x - opts.width, opts.right.y + opts.height, opts.right.x, opts.right.y, opts.right.x + opts.width, opts.right.y + opts.height)
+      ctx.lineWidth = 2
+      ctx.stroke()
+      ctx.closePath()
+      break
+    case 'none':
+      break
+  }
+}
+
+function renderNose (ctx, opts) {
+  ctx.strokeStyle = 'black'
+  ctx.beginPath()
+  ctx.moveTo(opts.x - opts.width / 2, opts.y - opts.height / 2)
+  ctx.bezierCurveTo(opts.x - opts.width / 2, opts.y - opts.height / 2, opts.x, opts.y - opts.height, opts.x + opts.width / 2, opts.y - opts.height / 2)
+  ctx.bezierCurveTo(opts.x + opts.width / 2, opts.y - opts.height / 2, opts.x + opts.width / 2, opts.y + opts.height / 2, opts.x, opts.y + opts.height / 2)
+  ctx.bezierCurveTo(opts.x, opts.y + opts.height / 2, opts.x - opts.width / 2, opts.y + opts.height / 2, opts.x - opts.width / 2, opts.y - opts.height / 2)
+  ctx.fillStyle = 'black'
+  ctx.fill()
+  ctx.stroke()
+}
+
+function renderMouth (ctx, opts) {
+  ctx.strokeStyle = 'black'
+  ctx.lineWidth = 0.01 * ctx.canvas.width
+  ctx.beginPath()
+  switch (opts.style) {
+    case 'smirk':
+      ctx.moveTo(opts.x - opts.width / 2, opts.y - opts.height / 2)
+      ctx.bezierCurveTo(opts.x - opts.width / 2, opts.y - opts.height / 2,
+        opts.x - opts.width / 2, opts.y + opts.height / 2,
+        opts.x + opts.width / 2, opts.y
       )
-      break;
-    case "cat":
-      ctx.moveTo(opts.x - opts.width/2, opts.y + opts.height/2);
-      ctx.bezierCurveTo(opts.x - opts.width/2, opts.y + opts.height/2,
-        opts.x, opts.y + opts.height/2,
-        opts.x, opts.y - opts.height/2
+      break
+    case 'cat':
+      ctx.moveTo(opts.x - opts.width / 2, opts.y + opts.height / 2)
+      ctx.bezierCurveTo(opts.x - opts.width / 2, opts.y + opts.height / 2,
+        opts.x, opts.y + opts.height / 2,
+        opts.x, opts.y - opts.height / 2
       )
       ctx.bezierCurveTo(
-        opts.x, opts.y - opts.height/2,
-        opts.x, opts.y + opts.height/2,
-        opts.x + opts.width/2, opts.y + opts.height/2
+        opts.x, opts.y - opts.height / 2,
+        opts.x, opts.y + opts.height / 2,
+        opts.x + opts.width / 2, opts.y + opts.height / 2
       )
-      break;
+      break
   }
-  ctx.stroke();
+  ctx.stroke()
 }
 
-function drawEllipseByCenter(ctx, cx, cy, w, h, color, fillColor, kappa) {
-  drawEllipse(ctx, cx - w/2.0, cy - h/2.0, w, h, color, fillColor, kappa);
+function drawEllipseByCenter (ctx, cx, cy, w, h, color, fillColor, kappa) {
+  drawEllipse(ctx, cx - w / 2.0, cy - h / 2.0, w, h, color, fillColor, kappa)
 }
 
-function drawEllipse(ctx, x, y, w, h, color, fillColor, kappa=0.3) {
-  const ox = (w / 2) * kappa; // control point offset horizontal
-  const oy = (h / 2) * kappa; // control point offset vertical
-  const xe = x + w;           // x-end
-  const ye = y + h;           // y-end
-  const xm = x + w / 2;       // x-middle
-  const ym = y + h / 2;       // y-middle
+function drawEllipse (ctx, x, y, w, h, color, fillColor, kappa = 0.3) {
+  const ox = (w / 2) * kappa // control point offset horizontal
+  const oy = (h / 2) * kappa // control point offset vertical
+  const xe = x + w           // x-end
+  const ye = y + h           // y-end
+  const xm = x + w / 2       // x-middle
+  const ym = y + h / 2       // y-middle
 
   if (color) {
-    ctx.strokeStyle = color;
+    ctx.strokeStyle = color
   }
-  ctx.beginPath();
-  ctx.moveTo(x, ym);
-  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y);
-  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym);
-  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye);
-  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym);
-  fillColor = fillColor || color;
+  ctx.beginPath()
+  ctx.moveTo(x, ym)
+  ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y)
+  ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym)
+  ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye)
+  ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym)
+  fillColor = fillColor || color
   if (fillColor) {
-    ctx.fillStyle = fillColor;
-    ctx.fill();
+    ctx.fillStyle = fillColor
+    ctx.fill()
   }
-  ctx.stroke();
+  ctx.stroke()
 }
 
-module.exports = renderFox;
+module.exports = renderFox
diff --git a/package.json b/package.json
index 2386d1c..d66944a 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,8 @@
   "description": "Makes Fox Faces",
   "main": "server.js",
   "scripts": {
-    "test": "mocha"
+    "test": "mocha",
+    "lint": "standard"
   },
   "repository": {
     "type": "git",
@@ -28,5 +29,8 @@
     "sharp": "^0.18.1",
     "supertest": "^3.0.0",
     "uuid": "^3.0.1"
+  },
+  "devDependencies": {
+    "standard": "^8.6.0"
   }
 }
diff --git a/run.js b/run.js
index b489db8..e189159 100644
--- a/run.js
+++ b/run.js
@@ -1,13 +1,13 @@
-const cluster = require('express-cluster');
-const app = require('./server.js');
+const cluster = require('express-cluster')
+const app = require('./server.js')
 
-const activePort = process.env.PORT || 3000;
+const activePort = process.env.PORT || 3000
 
 cluster((worker) => {
-    app.listen(activePort, () => {
-        console.log('worker ' + worker.id + ' is listening on port ' + activePort);
-    });
+  app.listen(activePort, () => {
+    console.log('worker ' + worker.id + ' is listening on port ' + activePort)
+  })
 }, {
-    'respawn': true, // workers will restart on failure
-    'verbose': true, // logs what happens to console
-});
+  'respawn': true, // workers will restart on failure
+  'verbose': true // logs what happens to console
+})
diff --git a/server.js b/server.js
index 912edb4..53bed90 100644
--- a/server.js
+++ b/server.js
@@ -1,42 +1,44 @@
+/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "newrelic" }] */
+
 try {
-  const newrelic = require('newrelic');
+  const newrelic = require('newrelic')
 } catch (e) {
-  console.error("WARNING unable to load newrelic")
+  console.error('WARNING unable to load newrelic')
 }
 
-const express = require('express');
-const uuid = require('uuid/v4');
-const sanitize = require('sanitize-filename');
-const Canvas = require('canvas');
+const express = require('express')
+const uuid = require('uuid/v4')
+const sanitize = require('sanitize-filename')
+const Canvas = require('canvas')
 
-const Fox = require('./js/fox.js');
-const renderFox = require('./js/render-fox.js');
+const Fox = require('./js/fox.js')
+const renderFox = require('./js/render-fox.js')
 
-function composeImage(width, height, seed) {
-    seed = seed || uuid();
-    const fox = Fox(width, height, seed);
-    const canvas = new Canvas(width, height);
-    renderFox(canvas, fox);
-    return canvas;
+function composeImage (width, height, seed) {
+  seed = seed || uuid()
+  const fox = Fox(width, height, seed)
+  const canvas = new Canvas(width, height)
+  renderFox(canvas, fox)
+  return canvas
 };
 
-const cacheTimeout = 60 * 60 * 24 * 30;
-const app = express();
+const cacheTimeout = 60 * 60 * 24 * 30
+const app = express()
 
 app.get('/healthcheck', (req, res) => {
-    res.status(200).end();
-});
+  res.status(200).end()
+})
 
 app.get('/:width/:seed', (req, res) => {
-    let width = parseInt(req.params.width) || 400;
-    if (width > 400) width = 400;
-    const seed = sanitize(req.params.seed) || uuid();
-    const canvas = composeImage(width, width, seed);
-    const buffer = canvas.toBuffer();
-    res.set('Cache-Control', 'max-age=' + cacheTimeout);
-    res.set('Content-length', buffer.length);
-    res.type('png');
-    res.end(buffer, 'binary');
-});
+  let width = parseInt(req.params.width) || 400
+  if (width > 400) width = 400
+  const seed = sanitize(req.params.seed) || uuid()
+  const canvas = composeImage(width, width, seed)
+  const buffer = canvas.toBuffer()
+  res.set('Cache-Control', 'max-age=' + cacheTimeout)
+  res.set('Content-length', buffer.length)
+  res.type('png')
+  res.end(buffer, 'binary')
+})
 
-module.exports = app;
+module.exports = app