News Flash

Great article by @NeutronUK on how to create a print stylesheet using Firebug and the Web Developer Toolbar - http://cot.ag/bOQiVM

Author Archive

22 April 2008

I’m a front-end engineer slash designer who likes to think he can dabble in code. With my simple side projects I do a passable job and my hacks limps along, most likely inefficiently and always on the verge of breaking, but getting the job (mostly) done. But where I almost always trip up and get lost — in days of hair pulling frustration — is when I’m setting up my local development or live production environment. It’s so difficult to find an accurate, knowledgeable and up-to-date walkthrough for frameworks like Rails or Django that it’s almost comical. And if, by the grace of the server gods, I do finally get something that runs and deploys my code — well now I get to monitor it, keep it updated and running 24/7. Yay!

This is why Heroku immediately appealed to me when it went live. “Develop and deploy a Rails app entirely in the browser.” Yes please. Unfortunately, by the time Heroku launched I’d already been bitten by Python and Django and had moved on to build my side projects without Ruby or Rails. So back to the drawing board, setting up my environments, dying a little each day I lost — once again — rebuilding the wheel.

Then Google App Engine launched, and I’ve been gleefully experimenting ever since.

This two-part series of articles is for all those who, like myself, are comfortable with markup, design and app code, but would rather not bother with all the other stuff. You know, the stuff that keeps Evan Williams awake at night . I want to spend what little time I have for my side projects being a mostly clueless developer, not a completely clueless sysadmin.

This intro will get you up and running on GAE in literally minutes and walk you through a simple app that’ll show you most of everything you need to know upfront about what GAE can do, for you and your app.

The app we’ll be building with this article is a silly, web-industry-navel-gazing barely-an-app I created called Startupdown , “where startups throw down”. Two startups enter, one startup leaves. It was partly inspired by TechCrunch’s GAE proof of concept where you voted on random startups. But I like to think mine’s a little more fun, and just barely better designed.

Screenshot of Startupdown

Now, in order to get any GAE application running, you’re going to need to have an account. Unfortunately, right now there’s a waiting list of 10,000 or so to get into the beta. So we’ll have to just pretend we’re all in. And since we’re all in, we first need to create our application and name it. Mine’s named “startupdown”.

Next you’ll need to download and install the appropriate GAE SDK for your OS .

Screenshot of SDK download

Then create the folder that’s going to house our project, I called mine startupdown. For this simple project our folder and file heirarchy is going to look like this:

  • startupdown
    • app.yaml – app’s basic settings
    • index.html – app’s homepage
    • index.yaml – auto-generated by GAE
    • main.py – app’s main functions
    • myloader.py – for populating our data, explained fully in Part 2
    • results.html – takes the results from the from submission on the homepage
    • startups.csv – used by myloader.py
    • stlylesheets
      • main.css

That’s all there is to it. So the first file we need to put into our app folder is the project’s app.yaml file — it holds the basic settings for our project — and it looks like this:

application: startupdown
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: main.py

Grab the completed app.yaml file here

Here “application” is whatever you named your app in the GAE admin. And we don’t need to worry about changing version, runtime or api_version, they can all stay as is. “Handlers” are GAE’s way of handling URLs, so right now our only handler is saying “whenever anyone pulls up the root URL or any subpages of it, we’ll use the main.py script to handle.”

Now that we’ve created our app.yaml file, we can fire up the local development server that comes with the GAE SDK. We start it like this:

dev_appserver.py ~/full/path/to/startupdown

Screenshot of server running

This takes the contents of the project folder and gets it up and running at http://localhost:8080. And as we add functions and make changes to our app, the server will automatically load them, so we don’t need to worry about restarting it for every change.

With our environment now running we can get started on the meat of our application, the main.py file. The main.py is going to contain:

  • all of our libraries
  • all of our datastore models (I’ll explain what this is in just a second)
  • all of our main page functions

First, we’ll start with our libraries, they look like this:

import wsgiref.handlers
import os
import random

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template

GAE apps need to import wsgiref.handlers and os in order to handle URLs, so just include those two lines by default. My app imports the random Python library because I’m using random numbers, as you’ll see in a few paragraphs. And the last three, webapp, db and template are for the GAE webapp framework, the GAE datastore API and the GAE template language respectively. You’ll most likely be including them by default in most of your GAE apps as well.

The next part of our main.py file is for our datastore models. One of the biggest reasons to use GAE is to take advantage of Datastore, its highly scalable data modeling API. Instead of using something like MySQL or PostgreSQL to create tables and fields in a relational database, you use the Datastore API to create data models like this:

...
class Startup(db.Model):
  name = db.StringProperty()
  url = db.StringProperty()
  logo = db.StringProperty()

class Vote(db.Model):
  loser = db.IntegerProperty()
  winner = db.IntegerProperty()
...

Here I’m defining the two data models I’m using in my Startupdown application. Every startup has a name, url and logo, which are all strings. And every vote has a loser and winner, which are both integers. For more complex apps you’ll probably have several models and many different types of properties, like floats, datetimes, blobs or any of the other types of data properties GAE supports .

Now that we’ve defined the type of data our application needs, we can write the functions that are going to be accessing and manipulating that stored data. Since this app is very basic, it only has two functions — one that displays the main page and one that takes the form values and displays the results of the voting.

Here’s the MainPage function:

...
class MainPage(webapp.RequestHandler):
  def get(self):
    startups = Startup.all()

    int1 = random.randint(0,49)
    int2 = random.randint(0,49)
    while int2 == int1:
      int2 = random.randint(0,49)

    template_values = {
      ’startup1': startups[int1],
      ’startup2': startups[int2],
      }

    path = os.path.join(os.path.dirname(__file__), 'index.html')
    self.response.out.write(template.render(path, template_values))
...

All this function is doing is 1) getting all the startups by calling Startup.all() (where Startup is the name of the Startup model we created earlier and all() is a function all models have that grabs all their data) 2) creating 2 unique random numbers between 0 and 49 (since we’re using these random numbers to pull 2 startups out of a list of 50 using the startup array, and don’t forget, arrays always start at 0) and 3) assigning the 2 random startups we grab to the template_values list (lists are a Python datatype, very similar to arrays, but you can put almost anything in them). Template_values are how you pass variables from functions to static HTML pages. The template_values array now has our two random startups and is available in our index.html file, thanks to those last two lines of code.

Speaking of index.html, let’s take a quick look at what our app’s front page looks like behind the scenes:

<html>
  <title>Startupdown - Where startups throw down</title>
  <head>
    <link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
  </head>
...
        <table cellspacing="0" class="startups-table">
          <tr>
            <td><h2>{{ startup1.name }}</h2></td>
            <td class="vs"></td>
            <td><h2>{{ startup2.name }}</h2></td>
          </tr>
          <tr>
            <td>
              <a href="http://{{ startup1.url }}">
                <img src="http://thinkvitamin.com/images/articles/startupdown/{{ startup1.logo }}" />
              </a>
            </td>
            <td class="vs">VS.</td>
            <td>
              <a href="http://{{ startup1.url }}">
                <img src="http://thinkvitamin.com/images/articles/startupdown/{{ startup2.logo }}" />
              </a>
            </td>
          </tr>
          <tr>
            <td>
              <form action="/results" method="post">
                <input type="hidden" name="winner" value="{{ startup1.key.id }}" />
                <input type="hidden" name="loser" value="{{ startup2.key.id }}" />
                <p><input type="submit" value="Vote for {{ startup1.name }}"></p>
              </form>
            </td>
            <td class="vs"></td>
            <td>
              <form action="/results" method="post">
                <input type="hidden" name="winner" value="{{ startup2.key.id }}" />
                <input type="hidden" name="loser" value="{{ startup1.key.id }}" />
                <p></p><input type="submit" value="Vote for {{ startup2.name }}"></p>
              </form>
...

Grab the completed index.html file here

Notice, first, how we reference variables inside HTML, using double curly braces around our objects and variables ( i.e. {{ startup1.name }}). Next notice how I refer to startup1 and startup2’s properties using dot notation. Remember when we defined the Startup model earlier as having a name, logo and url? Well now we’re accessing those properties using startup1.name, startup1.logo and startup1.url.

Also notice how, in our form, we’re using startup1.key.id — this gives us access to the ID, or key, that GAE automatically creates whenever we import or create data in the datastore. And, lastly, we set the form’s action to “/results”, which is the app’s only other page, and is also the only other function in our main.py file. Let’s take a look:

...
class Results(webapp.RequestHandler):
  def post(self):
    vote = Vote()
    vote.loser = int(self.request.get('loser'))
    vote.winner = int(self.request.get('winner'))
    vote.put()
...

The first part of our Results function is what processes the form data. def post(self) is grabbing the post data and vote = Vote() is creating a new vote model so that we can add the vote data to the datastore. We then grab our form’s loser value with self.request.get('loser') and assign that to vote.loser. And we then do the same to vote.winner. Then, with vote.loser and vote.winner assigned values, we put that data into the datastore using the put() function.

Grab the completed results.html file here

So now we’ve grabbed the ID’s of the losing startup and the winning startup, next we need to grab the rest of the startup’s data.

...
  theWinner = Startup.get_by_id(vote.winner)
  theLoser = Startup.get_by_id(vote.loser)

  q = Vote.gql("WHERE winner = :1 AND loser = :2", vote.winner, vote.loser)
  winnerVsLoser = float(q.count())

  q = Vote.gql("WHERE loser = :1 AND winner = :2", vote.winner, vote.loser)
  loserVsWinner = float(q.count())
...

Grab the completed main.py file here

Using GAE’s get_by_id function, we can grab the rest of our startup’s info (name, url and logo) by using the ID’s we grabbed from the form. Notice also how we can use GAE’s query language, GQL, to get results from our Vote data. In the instance of the winnerVsLoser variable, we’re grabbing all the instances of Vote where winner equals the winner we grabbed from the form and loser equals the loser we grabbed. Then, using GQL’s count() function, we’re counting how many results were returned. If 5 people have voted for startup1 over startup2, we’d get 5 rows of data back from or GQL query.

Using queries like this we’re able to create percentages of how often certain startups won and lost against other startups, etc.

That’s a lot to take in for one article, so we’ll stop here. Next article, in the second part of Developing with GAE, we’ll look at how to import our list of 50 startups into Startupdown, how to deploy and administer our app once we’re finished and a few tips and tricks once you’re up and running.

Continue reading 12

24 July 2007

With the Future of Web Apps conference just a few months away and Carsonified announcing their whistle stop tour across Europe, we thought it’d be a good time to ask the top designers, developers and entrepreneurs across the world what they thought of the future of the web.

We asked them all this question:

“What’s one thing about today’s web (company, technology, movement, etc.) that you think we’ll look back on in 10 years and say ‘that was important’ or ‘that was really a turning point in the history of the web’?”

And here is what they had to say:

Greg Storey, Airbag Industries

“After the crash and the money left the Internet the same people who pioneered web design and development stayed behind and found a way to take the Internet as a platform to the next level. We’ll look back at the last three years as the time when smart, talented people found a way to harness the power of web technologies and turned it into a viable, real-world alternative to traditional applications and media all without the need or assistance of Wall Street or the venture capitalists. It will be a time when skill and talent, not money, ran the show.”

Geoffrey Grosenbach, TopFunky Corporation

“The most impactful change in the last few years has been web developers treating the web as an API. The ability to share resources programmatically through Microformats, RSS, and APIs has not only made life richer for programmers and entrepreneurs, but for the end user as well.”

Jeffrey Kalmikoff, SkinnyCorp

“I think we’ll look back and think it’s amusing how much emphasis people put on “web 2.0”. In my opinion, people spend so much time trying to define it and make their projects “comply” with it, that it’s most likely slowing down what’s certainly to come next. It’s gotten to the point where “web 2.0” is more about the fashion of a website rather than it’s functionality. Hopefully in 10 years, we’ll look back on this all from web 8.0 and have a hearty chuckle.”

Dan Saffer, Adaptive Path

“Ten years ago, in 1997, it was the rise of broadband connections that have made much of the last internet decade possible or, at least, tolerable. The next ten years will be all about mobile-tailored services delivered over the web to mobile devices. The iPhone and Nokia’s N95 are just starting to scratch the surface of what’s possible. We’re starting to see physical locations having metadata attached to them, and it won’t be long before our devices and the mobile web can make that data available to us rapidly and geo-specifically.”

Dylan Schiemann, Sitepen

“I think the single biggest thing was been the spread of both open source and user-driven content. Getting more people involved with publishing, creating, and doing — not just consuming — has made the web and the world a place where people are more empowered to be creative, find their passion, and make a living doing the things they most enjoy.”

John Oxton

“From a designer’s point of view I think the work that has been going on with grids and typography for the web will be viewed as a turning point for sure. Also, Apple’s approach to the mobile web seems quite important, by making it easier, much easier, for designers to deliver content to mobile devices.”

Thomas Fuchs, Wollzelle

“The mid-2000s marked an emancipation from pure informational or static web sites and ported-over desktop apps. The Web grew up to provide for applications and services not possible until then, through the use of the first and foremost resource on the net: people. The “social web” will stay with us for a long time.

Noteworthy, this also influences technology and helps break browser monopolies, which can only be a good thing for the years to come.”

Larissa Meek, AgencyNet Interactive

“One of the most important changes 10 years from now will be the birth of YouTube. User-generated video made the world smaller, giving anyone the ability to be their own filmmaker or even become an instant celebrity. It also reminds us how careful you have to be with your personal life appearing on the web.”

Michael McDerment, Freshbooks

“I think that APIs and connections between various apps will be something that we look back on as a turning point because it ushers in a new world where people can choose the best parts of web apps for their needs and use those to design really effective workflows … especially for the small business markets.”

Keith Robinson, Blue Flavor

“I might be a bit biased because of what I’ve been working on lately (getleaflets.com), but I think the introduction of iPhone, and the latest version of Safari, is going to cause a major change to the web as we know it. It’ll finally make the mobile web interesting to both users and developers in the US and with its support of CSS3 could push browser support and standards to a new level even on the desktop Web. Someday in the next few years we could start to see true standards support across multiple browsers, platforms and devices as well as a very compelling mobile user experience in the hands of a huge number of people around the world.”

Garrett Dimon

“We’re still in the “awkward early teen years” of web services and APIs. Right now it’s more of a novelty where technically savvy people are enabling access to some basic information and other technically savvy people are playing with all of this information under the guise of “mashups” and experimentation.

However, once these APIs are everywhere, the possibilities become much more robust and move from the realm of novelty experiments into truly practical and business-oriented uses. Whether it’s Amazon selling services/functionality, an application exposing data, or simply improved tools for consuming these services, the web starts to become more seamlessly connected instead of duct-taped together.”

Eric Meyer

“Microformats. Whether they persist in their current form 10 years down the road or give rise to something newer, they are the only real hope we have of delivering a more semantic web to everyone. If you want to see the beginnings of what that will be like from the user’s perspective, install the Operator extension for Firefox and hit some microformatted sites.”

Andy Budd, ClearLeft

“I think one of the biggest changes came when businesses started to realise that they needed to work their business models around their user needs, and not expect users to fit around their outdated business models.”

Sean Madden, Frog Design

“I’m hoping that we’ll place a grubby little finger squarely on information aggregation, both on a personal level and as a vehicle for providing relevant recommendations. The key tenet powering the idea of the wisdom of the crowds says that a crowd is at its wisest when it is diverse, independent, decentralized, and aggregated. The internet has always encompassed the first three, but only recently have we recognized the power and started to understand what we can do with intelligently considered aggregation.”

Peter Nixey

“Funny you should ask … my call would be OpenId. Of course, as a disclosure, I should also tell you that I’m currently on Y-Combinator in the states and my company is one which is hoping to make OpenID easy!”

Derek Powazek

“The thing about today’s web that we’ll look back on in 10 years and say “that was important” is … print. Tangible, actual print.

The web has created a new generation of writers. Say what you want about crappy screens and ever-faster broadband — what we do online every day is read and write.

Meanwhile, print-on-demand technologies are quietly getting better and cheaper every day. You can now get better photographic reproduction out of a digital press than a traditional one.

Where do you think this new generation writers will turn for authenticity and professionalism after they’ve gotten the taste for writing in their system? What could be more respectable than the printed page?

We’re still figuring out what the web is truly good for. After all, we’ve only had a dozen or so years to practice. But we all know what print is good for — permanence, authority, and beauty. The web will not replace print any more than television replaced radio. It will, instead, change it into something better.

The children of the internet, raised on digital efficiencies and open access, are going to reinvent the printed page. The revolution has already begun.”

Continue reading 1

Sign Up to our Newsletter

Enter your e-mail address below to receive regular updates on web design, web development and web business. Subscribe today and receive a free 44 page PDF "Designing Web User Interfaces" by Ryan Singer of 37signals.

Subscribe to the Think Vitamin articles RSS feed

HTML5 Online Conference April 12 2010

News

Twitter

Follow us on Twitter

Subscribe

Article Subscribers

Feedburner blog subscriber indicator

News Subscribers

Feedburner blog subscriber indicator

Subscribe by Email

You can receive Think Vitamin updates via email. Just pop your email address in the box below and click the arrows.

Subscribe by RSS

You can also receive new Think Vitamin posts via your RSS feed reader

Subscribe RSS Think Vitamin is a proud member of the Smashing Network

Ads Via The Deck