Buick Not So Pee Wee Football

Post pobrano z: Buick Not So Pee Wee Football

Buick’s 2017 Super Bowl advertising campaign “Not So Pee Wee Football”, features NFL most valued player Cam Newton and supermodel Miranda Kerr alongside two teams of Pee Wee football players and their supporters. The Buick Not So Pee Wee Football spot takes place at a Pee Wee football game where two dads are in the stands watching their kids play. As a Buick Sport Red Cascada ST pulls into the parking lot, one of the men says, “Check out that Buick!” with delight. The other dad says, “If that’s a Buick, then my kid is Cam Newton.” The football game, of course, picks up with a new injection of muscle and experience. A Buick Encore SUV arrives toward the end of the commercial, with the coach of the “Sharks” saying, “If that’s a Buick, then I’m a supermodel.” He then turns into Kerr. The campaign, online at buick.com/biggame, is designed to reset expectations about Buick’s modern vehicles, particularly the Encore SUV and Cascada convertible and provokes viewers with its “That’s a Buick?” theme.

Buick Not So Pee Wee Football

“Buick is experiencing unprecedented sales success and consumer awareness backed by remarkable third-party quality and reliability validation,” said Duncan Aldred, vice president of Global Buick Sales, Service and Marketing. “Our latest vehicles like the Encore and Cascada belong in the spotlight on a global stage only the Super Bowl can offer.”

“Every time I take the field, I aim to shatter traditional expectations of the quarterback position,” said Newton. “Buick’s doing the same thing with this ad, and I think everyone watching will love it. It was so fun going back to the Pee Wee field with such great kids.”.

Buick Not So Pee Wee Football Credits

The Buick Not So Pee Wee Football campaign was developed at Engage M-1 / Leo Burnett Detroit, by creative directors Steve Glinski, Tim Thomas, Christopher Handyside, associate creative director/art director Stephen Kerry, associate creative director/copywriter Matt Perry, group account directors Brian McCallum and Yanlin Sun, director if integrated production Brian Dooley, executive producer Tom Hillebrand.

Filming was shot by director Erich Joiner via Tool of North America.

Editor was Paul Martinez at Arcade Edit with executive producer Crissy DeSimone, managing partner Damian Stevens, head of production Kirsten Thon-Webb, senior producer Rebecca Jameson and assistant editor Pete D’Andrea.

Visual effects were produced at Timber by creative directors Jonah Hall and Kevin Lau, executive producer Sabrina Elizondo, senior producer Megan Kennedy, lead Flame artist Christopher DeCristo, Flame artist Mark Loso, Flame assistant Austin Lewis, nuke artists Nick Hiegel, Eric Almeras, Robert Williams, Eduardo Anton. CG tracking was done at Match the Motion LLC by Matthew Merkovich. Rotoscoping was done at Rotomaker LLC. Colour was produced at Shed.

Sound was produced at Eleven Sound by sound designer and mixer Jeff Payne, executive producer Melissa Elston, assistant mixers Jordan Meltzer and AJ Murrillo.

84 Lumber Journey

Post pobrano z: 84 Lumber Journey

84 Lumber, a building materials supply company based in Pennsylvania, is using the Super Bowl to run a controversial television commercial featuring Mexican immigrants. A young girl travels with her mother on foot as they head towards the Mexico USA border. As they travel the girl collects red white and blue pieces of fabric. 84 Lumber’s Super Bowl spot is the launch of a national recruiting campaign for the company’s management training program. The 84 Lumber Journey campaign, online at journey84.com, is targeting males’ ages 20 to 29 that want to take control of their careers and embody the entrepreneurial spirit that runs rampant at 84 Lumber.

Viewing scene in 84 Lumber Journey commercial

Chief Creative Officer Rob Schapiro talks about the commercial.

Director Cole Webley speaks about the controversial 84 Lumber Super Bowl commercial.

“For 60 years, this has been a company defined by its people, entrepreneurs who see opportunity where others don’t,” said Maggie Hardy Magerko, 84 Lumber owner and president. “Our next 60 years will be no different. That’s why we’re casting a wider net; we want the world to know 84 Lumber is the place for people who don’t always fit nicely into a box.”

“Our industry is going through a period of extreme disruption,” Hardy Magerko continues. “And I’ve always preferred to be the one doing the disrupting, rather than the one being disrupted. But to do that, we need to hire and train people differently. We don’t need more people interested in doing the same thing that’s always been done. We need more people interested in creating their own path for themselves and for 84 Lumber.”

Carton in Twitter promotion for 84 Lumber Journey commercial
Fortune favours the brave - Twitter promotion for 84 Lumber Journey commercial
Take the journey - Twitter promotion for 84 Lumber Journey commercial
Some stories need to be told - Twitter promotion for 84 Lumber Journey commercial
No detail too small - Twitter promotion for 84 Lumber Journey commercial

84 Lumber Journey Credits

The 84 Lumber Journey campaign was developed at Brunner, Pittsburgh, by creative director Dave Vissat, chief creative officer Rob Schapiro, associate creative directors Derek Julin, Kevin Corfield, chief client officer Jeff Maggs, account director Lauren Tedesco, senior account manager Dana Lucas, associate broadcast director Kathy Baldauf, with Fixer Partners executive producers John Noble and Brad Powell.

Filming was shot by director Cole Webley via Sanctuary with director of photography Justin Brown, creative director Matt Wilson, line producer Christopher Cho, executive producer Preston Lee, heads of production Adam Litt, Leopoldo Luisetti, and production designer Christopher Lagunes.

Editor was Jeff Buchanan at Final Cut with executive producer Sarah Roebuck, producer Penny Ensley, head of production Jen Sienkwicz, assistant editor Geoff Hastings and cutting assistant Andre Castiglioni.

Visual effects were produced at Method Studios by executive producer Stuart Robinson, CG supervisor Boaz Livny, VFX supervisor Eliza Pelham Randall, Flame artists Stephen Morris and Jared Pollack, senior VFX producer Bennett Lieber.

Color was graded at Company 3 by colourist Tom Poole.

Sound was produced at Heard City by sound mixer Phil Loeb.

Music was produced Future Perfect by composer Victor Magro and producer Max Gosling.

84 Lumber Journey

Post pobrano z: 84 Lumber Journey

84 Lumber, a building materials supply company based in Pennsylvania, is using the Super Bowl to run a controversial television commercial featuring Mexican immigrants. A young girl travels with her mother on foot as they head towards the Mexico USA border. As they travel the girl collects red white and blue pieces of fabric. 84 Lumber’s Super Bowl spot is the launch of a national recruiting campaign for the company’s management training program. The 84 Lumber Journey campaign, online at journey84.com, is targeting males’ ages 20 to 29 that want to take control of their careers and embody the entrepreneurial spirit that runs rampant at 84 Lumber.

Viewing scene in 84 Lumber Journey commercial

Chief Creative Officer Rob Schapiro talks about the commercial.

Director Cole Webley speaks about the controversial 84 Lumber Super Bowl commercial.

“For 60 years, this has been a company defined by its people, entrepreneurs who see opportunity where others don’t,” said Maggie Hardy Magerko, 84 Lumber owner and president. “Our next 60 years will be no different. That’s why we’re casting a wider net; we want the world to know 84 Lumber is the place for people who don’t always fit nicely into a box.”

“Our industry is going through a period of extreme disruption,” Hardy Magerko continues. “And I’ve always preferred to be the one doing the disrupting, rather than the one being disrupted. But to do that, we need to hire and train people differently. We don’t need more people interested in doing the same thing that’s always been done. We need more people interested in creating their own path for themselves and for 84 Lumber.”

Carton in Twitter promotion for 84 Lumber Journey commercial
Fortune favours the brave - Twitter promotion for 84 Lumber Journey commercial
Take the journey - Twitter promotion for 84 Lumber Journey commercial
Some stories need to be told - Twitter promotion for 84 Lumber Journey commercial
No detail too small - Twitter promotion for 84 Lumber Journey commercial

84 Lumber Journey Credits

The 84 Lumber Journey campaign was developed at Brunner, Pittsburgh, by creative director Dave Vissat, chief creative officer Rob Schapiro, associate creative directors Derek Julin, Kevin Corfield, chief client officer Jeff Maggs, account director Lauren Tedesco, senior account manager Dana Lucas, associate broadcast director Kathy Baldauf, with Fixer Partners executive producers John Noble and Brad Powell.

Filming was shot by director Cole Webley via Sanctuary with director of photography Justin Brown, creative director Matt Wilson, line producer Christopher Cho, executive producer Preston Lee, heads of production Adam Litt, Leopoldo Luisetti, and production designer Christopher Lagunes.

Editor was Jeff Buchanan at Final Cut with executive producer Sarah Roebuck, producer Penny Ensley, head of production Jen Sienkwicz, assistant editor Geoff Hastings and cutting assistant Andre Castiglioni.

Visual effects were produced at Method Studios by executive producer Stuart Robinson, CG supervisor Boaz Livny, VFX supervisor Eliza Pelham Randall, Flame artists Stephen Morris and Jared Pollack, senior VFX producer Bennett Lieber.

Color was graded at Company 3 by colourist Tom Poole.

Sound was produced at Heard City by sound mixer Phil Loeb.

Music was produced Future Perfect by composer Victor Magro and producer Max Gosling.

How to Create Flat Design Headphones in Adobe Illustrator

Post pobrano z: How to Create Flat Design Headphones in Adobe Illustrator

Final product image
What You’ll Be Creating

I love headphones, and this tutorial is inspired by the Audiotechnica M50X. As you’ll see, we’ll be creating this with basic shapes in Adobe Illustrator. So if you’re a lover of headphones and good music, this tutorial is for you!

Get inspiration from the many flat design vector illustrations over on GraphicRiver.

Let’s start!

1. How to Create a New Document and Set Up a Grid

Press Control-N to make a New Document. Set the Units to Pixels, and enter 800 x 600 for the width and height of the document. Then in the Advanced options, select RGBScreen (72 ppi), and make sure to activate the Align New Objects to Pixel Grid box before clicking OK.

Activate the Grid (View > Show Grid) and Snap to Grid (View > Snap to Grid). You’ll need a grid every 10 px, so simply press Control-K to go to Preferences, and in Guides & Grid set Gridline every to 10 and Subdivisions to 4. Don’t worry—the grid will help you work in an easy way, and it can also be enabled or disabled by pressing the keyboard shortcut Control-„.

You can activate the Info panel (Window > Info) in order to have a preview of the size and position of your shapes. Remember to set the measuring unit to Pixels from Edit > Preferences > Units. This will greatly increase the speed of your work.

Set Up a new document of 800 x 600 px set the Grid and Units to Pixels

2. How to Create the Headphones

First things first—let’s start with one earpad so we can
duplicate it and then create the headband for our headphones. Make sure to turn on the Grid so that you can work with greater precision and ease.

Step 1

Start by creating the earpad with a 46 x 132 px rectangle using the
Rectangle Tool (M). Select #84EDFF as the fill color and no color for the stroke fill.

In the Transform panel, enter 14 px as the right-side corner
radius and 2 px as the left-side corner radius.

A 46 x 132 px rectangle with round corners in the Transform panel

Step 2

Duplicate the rectangle (Control-C > Control-F)
and change its Width to 36 px with the Selection Tool (V). Select #40BDD1 as the fill color and change the right-side corner radius to 10 px.

Setting the Width to 36 px with Selection Tool

Step 3

Duplicate the last rectangle (Control-C > Control-F) and change its Width to 24 px. Select #47D2E9 as the fill color and change the left-side corner radius to 6 px.

Duplicating the rectangle and changing its width

Step 4

Next to the earpad, create the speaker base
using a 4 x 128 px rectangle, and use #5B5B5F as the fill color; then set the right-side corner radius to 2 px.

Adding a base for the earpad using a 4 x 128 px rectangle

Step 5

Now create the housing using a 24 x 80 px rectangle. Select #363434 as the fill color and change
the left-side corner radius to 2 px

Adding a housing of 24 x 80 px rectangle

Step 6

Add some depth to the housing duplicating
(Control-C > Control-F) the previous rectangle and changing its Height to 58 px.
Change the fill color to #3B3939.

Duplicating the rectangle and changing its width from Transform panel

Step 7

Repeat the previous step and change the
rectangle’s Height to 50 px. Change the fill color to #444242.

Repeating the previous step

Step 8

Now create the support for the speaker’s hinge
using a 20 x 16 px rectangle. Select #4D4A4A as the fill color and change the left side radius to 8 px.

Duplicate the rectangle (Control-C > Control-F)
and move 2 px downwards using the arrow of your keyboard. Change the fill color
to #3B3B3B and send it backwards
(Object > Arrange > Send Backward).

Adding the support for the speakers hinge with a 20 x 16 px rectangle

Step 9

Create a 8 x 42 px rectangle for the small headband on the speaker/housing.
Set the lower corner radius to 4 px and select #5B5B5F as the fill color. 

Duplicate it (Control-C > Control-F) and change
the fill color to #3B3B3B. Move the rectangle
downwards 2 px, and send it backwards (Object > Arrange > Send Backward).

And now a small headband on the speaker with 4 px corner radius

Step 10

Continue with the small headband using a 8 x 10
px
rectangle. Select #444242 as the fill color and place
the rectangle as shown in the image below.

Another piece small over the headband using a 8 x 10 px rectangle

Step 11

Now create a hinge using a 16 x 16 px ellipse
with the Ellipse Tool (L). Select #5B5B5F as the fill color and place the ellipse as shown in the image below.

Duplicate the ellipse and change its size to
12 x 12 px from the Transform panel. Change the fill color to #444242.

Adding a hinge with a 16 x 16 px ellipse and another of 12 x 12 px

Step 12

Continue drawing the headband’s support using
a 16 x 18 px rectangle. Change the fill color to #444242. Select chamfer corners for the lower corners and set the
radius to 4 px. Send the rectangle to the back (Object > Arrange > Send
to Back
).

The headbands support with a 16 x 18 px rectangle over the hinge

Step 13

Create a new 12 x 20 px rectangle, and select #5B5B5F as the fill color. Set the lower corner’s radius to 6 px.

Duplicate (Control-C > Control-F) the rectangle
and change the fill color to #3B3B3B. Send it backwards
(Object > Arrange > Send to Back) and move it downwards 2 px.

Another support over the hinge with a 12 x 20 px rectangle

Step 14

Create two rectangles, one of 4 x 26 px (#D8D9DD) for
the headband strap, and another one of 12 x 20 px (#5B5B5F) as the strap support.

Duplicate the first rectangle (Control-C > Control-F) and change its Height to 2 px. Change the fill color to #AEADB3

Select everything and group it together
(Control-G).

And adding a headband strap of 4 x 26 px and another support of 12 x 20 px

Step 15

Now, we’ll draw our headphones headband. Let’s begin by creating a 252 x 252 px ellipse and selecting 20 px as the stroke width.
Select #84EDFF as the stroke color and delete the ellipse’s lower anchor point with
the Direct Selection Tool (A).

Expand the stroke (Object > Expand…) and
then slightly round the headband’s lower edges with the Direct Selection Tool
(A)
.

Adding a 252 x 252 px ellipse for the headphones headband

Step 16

Duplicate the headband (Control-C > Control-F).
Set the scale to 93% (Object > Transform > Scale..). Use #47D2E9 as the fill color.

Move the duplicated headband 6 px downwards, and then select both headbands and remove the lower remaining part with the Shape
Builder Tool (Shift-M)

Some depth for the headband duplicating and change its Scale

Step 17

We are about to finish the headphones!

Now select the left speaker, duplicate it
(Control-C > Control-F) and reflect it vertically (Object > Transform >
Reflect…
). Put it just on the right side of the headband.

Duplicating the speaker on the right side of the headband

3. How to Create a Plug Cord

Now that we have finished the headphones, it’s time to draw the plug cord.
Moving on!

Step 1

Let’s start with the cable entry in the right
speaker. Draw it using a 14 x 20 px rectangle, and select #2B2A2A as the fill color.

Add another 8 x 16 px rectangle for the cable connector. Use #545252 as the fill color.

Drawing the cable entry in the right speaker for the plug cord

Step 2

Now, draw the cable with the Pen Tool (P), using 4 px as the stroke thickness. Use #47D2E9 as the stroke color.

Round all corners with the Direct Selection
Tool (A)
. Then expand the stroke shape (Object > Expand…) and press OK.

Turn off Snap to Grid for a moment
(Shift-Control-„) to align the cable with the connector.

And now drawing the cable for the headphones with the Pen Tool

Step 3

Let’s draw the jack using a 8 x 22 px rectangle
and #545252 as the fill color. Add another 2 x 8 px rectangle (#8A8686).

Add a third rectangle, this one of (#B4B5B8) 4 x 20
px,
and set 2 px chamfers in the upper corners from the Transform panel.

Finally, add two 4 x2 px rectangles (#8A8686) and
place them over the jack.

Drawing the jack connector using rectangles

4. How to Create a Background

And we are done with the plug cord, so now let’s
finish the design by creating a nice background for our headphones.

Step 1

Let’s start by creating a musical note. To do
this, use a 22 x 12 px rectangle, a 4 x 40 px rectangle and finally a 20 x 20 px
ellipse. Use #003E57 as the fill color.

Link all forms and merge them together using the
Unite button from the Pathfinder panel. Slightly round all corners with the
Direct Selection Tool (A).

Creating a musical notes for the background

Step 2

Duplicate (Control-C > Control-F) the
musical note four times, and rotate the copies and change their scales using the Selection Tool (V).
Place them as shown in the picture below.

Then group them together and flip them
vertically (Object > Transform > Reflect…) to place them on the right side of the headphone.

Duplicating musical notes in the background with Selection Tool

Step 3

Finally, create an 800 x 600 px rectangle, the same
size as the canvas. Apply a radial gradient from the Gradient panel, using the
following fill colors:

  • Color A: #1F3B54
  • Color B: #182D40

Remember to send the rectangle to the back of
the canvas (right click > Arrange > Send to Back).

Setting a radial gradient for the background of 800 x 600 px

Awesome Work, You’re Finished!

Yaaaay! We’re done! You have finished this
amazing headphones illustration! It’s an incredible result, another example
that you can achieve fun illustrations without much difficulty by using basic forms.

I hope you enjoyed this tutorial as much as I
did; hopefully, it was full of new knowledge for you. I’d like to see your
design—I’ll be waiting!

Final result

Color variations

26 Clean and Green Environmental Logos

Post pobrano z: 26 Clean and Green Environmental Logos

We only have one home, protecting it should be of utmost priority! Plenty of companies, NPO’s, and government bodies have set exactly this as their goal and mission. If you’re not convinced, hopefully this will sway you.

  • 27,000 trees are cut down each day and used for Toilet Paper.
  • Rainforests are cut down at a rate of 100 acres per minute.
  • Roughly 14 billion pounds of garbage is dumped into the ocean each year.
  • Approximately 46% of the lakes in America are extremely polluted making them risky for swimming, fishing and aquatic life.
  • Every year around one trillion gallons of untreated sewage and industrial waste is dumped in the U.S water.
  • Almost 80% of urban waste in India is dumped in the river Ganges.
  • A single car generates half a ton of CO2 and a NASA space shuttle releases 28 tons of C02.
  • It takes only 5 days for a jet stream in China to carry the air pollution to the United States.
  • Pollution in China can change the weather in United States.
  • There are more around 73 various kinds of pesticides in the groundwater, which is used as drinking water.

[source:Conserve Energy Future.]

In hindsight, we all should be playing our part, but cheers to those who are acting to make a difference.

I’ve put together a collection of 26 clean and green environmental related logos for your inspiration. Enjoy!

Credit to respective artists.


credit:Alfrey Davilla | vaneltia

credit:Matt Yow

credit:Liv Elinor

credit:Cody Petts

credit:Isaac Grant

credit:Breno Bitencourt

credit:Dimitrije Mikovic

credit:trinitiff

credit:Nick Signet

credit:trinitiff

credit:Stephen MacEachern

credit:Matt Cameron

credit:Nikhil Singh

credit:Charles Aroutiounian

credit:Matt Cameron

credit:Paul J. Bartlett

credit:Diana Arizmendi

credit:Becca Dalke

credit:Tom Frew

credit:ASK Dziner

credit:Mohiuddin Parekh

credit:Jordan Frank

credit:Carlos Sosa

credit:Freddy Tejeda

credit:Sarah Croughwell

credit:Laura Santos


Conclusion

The thought that our earth is our only option (unless Elon Musk figures our Mars) should be motivation enough to really commit to keeping our home clean. If everyone does their part, we should see a dramatic difference within the near future.

I hope that this collection of environmental related logos has inspired you! Thanks for stopping by!


What Really Makes a Static Site Generator?

Post pobrano z: What Really Makes a Static Site Generator?

I talk a lot about static site generators, but always about using static site generators. In most cases, it may seem like a black box. I create a template and some Markdown and out comes a fully formed HTML page. Magic!

But what exactly is a static site generator? What goes on inside that black box? What kind of voodoo is this?

In this post, I want to explore all of the parts that make up a static site generator. First, we’ll discuss these in a general fashion, but then we’ll take a closer look at some actual code by delving deep inside HarpJS. So, put your adventurer’s cap on and let’s start exploring.

Why Harp? For two reasons. The first is that HarpJS is, by design, a very simple static site generator. It doesn’t have a lot of the features that might cause us to get lost exploring a more comprehensively full-featured static site generator (like Jekyll for instance). The second, much more practical, reason is that I know JavaScript and don’t know Ruby very well.

The Basics of a Static Site Generator

The truth is, a static site generator is a pretty simple concept. The key ingredients to a static site generator are typically:

  • A template language(s) for creating page/post templates
  • A lightweight markup language (typically Markdown) for authoring content
  • A structure and markup (often YAML) for providing configuration and metadata (e.g. „front matter„)
  • A set of rules or structure for organizing and naming files that are exported/compiled, files that are not and how these files will be handled (e.g. frequently prefacing a file or folder with an underscore means that it is not exported into the final site files or all posts go in a posts folder)
  • A means of compiling templates and markup into HTML (frequently support for CSS or JavaScript preprocessors is also included)
  • A local server for testing.

That’s it. If you’re thinking, „Hey… I could build that!” you are probably correct. Things start to get complicated though when you start to expand the functionality, as most static site generators do.

So, let’s look at how Harp handles this.

Getting to the Harp of the Matter

Let’s look at the basics of how Harp handles the key ingredients described above. Harp offers more than this handful of functionality, but, for the sake of our examination, we’ll stick to those items.

First, let’s discuss the basics of Harp.

Harp Basics

Harp supports Jade and EJS (for templating) and Markdown as its lightweight markup language (for content). Note that while Jade is now called Pug, Harp has not officially transitioned in their documentation or code, so we’ll stick with Jade here. Harp also offers support for other preprocessing such as Less, Sass, and Stylus for CSS and CoffeeScript for JavaScript.

By default Harp does not require much in the way of configuration or metadata. It tends to favor convention over configuration. However, it allows for specific metadata and configuration using JSON. It differs from many other static site generators in that file metadata is contained outside of the actual file within a `_data.json` file.

While it is configurable to a degree, Harp has certain established guidelines for how to structure files. For example, in a typical application, the files that are served fall within a public directory. Also, any file or folder prefaced by an underscore will not be served.

Lastly, Harp offers a basic local web server for testing that includes some configurable options. And, of course, it will compile the finished HTML, CSS and JavaScript files for deployment.

Let’s Look at Harp’s Actual Source Code

Since much of what makes a static site generator are rules and conventions, the code centers around the actual serving and compiling (for the most part). Let’s dig in.

The Server Function

In Harp, serving your project is usually done by executing harp server from the command line. Let’s look at the code for that function:

exports.server = function(dirPath, options, callback){
  var app = connect()
  app.use(middleware.regProjectFinder(dirPath))
  app.use(middleware.setup)
  app.use(middleware.basicAuth)
  app.use(middleware.underscore)
  app.use(middleware.mwl)
  app.use(middleware.static)
  app.use(middleware.poly)
  app.use(middleware.process)
  app.use(middleware.fallback)

  return app.listen(options.port || 9966, options.ip, function(){
    app.projectPath = dirPath
    callback.apply(app, arguments)
  })
}

While the function looks simple, obviously there is a ton going on within middleware that isn’t illustrated here.

The rest of this function opens up a server with the options you specify (if any). Those options include a port, an IP to bind to and a directory. By default the port is 9000 (not 9966 as you might guess by the code), the directory is the current one (i.e. the one Harp is running in) and the IP is 0.0.0.0.

The details for these defaults are in the command line application source.

The Compiler Function

Staying within index.js, let’s take a look at the compile function next.

exports.compile = function(projectPath, outputPath, callback){

  /**
   * Both projectPath and outputPath are optional
   */

  if(!callback){
    callback   = outputPath
    outputPath = "www"
  }

  if(!outputPath){
    outputPath = "www"
  }


  /**
   * Setup all the paths and collect all the data
   */

  try{
    outputPath = path.resolve(projectPath, outputPath)
    var setup  = helpers.setup(projectPath, "production")
    var terra   = terraform.root(setup.publicPath, setup.config.globals)
  }catch(err){
    return callback(err)
  }


  /**
   * Protect the user (as much as possible) from compiling up the tree
   * resulting in the project deleting its own source code.
   */

  if(!helpers.willAllow(projectPath, outputPath)){
    return callback({
      type: "Invalid Output Path",
      message: "Output path cannot be greater then one level up from project path and must be in directory starting with `_` (underscore).",
      projectPath: projectPath,
      outputPath: outputPath
    })
  }


  /**
   * Compile and save file
   */

  var compileFile = function(file, done){
    process.nextTick(function () {
      terra.render(file, function(error, body){
        if(error){
          done(error)
        }else{
          if(body){
            var dest = path.resolve(outputPath, terraform.helpers.outputPath(file))
            fs.mkdirp(path.dirname(dest), function(err){
              fs.writeFile(dest, body, done)
            })
          }else{
            done()
          }
        }
      })
    })
  }

  /**
   * Copy File
   *
   * TODO: reference ignore extensions from a terraform helper.
   */
  var copyFile = function(file, done){
    var ext = path.extname(file)
    if(!terraform.helpers.shouldIgnore(file) && [".jade", ".ejs", ".md", ".styl", ".less", ".scss", ".sass", ".coffee"].indexOf(ext) === -1){
      var localPath = path.resolve(outputPath, file)
      fs.mkdirp(path.dirname(localPath), function(err){
        fs.copy(path.resolve(setup.publicPath, file), localPath, done)
      })
    }else{
      done()
    }
  }

  /**
   * Scan dir, Compile Less and Jade, Copy the others
   */

  helpers.prime(outputPath, { ignore: projectPath }, function(err){
    if(err) console.log(err)

    helpers.ls(setup.publicPath, function(err, results){
      async.each(results, compileFile, function(err){
        if(err){
          callback(err)
        }else{
          async.each(results, copyFile, function(err){
            setup.config['harp_version'] = pkg.version
            delete setup.config.globals
            callback(null, setup.config)
          })
        }
      })
    })
  })

}

The first portion defines the output path as specified by the call to harp compile via the command line (source here). The default, as you can see, is www. The callback is a callback function passed by the command line utility which is not configurable.

The next part starts by calling the setup function in the helpers module. For the sake of brevity, we won’t go into the specific code of the function (feel free to look for yourself), but essentially it reads the site configuration (i.e. harp.json).

You may also notice a call to something called terraform. This will come up again within this function. Terraform is actually a separate project required by Harp that is the basis of its asset pipeline. The asset pipeline is where the hard work of compiling and building the finished site gets done (we’ll look at Terraform code in a little bit).

The next portion of code, as it states, tries to prevent you from specifying an output directory that would inadvertently overwrite your source code (which would be bad as you’d lose any work since your last commit).

The compileFile and copyFile functions are fairly self-explanatory. The compileFile function relies on Terraform to do the actual compilation. Both of these functions drive the prime function which uses a helper function (fs) to walk the directories, compiling or copying files as necessary in the process.

Terraform

As I discussed, Terraform does the grunt work for compiling the Jade, Markdown, Sass and CoffeeScript into HTML, CSS and JavaScript (and assembling these pieces as defined by Harp). Terraform is made up of a number of files that define its processors for JavaScript, CSS/stylesheets, and templates (which, in this case, includes Markdown).

Within each of these folders is a processors folder that contains the code for each specific processor that Terraform (i.e. Harp) supports. For example, in the templates folder are files that form the basis for compiling EJS, Jade, and Markdown files.

I won’t delve into the code for each of these, but, for the most part, they rely upon external npm modules that handle the supported processor. For example, for Markdown support, it depends upon Marked.

The core logic of Terraform is contained in its render function.

/**
    * Render
    *
    * This is the main method to to render a view. This function is
    * responsible to for figuring out the layout to use and sets the
    * `current` object.
    *
    */

render: function(filePath, locals, callback){

    // get rid of leading slash (windows)
    filePath = filePath.replace(/^\\/g, '')

    // locals are optional
    if(!callback){
    callback = locals
    locals   = {}
    }


    /**
    * We ignore files that start with underscore
    */

    if(helpers.shouldIgnore(filePath)) return callback(null, null)


    /**
    * If template file we need to set current and other locals
    */

    if(helpers.isTemplate(filePath)) {

    /**
        * Current
        */
    locals._ = lodash
    locals.current = helpers.getCurrent(filePath)


    /**
        * Layout Priority:
        *
        *    1. passed into partial() function.
        *    2. in `_data.json` file.
        *    3. default layout.
        *    4. no layout
        */

    // 1. check for layout passed in
    if(!locals.hasOwnProperty('layout')){

        // 2. _data.json layout
        // TODO: Change this lookup relative to path.
        var templateLocals = helpers.walkData(locals.current.path, data)

        if(templateLocals && templateLocals.hasOwnProperty('layout')){
        if(templateLocals['layout'] === false){
            locals['layout'] = null
        } else if(templateLocals['layout'] !== true){

            // relative path
            var dirname = path.dirname(filePath)
            var layoutPriorityList = helpers.buildPriorityList(path.join(dirname, templateLocals['layout'] || ""))

            // absolute path (fallback)
            layoutPriorityList.push(templateLocals['layout'])

            // return first existing file
            // TODO: Throw error if null
            locals['layout'] = helpers.findFirstFile(root, layoutPriorityList)

        }
        }

        // 3. default _layout file
        if(!locals.hasOwnProperty('layout')){
        locals['layout'] = helpers.findDefaultLayout(root, filePath)
        }

        // 4. no layout (do nothing)
    }

    /**
        * TODO: understand again why we are doing this.
        */

    try{
        var error  = null
        var output = template(root, templateObject).partial(filePath, locals)
    }catch(e){
        var error  = e
        var output = null
    }finally{
        callback(error, output)
    }

    }else if(helpers.isStylesheet(filePath)){
    stylesheet(root, filePath, callback)
    }else if(helpers.isJavaScript(filePath)){
    javascript(root, filePath, callback)
    }else{
    callback(null, null)
    }

}

(If you were reading all this code closely, you likely noticed TODO’s, typos, and even a funny „understand again why we are doing this” comment. That’s real life coding!)

The majority of the code in the render function is about handling templates. Things like CoffeeScript and Sass fundamentally render on a one-to-one basis. For example, style.scss will render to style.css. Even if it has includes, that is handled by the renderer. The very end of the render function deals with these types of files.

Layouts in Harp, on the other hand, are nested within each other in a variety of manners that can even depend upon configuration. For example, about.md might be rendered within the default _layout.jade (where, exactly, is determined by the use of != yield within that layout). However, _layout.jade might include multiple other layouts within itself by way of the partial support in Harp.

Partials are a way of splitting up a template into multiple files. They are especially useful for code reuse. For instance, I might put the site header inside a partial. Partials are important for making layouts within a static site generator maintainable but they also add a good deal of complexity to the logic of compiling templates. This complexity is handled within the partial function of the templates processor.

Finally, you could override the default layout by specifying a specific layout or no layout at all for a particular file within the _data.json configuration file. All of these scenarios are handled (and even numbered) within the logic of the render function.

That’s Not So Complicated, Is It?

To make this digestible, I’ve skipped over a ton of additional detail. At its core, every static site generator I’ve ever used (and I’ve used a bunch) functions similarly: a set of rules, conventions, and configuration that is run through compilers for the various supported markups. Perhaps that is why there are a ridiculous number of static site generators out there.

That being said, I wouldn’t want to build my own!

My Report & Book

If you are interested in learning how to build sites using a static site generator, I’ve authored a report and co-authored a book for O’Reilly that might interest you. My report, simply titled Static Site Generators is free and attempts to establish the history, landscape, and basics behind static site generators.

The book that I co-authored with Raymond Camden is called Working with Static Sites and is available as an early release, but should be available in print soon.


What Really Makes a Static Site Generator? is a post from CSS-Tricks