We are assuming you have node installed!

Similar documents
Client Side JavaScript and AJAX

Interactive Web Application

What is Node.js? Tim Davis Director, The Turtle Partnership Ltd

Hands-on Lab Session 9011 Working with Node.js Apps in IBM Bluemix. Pam Geiger, Bluemix Enablement

Django urls Django Girls Tutorial

BEGINNER PHP Table of Contents

Persistence & State. SWE 432, Fall 2016 Design and Implementation of Software for the Web

Tools. SWE 432, Fall Design and Implementation of Software for the Web

Node.js. Node.js Overview. CS144: Web Applications

NODE.JS SERVER SIDE JAVASCRIPT. Introduc)on Node.js

Ruby on Rails Welcome. Using the exercise files

CS193X: Web Programming Fundamentals

Arduino IDE Friday, 26 October 2018

Microservices with Node.js

Backend Development. SWE 432, Fall Web Application Development

Chrome if I want to. What that should do, is have my specifications run against four different instances of Chrome, in parallel.

CSCU9B2 Practical 1: Introduction to HTML 5

Building a Django Twilio Programmable Chat Application

welcome to BOILERCAMP HOW TO WEB DEV

Dreamweaver Website 1: Managing a Website with Dreamweaver

mismatch between what is maybe possible today and what is going on in many of today's IDEs.

Persistence. SWE 432, Fall 2017 Design and Implementation of Software for the Web

Web Application Development

An attribute used in HTML that is used for web browsers screen reading devices to indicate the presence and description of an image Module 4

Backend Development. SWE 432, Fall 2017 Design and Implementation of Software for the Web

CS Multimedia and Communications REMEMBER TO BRING YOUR MEMORY STICK TO EVERY LAB!

c122jan2714.notebook January 27, 2014

Serverless Single Page Web Apps, Part Four. CSCI 5828: Foundations of Software Engineering Lecture 24 11/10/2016

Catbook Workshop: Intro to NodeJS. Monde Duinkharjav

Exercise 1. Bluemix and the Cloud Foundry command-line interface (CLI)

CSS BASICS. selector { property: value; }

Lab 1 - Introduction to Angular

Using X-Particles with Team Render

Lesson 1: Writing Your First JavaScript

Dreamweaver CS6. Table of Contents. Setting up a site in Dreamweaver! 2. Templates! 3. Using a Template! 3. Save the template! 4. Views!

Programming Lab 1 (JS Hwk 3) Due Thursday, April 28

Challenge: Working with the MIS2402 Template

I'm Andy Glover and this is the Java Technical Series of. the developerworks podcasts. My guest is Brian Jakovich. He is the

Week - 01 Lecture - 04 Downloading and installing Python

IERG Tutuorial 5. Benedict Mak

Getting started with Tabris.js Tutorial Ebook

Setting up a ColdFusion Workstation

Adafruit WebIDE. Created by Tyler Cooper. Last updated on :29:47 PM UTC

Clearing Your Browser Cache in: Internet Explorer 7 or 8

Web API Lab. The next two deliverables you shall write yourself.

Linked Lists. What is a Linked List?

Human-Computer Interaction Design

Quick.JS Documentation

Android Programming Family Fun Day using AppInventor

CSc 337 LECTURE 16: WRITING YOUR OWN WEB SERVICE

PROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between

Reading How the Web Works

Dreamweaver Basics Workshop

Ionic Tutorial. For Cross Platform Mobile Software Development

ADOBE DREAMWEAVER CS4 BASICS

Title: Jan 29 11:03 AM (1 of 23) Note that I have now added color and some alignment to the middle and to the right on this example.

TDDC88 Lab 4 Software Configuration Management

IBM Watson Solutions Business and Academic Partners

In our first lecture on sets and set theory, we introduced a bunch of new symbols and terminology.

About the Tutorial. Audience. Prerequisites. Copyright & Disclaimer. Laravel

Hello World! Computer Programming for Kids and Other Beginners. Chapter 1. by Warren Sande and Carter Sande. Copyright 2009 Manning Publications

USING DRUPAL. Hampshire College Website Editors Guide

Contents. What's New. Dropbox / OneDrive / Google drive Warning! A couple quick reminders:

Introduction to Express.js. CSC309 Feb. 6, 2015 Surya Nallu

Bitnami Ruby for Huawei Enterprise Cloud

Chris' Makefile Tutorial

Lesson 1 using Dreamweaver CS3. To get started on your web page select the link below and copy (Save Picture As) the images to your image folder.

Lab 4: create a Facebook Messenger bot and connect it to the Watson Conversation service

JQuery and Javascript

Bitnami MEAN for Huawei Enterprise Cloud

Figure 1-1. When we finish Part 2, our server will be ready to have workstations join the domain and start sharing files. Now here we go!

Each class (which we will talk about in the next section) you see in an Ionic application will

MITOCW watch?v=0jljzrnhwoi

Dynamism and Detection

CS193X: Web Programming Fundamentals

BlueMix Hands-On Workshop Lab A - Building and Deploying BlueMix Applications

Part 3: Images & form styling NOMZAMO S WEBSITE

This guide is intended to help the un-experienced in PHP in particularly Phpvms to easily install and use this freeware software.

FileWave 10 Webinar Q&A

The Stack, Free Store, and Global Namespace

XBMC. Ultimate Guide. HenryFord 3/31/2011. Feel free to share this document with everybody!

Slide 1 CS 170 Java Programming 1 Testing Karel

Introduction to Git and GitHub for Writers Workbook February 23, 2019 Peter Gruenbaum

Guides SDL Server Documentation Document current as of 04/06/ :35 PM.

Read Source Code the HTML Way

AngularJS Intro Homework

Physics REU Unix Tutorial

Installing and Configuring the Voice UPB Bridge updated 1-Jan-2019

Siteforce Pilot: Best Practices

Café Soylent Green Chapters 4

Learn Gulp. Jonathan Birkholz. This book is for sale at This version was published on

ChartJS Tutorial For Beginners

New to the Mac? Then start with this lesson to learn the basics.

Google Earth: Significant Places in Your Life Got Maps? Workshop June 17, 2013

JS Lab 1: (Due Thurs, April 27)

What's the Slope of a Line?

Monitoring Apache Tomcat Servers With Nagios XI

The Structure of the Web. Jim and Matthew

CAL 9-2: Café Soylent Green Chapter 12

CSE 115. Introduction to Computer Science I

Transcription:

Node.js Hosting

We are assuming you have node installed! This lesson assumes you've installed and are a bit familiar with JavaScript and node.js. If you do not have node, you can download and install it from http://nodejs.org.

Node has built-in web server capabilities First lets make a new workspace directory for our project. We can call it nodeserver and it will be the root folder. Now lets make our server JavaScript file, call it server.js and put the following code in it: var http = require('http'); var port = 1337; http.createserver(function (req, res) { res.writehead(200, {'Content-Type': 'text/plain'}); res.end('hello World!'); }).listen(port, '127.0.0.1'); console.log('running server'); console.log('access locally at http://localhost:'+port); console.log('to stop server and return to command line, press ctrl+c');

To run the web server, navigate to your root directory in the command prompt (hint, you can get the full path by right clicking on your server.js file and selecting "properties". It will be listed somewhere under location. $ cd /Users/aaron/Workspace/nodeserver Then simply use the node command to execute our server.js code. $ node server.js You should see that the server is now running (as well as instructions on how to stop it) because of the helpful log statements we put in our code. Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c Now go ahead and connect to your web server using a browser! Open one up and navigate to where it says, which is: http://localhost:1337.

Look at our web server talking to the browser!

The package.json file is a general outline of the parts of a node application So thats great, but seemed a bit complicated. We don't want to write http headers or even know what they mean! We also don't want to have to put all our html in a JavaScript string. Let's build a web server that can serve up the HTML files we write! The combination of this is called a web application, or web app for short. We'll get started by setting up a special file called package.json. This is a general outline of the information of our web application. Its format is a JavaScript object represented in JavaScript Object Notation (JSON), with all properties and values surrounded by double quotes. Create the file and we'll populate it with a couple of minimal properties to start. { "name": "MyAwesomeWebsite", "version": "0.0.1", "main": "server.js" } Here we are starting out by saying our website is awesome, it's the first version, and the main file is server.js.

The package.json file can specify external modules to use Now lets use this package file to add an external module we want to use! Modules are extra pieces of code others (or yourself) have written that can plugged into your program. We will use expressjs, a full featured web application module. Lets go ahead and add the express module as a dependency in our package.json. Old JSON is in black, new JSON in green. Don't forget the comma we need after "server.js"! { "name": "MyAwesomeWebsite", "version": "0.0.1", "main": "server.js", "dependencies": { "express": "3.x" } } Now that we listed this a dependency, we can have node install it for us using the Node Package Manager or NPM. By running the command "npm install" in the command line it will read the dependency section of package.json and install any missing dependencies. $ npm install

External modules can be installed using npm NPM does a lot of work to get get the packages so you may see a bunch of stuff fly by. But the net result is the module code being loaded into a node_modules folder. And in that folder we see express, the external module we've added to our project. We can now leverage all the code in that module.

The express node module makes web applications easy Recall that you include external modules using the require() function. Lets go ahead and at the top of server.js require express so we can start using it. Since we will be using express, we no longer need the http module. Here old code is in black, new code is green, and deleted code is red. var express = require('express'); var http = require('http'); var port = 1337; Let's use our express module to create a web application object. This application object can do lots of the magic involved in hosting and serving a web site! The express "module" in this case is just a function we can call to get our application object--so lets call it! var port = 1337; var app = express();

Now lets use our app to respond to web requests. Get rid of all that old complicated stuff and lets put in some streamlined express magic! var app = express(); http.createserver(function (req, res) { res.writehead(200, {'Content-Type': 'text/plain'}); res.end('hello World!'); }).listen(port, '127.0.0.1'); app.get('/', function(req, res){ res.send('hello World! --from express'); }); app.listen(port);

So our whole server.js file should now look like: var express = require('express'); var port = 1337; var app = express(); app.get('/', function(req, res){ res.send('hello World! --from express'); }); app.listen(port); console.log('running server'); console.log('access locally at http://localhost:'+port); console.log('to stop server and return to command line, press ctrl+c'); Lets go ahead and fire up our updated server on the command line using the node server.js command. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c

Now lets get our web browser and go to http://localhost:1337 to use our new express app! Look at that! We just used express to serve up a web page!

Express handles requests based on their route What we did here was use express's routing. Which tells it to do certain things depending on the URL (web address) sent to the web server. The slash (/) means that all get requests--which is what web browsers use when you type in an address--to the root web site should be responded with "Hello World! --from express". app.get('/', function(req, res){ res.send('hello World! --from express'); }); Also, we told the web application to listen on port specified by the port variable, which we set earlier to 1337. app.listen(port); Ports are used in combination with web site addresses to get to web servers. Think of them as extension numbers for a phone number. The default port for unencrypted web sites is 80. Here we are using 1337 to avoid conflicting with any other web servers that may be running on your computer. That is why we enter the ":1337" after the url.

Web servers can handle different routes differently Lets add a new page to our website that will be accessed using a different URL. The part of the URL that differs for different parts of the website are called routes. Let's add our new route! This one can say goodbye. We'll make it so somebody goes to /bye on our website, they see a goodbye message. To do this we'll add a route for "/bye". var app = express(); app.get('/', function(req, res){ res.send('hello World! --from express'); }); app.get('/bye', function(req, res){ res.send('goodbye World!'); }); app.listen(port);

Lets stop and start the server again--remember we have to do this every time we change code. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c Now in the web browser, lets navigate to our newly created route: http://localhost:1337/bye Awesome, express used our new route to serve us different content!

Now lets see if our original route (just the forward slash) still works: http://localhost:1337/ Excellent, it still works!

Let's try something crazy, and navigate to a route we haven't defined: http://localhost:1337/abcdefg Here we got an error sent from express letting us know we cannot get that route. If we want a "catch all" route we can define one using an asterisk ("*") instead of a path.

A catch-all route can also be defined. Let's add a catch-all route that lets people know they entered an invalid web address. Since its a catch-all, make sure this route is defined after all of your other routes. var app = express(); app.get('/', function(req, res){ res.send('hello World! --from express'); }); app.get('/bye', function(req, res){ res.send('goodbye World!'); }); app.get('*', function(req, res) { res.send('i think you messed up the url!'); }) app.listen(port);

Lets stop and start the server again--once again we need to do this every time we change server code. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c Now in the web browser, lets try that crazy route again: http://localhost:1337/abcdefg Great! Now for undefined routes the web application does what we want, instead of what express wants. We successfully support multiple routes and handle unknown ones!

EJS is very simple HTML templating engine that can render HTML pages (and more) So outputting single sentences to the browser is ok, but really we want to output full HTML files! One way to do this is from EmbeddedJavaScript Templates, or EJS. Lets include EJS as a dependency in our web application by adding it as a dependency in our package.json. We'll use version 0.8. Once again don't forget the comma we now need after the express dependency. { "name": "MyAwesomeWebsite", "version": "0.0.1", "main": "server.js", "dependencies": { "express": "3.x", "ejs": "0.8.x" } } Once that is in place, we can install that depency's code from the command line using NPM $ npm install

Now we should have the EJS npm nodule in our node_modules directory And in that folder we see our new module, ejs, next to express, the module we added earlier We can now leverage all the code people have written for EJS! Lets go ahead and write an HTML file for EJS to process. When EJS processes a file, it is rendering it.

Since HTML files are what are seen by users when they browse your web application, they are called views HTML makes up what the user sees, so we call them views. Lets make a folder at the root level of the project where we can keep all our views. In our views folder, lets make a file called hello.ejs. Note that we use the "ejs" extension, not the "html" extension. That is because EJS files can actually do more than just hold HTML. But that is outside the scope of this lesson--just be sure to have your HTML view files end in ".ejs". <h1> Hello, World! </h1>

EJS can be wired up to Express by setting it as the view engine, and setting the views directory Now let's tell our web application to render that file when requests are received at the root level. To begin, we need to tell it to use EJS and that our views are located in the views folder. var app = express(); app.set('view engine', 'ejs'); app.set('views', dirname+'/views'); Note we used the special variable dirname, which means the directory (folder) where our program (server.js) is running. We said the views are stored in the views subfolder of that program folder.

Express can render EJS files using the render() function And now we can replace our hard-coded "Hello, World" with instructions for express to render our hello.ejs view. We can do this using the render() function and the name of the ejs view file. app.set('view engine', 'ejs'); app.set('views', dirname+'/views'); app.get('/', function(req, res) { res.send('hello World! --from express'); res.render('hello'); }); Now save, quit, and restart our node web server. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c

Lets visit our main page and see our HTML view in action. The <h1> tags should make the text bigger. Go ahead and navigate to http://localhost:1337/ Nice! It rendered our HTML view! Lets make one for our /bye route.

In our views folder, lets make another file called bye.ejs. We'll make this one a little more interesting. <h2> Goodbye cruel world! </h2> <p> We will miss you. </p>

And now let's modify server.js to have our /bye route render that view. app.get('/', function(req, res) { res.render('hello'); }); app.get('/bye', function(req, res) { res.send('goodbye World!'); res.render('bye'); }); Since we changed our server code, lets restart it! $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c

And now we can check out our /bye route view rendering by navigating to http://localhost: 1337/bye. Sure enough, our HTML view is being rendered! Now as hinted at earller, EJS can do a little more than just render HTML, but that is outside the scope of this lesson.

For your web application to be accessible on the internet, it needs to be hosted So far we've run the server on our own computer, and we can only access our web application from our computer. This is known as running locally, and why we use the "localhost" web address to access our server. If we want our application accessible to everybody on the internet, it needs to be hosted. When an application is hosted, it means it is running on a server that is accessible by the entire internet. Moving an application from your local machine to a hosted server is called deploying the web application. Lets deploy our web application!

AppFog provides free basic node.js hosting So now we have our web application and views. Lets make them available to the world! In order to do this, we need somebody to host our web application. That is run our code on their servers and listen to requests from the outside world. Usually hosting costs a lot of money, but we can leverage some free plans. One of them is from is a company called AppFog. Go on over to http://appfog.com. Let's click the "Sign up - it's free" button so we can start down our path to free node.js hosting!

It will want your email and for you to create a password, so go ahead and do that and then click "Sign Up".

Now we need to choose an application setup. Since we are programming node.js, we chose the Node application. We could have chosen Node Express, but we added express ourselves using our package.json and NPM, so Node is all we need.

Now we pick a datacenter where our application will be hosted. We'll us Amazon Web Services (AWS) as they are experienced at cloud datacenters, and choose their datacenter that is in the United States: AWS US East.

We need to give our application a name! This will determine the url used to access it from a web browser, so choose something you like and then click "Create App" Be sure to write down or remember that full domain name. In this example it is: myawesomewebsite.aws. af.cm

AppFog will start setting up your app on their servers in the cloud!

Once its ready you will see the mission control panel for your node web application. Now we need to send AppFog the code for our web application

AppFog uses a ruby based command line tool You can talk to your AppFog server using their command line tool. This tool is based on the ruby scripting language. Ruby is like node.js, but a bit older and with different programming syntax and style. The only thing you will need to know about ruby is how to install it. Instructions for installing ruby and the AppFog command line tool can be found on AppFog's website here: http://docs.appfog.com/getting-started/af-cli#installation. Basically to install ruby you can see many options on the ruby website: http://ruby-lang.org Windows users can download and run the windows installer found here: http://rubyinstaller.org/ Mac users may have ruby already installed. If you don't or you don't have a high enough version I recommend using the RVM method outlined at http://www.ruby-lang.org/en/downloads/

We need ruby that is at least version 1.8.7. You can check what version ruby you have using the ruby command with the -v argument. $ ruby -v ruby 1.9.3p286 (2012-10-12 revision 37165) [x86_64-darwin12.2.0] Here we have version 1.9.3, which is higher than 1.8.7 so we are good to go! Now we need to use ruby to fetch and install the AppFog command line tool. We use this using a special ruby command called "gem". We'll use gem to update (if needed) its information and then install the AppFog command line tool, called "af". You may need to run these commands with administrative privileges. $ gem update --system You'll probably see a lot of stuff fly by in your console as this commands run. When its done, enter this next command. $ gem install af Again you'll see lots of stuff fly by as the AppFog command line tool is installed.

The af command line tool lets you push code to your server, view its logs, and do other management tasks Now that we have our AppFog command line tool, af, we can use it to send our code to our server! The first thing we need to do is log in. We can do this using the af program and the login argument. $ af login Attempting login to [https://api.appfog.com] Email: demo@rockymountaincoding.org Password: ********** Successfully logged into [https://api.appfog.com] Once we are successfully logged in, we can use the af program and the apps argument to confirm our app is listed and running. $ af apps +-----------------------------------+----+--------------+------------------------------------------+-------+ Application # Health URLS In +-----------------------------------+----+--------------+------------------------------------------+-------+ myawesomewebsite 1 RUNNING myawesomewebsite.aws.af.cm aws +-----------------------------------+----+--------------+------------------------------------------+-------+

Use af update [application name] to send your code to the AppFog server Go ahead and go to the url of your web application. Since we haven't deployed our code to the server yet, we will be hitting AppFog's default code. Now lets put our code up there! We can do this using the af program, the update argument, and a second argument which is the name of our application. $ af update myawesomewebsite Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (26K): OK Push Status: OK Stopping Application 'myawesomewebsite': OK Staging Application 'myawesomewebsite': OK Starting Application 'myawesomewebsite': OK If you see the "OK"s then everything is working as planned!

Use af logs [application name] to view your server output, including any errors. Let's use AppFog to check on the logs. These contain everything we output using the console.log() function, as well as stuff output by the node program, such as error messages. We can do this using the af program and the logs argument, with our application name as a second argument. $ af logs myawesomewebsite ====> /logs/stdout.log <==== Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c Here we can see everything our program output using console.log(). In this case it doesn't make much sense since these messages apply to when we are running the server on our own machine. But at least we can see it is working. If the app isn't working or hit any errors, we would see the error message here and it could help us debug what is going on. Since we see Running server and no errors, everything should be working. Lets go to our web application on the internet!

You can access your application on the internet using your AppFog domain. Go check out your domain url! Note that AppFog is smart about ports so you don't need to worry about : 1337 here, it will actually use default port of 80 so you can just leave all that port stuff off. Now check out your domain url with the /bye route! Our node.js web application is successfully running in the cloud and be accessed from the internet!

Express can server CSS and Image assets as well Web sites that are just HTML are pretty boring. Lets spice it up with an an image and some CSS! We'll want to develop locally, and then once it works on our computer deploy the new version to the AppFog servers. First lets make a place for images and CSS. Since these are usually served with no modification or processing, they are called static assets and are considered public. So first lets make a public folder in your root directory. And now inside that public folder, lets make images and css folders.

Go ahead and download a cool image into your images folder. Make the name all lower case and keep the name simple. In our css folder, lets make a new CSS file. We can call it style.css. In it we can add a rule that makes images that are class cool have a blue border. img.cool { border: solid blue 2px; }

Normally if you load the path to an image or css file in the browser, you should see it. But since express is processing routes, it just treats /css and /images as unknown routes. You can verify this by first starting your server locally. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c And then by navigating to http://localhost:1337/public/css/style.css in your browser. This is not good, as browsers need to be able to access images and css! Lets tell express how to handle these requests.

The static middleware can be used to serve static assets Open back up your server.js file for editing. We'll tell express to treat our public folder as a static directory. This means that any requests to routes begin with the names of folders within the static directory, will be sent unprocessed from within the public folder. For example, if expres sees /css/style.css it will send back the unprocessed (static) contents of public/css/style.css. To set up the static directory, we will use something called express middleware. Middleware can be quite complicated, but the only thing you need to know is it intercepts a request in the middle and can do stuff. In our case, we want to use static middleware, that handles our static directory. We use middleware with the use() command, and will use express's built in static middleware. We want to add the middleware before our routes. app.set('view engine', 'ejs'); app.set('views', dirname+'/views'); app.use(express.static( dirname+'/public')); app.get('/', function(req, res) { res.render('hello'); });

Now lets see if our static assets will serve up! Since we made a change to server.js we need to restart it.. $ node server.js Running server Access locally at http://localhost:1337 To stop server and return to command line, press ctrl+c Now lets first try our CSS file. In a web browser, open http://localhost:1337/css/style.css. Hooray! And lets check to make sure image serving works too by opening up your image. In this example we would navigate to http://localhost:1337/images/icecream.jpg.

With our static assets being served up, lets go ahead and put them into our hello.ejs view! We've been cheating with invalid HTML, so while we add this stuff lets clean up our HTML and make it valid. We'll also add a link to our other route. <!DOCTYPE html> <html> <head> <link type="text/css" rel="stylesheet" href="css/style.css" /> </head> <body> <h1> Hello, World! </h1> <p> <img class="cool" src="/images/icecream.jpg" /> <br /> <a href="/bye">say Goodbye</a> </p> </body> </html>

Since this time we changed a view, we actually don't have to restart the server. That is because the view will be re-rendered by the server. So we can go ahead and reload http://localhost:1337 to see our changes! And now our website is using image and CSS files!

New code needs to be deployed to the hosted server for it to be live on the internet If we go to our hosted AppFog server right now, it still has old code. Lets deploy our changes! Quit the server its running to get back to a command prompt, and use the af update command. (Remember if you forgot the name of your application you can use af apps to look it up). $ af update myawesomewebsite Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (18K): OK Push Status: OK

Usually we see "Starting Application", but if you don't see anything about that you need to restart the AppFog server yourself. You can do this using the af program with the restart argument and the name of our application as the second argument. If you did see this stuff, then you can skip the restart step. $ af restart myawesomewebsite Application 'myawesomewebsite' already stopped Staging Application 'myawesomewebsite': OK Starting Application 'myawesomewebsite': OK We see that our application started again OK, so lets go check it out on the internet! And here we see our updated code has been successfully deployed!

You have successfully written and deployed a hosted simple node.js web application! You can make changes and upload them as well! I recommend spicing up your pages using twitter bootstrap. With AppFog, you can find a list of all the af program arguments you can use in their command line tool documentation here: http://docs.appfog.com/getting-started/af-cli Of course this is just the beginning! Web applications can take in user input, process it, and factor it into what it displays in the user's web browser! But serving up different HTML, CSS, and images for different routes is a great way to start!