Too Much About Paul

Various things I'm saying and doing in various places

Looking for music, show schedule, videos? That's just a click away at paulroub.com.

May 05, 2013

My Upcoming Gigs

Nolan's Irish Pub, Monday May 6, 2013

Nolan's Irish Pub, Monday May 6, 2013

204 W Cocoa Beach Causeway
Cocoa Beach, FL
321-783-8499
http://www.nolansirishpub.net/

Writers' Night. I'll be in-the-round with Steve and Hannah. Sideman duties make me very happy..

With Sam Tritico, Susan Rose, Steve Hodak, Hannah Kauffman, and more..

by Paul Roub at May 05, 2013 04:12 PM

May 01, 2013

Work Blog

Handling Simultaneous Updates in Zumero: There Is No Step 2

When we talk about the advantages of always-local data for mobile apps, the typical first reaction is “that sounds awesome”.

The next step is to start thinking about your apps, and how mobile users interact with your data, and how those users aren’t going to sit down and coordinate with each other:

“It’s my turn to update the inventory records for store #42”

“Done with those yet?”

“Yep, go ahead and sync.”

“Cool, thanks. Now I can update the ordered-quantity data.”

(a) That’s not how work gets done, (b) computers are supposed to take care of picky details for us, and (c) I don’t want to hang out with those guys at all.

Dealing with this scenario in a Zumero-enabled app boils down to:

  • Users update and add data as they see fit.
  • At some point, probably in the background, the app syncs to the server.
  • Up-to-date, merged data now lives on the device.

You don’t have to write any code that knows conflicting changes happened. Seriously. That’s our problem.

Even when the changes are tricky.

Consider the Zumero wiki sample app. A wiki is a collaborative tool. People can, will, should edit the same pages. Sometimes at the same time.

What happens if they do? Andy creates a page on his iPad:

Colin pulls up the app on his iPhone, syncs, and gets his own copy. While offline, he adds a line to the page:

At the same time, Andy completes one of the items on his list, and marks that line as completed.

Colin comes back online, his app checks in and syncs, and he sees this:

Here’s the code that caused their apps to reconcile the conflicting updates:

Sync a Zumero database link
1
ok = [_db sync:scheme user:username password:password error:&err];

There’s no step 2.

To be fair, there were a couple of lines of code that ran when we initially set up the database, which boiled down to:

  1. If there are conflicting edits on the ‘text’ field of a wiki page, try to merge them, Zumero. Thanks.

No step 2.

May 01, 2013 02:51 PM

April 15, 2013

My Upcoming Gigs

Vinyl Request Records, Saturday April 20, 2013

Vinyl Request Records, Saturday April 20, 2013

501 E New Haven Ave
Melbourne, FL
321-208-5455
http://www.vinylrequestrecords.com/

Record Store Day Bash.

With Adam Hosburgh, Special Blend, ISO and Fields of Saturn.

by Paul Roub at April 15, 2013 01:02 PM

April 14, 2013

My Upcoming Gigs

Vinyl Request Records, Saturday April 20, 2013

Vinyl Request Records, Saturday April 20, 2013

501 E New Haven Ave
Melbourne, FL
321-208-5455
http://www.vinylrequestrecords.com/

Record Store Day Bash.

With Adam Hosburgh, Special Blend, ISO and Fields of Saturn.

by Paul Roub at April 14, 2013 08:56 PM

Personal Blog

People: Gotta Love (some of) 'Em

Yesterday, I had the minor misfortune of witnessing a serious accident from far too close. A pickup, traveling very fast on a crowded highway, cut off the car in the adjacent lane, started rolling to one side, swerved back the other way, and flipped; he rolled twice before stopping sideways 20 feet from the road. I was the driver he cut off.

I say “minor” because I wasn’t in the truck; wasn’t harmed; saw what he was going to do, and the load of unsecured pipe and metal in the truck bed, and had slowed down enough to avoid the debris.

Somehow no one else was hit, and there was no pileup. The adults and small children in the car walked away from the crash, bloodied but surprisingly OK. (The wonderful thing about car seats and seat belts - they work even when you’re too young to appreciate them)

I’ll refrain from comment on the driver’s behavior before and afterwards. I’m immensely glad the kids are OK.

I pulled over immediately, and ran back to the truck. By the time I got there, several other drivers had already reached them and were helping everyone out of the truck.

Within two minutes, random passerby were already calming the children, pressing clothing to their cuts, because of course you’d do that.

A man stopped and brought water bottles from his trunk, for the kids, because it’s hot and shadeless and of course he would.

We all confirmed that one woman had called 911, and got out of her way as she checked the kids out per their instructions, because of course she would.

The rest of us decided at the same time to clear the worst of the shattered pipe, rebar, and sheet metal from the road. It needed to happen, we were there, so of course we did.

A nurse came running down the grass, from however far back she’d stopped. Because of course.

Fire Rescue, Sheriffs and Troopers arrived within 5 minutes, and we all gave our versions of events. Except for one man who couldn’t stick around, but left me his name and number to pass along. Of course.

Once we’d done that, and the professional and responsible folks had things in hand, we all got out of the way and left without further discussion.

Because we hadn’t done anything special; we were just the closest of many decent people in the area at that moment. That’s what choked me up, driving on afterwards - it was all so matter-of-fact. The awful exceptions make the news, and make better stories, but most people? When they see they can be of use?

Of course.

April 14, 2013 04:03 PM

April 12, 2013

My Upcoming Gigs

Cafe Da Vinci, Saturday April 13, 2013

Cafe Da Vinci, Saturday April 13, 2013

112 W. Georgia Ave
Deland, FL
386-736-0008
http://www.cafedavincideland.com/

Part of the DeLandapalooza Music Festival. I'll be on the inside stage..

by Paul Roub at April 12, 2013 09:43 PM

April 09, 2013

Work Blog

Zumero: Background Sync in Objective-C

Mobile offline RSS reader, Part 5

In the second “crossover episode” of our series (previous episodes begin on Eric’s blog), we look at background operations.

Previously, we built Zumero databases full of RSS lists and feed contents. The ZumeroReader sample app pulls, reads and displays those feeds on iOS devices. In action, it looks like this:

At startup, it pulls the feed list like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ZumeroDB *db = [[ZumeroDB alloc]
              initWithName:@"all_feeds"
              folder:path host:host];
db.delegate = self;

NSError *err = nil;
BOOL ok = YES;

if (! [db exists])
  ok = [db createDB:&err];

ok = ok && ([db isOpen] || [db open:&err]);

NSDictionary *scheme = nil;
NSString *uname = nil;
NSString *pwd = nil;

ok = ok && [db sync:scheme user:uname password:pwd error:&err];

We’re creating a Zumero database file named “all_feeds”. It will sync with a similarly-named dbfile on the server side.

We don’t need any authentication info, since (as previously discussed) the feed lists and feed databases are pullable by anyone.

The ZumeroDB::sync method always performs its network activity on a background thread, calling delegate methods when the action is completed (hence db.delegate = self).

In this case, on sync success, we grab the latest copies of the individual feed databases:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ok = [db selectSql:@"select feeds.feedid, url, title from feeds, about "
    "where (feeds.feedid = about.feedid)" values:nil
    rows:&rows error:&err];
// ...
  
for (NSDictionary *row in rows)
{
  NSNumber *id = [row objectForKey:@"feedid"];
  
  [self syncFeed:id];
}

// ...

- (void) syncFeed:(NSNumber *)feedid
{
  // ...
  NSString *dbname = [NSString stringWithFormat:@"feed_%@", feedid];
  ZumeroDB *db = [[ZumeroDB alloc] initWithName:dbname folder:path host:host];
  // ...
  db.delegate = self;
  ok = [db sync:nil user:nil password:nil error:&err];
  // ...
}

But what if feeds are updated while the app is running? There are seemingly infinite strategies for launching background tasks in iOS, and you’ll use the one that fits your application best. In this case, I cribbed a simple plan from a StackOverflow post - every time a touch is detected, we restart a timer. If that timer actually manages to expire, then we’ve seen no touches in 5 seconds.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
  
    NSSet *allTouches = [event allTouches];
    if ([allTouches count] > 0) {
        UITouchPhase phase = ((UITouch *)[allTouches anyObject]).phase;
        if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded)
            [self resetIdleTimer:maxIdleTime];
    }
}

- (void)resetIdleTimer:(NSTimeInterval)secs
{
    if (idleTimer) {
        [idleTimer invalidate];
      idleTimer = nil;
    }
  
    idleTimer = [NSTimer scheduledTimerWithTimeInterval:secs
               target:self selector:@selector(idleTimerExceeded)
               userInfo:nil repeats:NO];
}

When that timer fires, we check to see if its been 5 minutes since our last sync, and that a sync is wanted. If so, we sync again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- (void)idleTimerExceeded {
  if (wantToSync)
  {
      NSTimeInterval since = [nextSync timeIntervalSinceNow];
      
      if (since <= 0)
      {
          wantToSync = FALSE;
          
          BOOL ok = FALSE;

          // the view controller's sync method from earlier          
          if (mvc)
              ok = [mvc sync];
          
          if (ok)
              self.networkActivityIndicatorVisible = YES;
          else
              // the sync call failed; try again later
              [self waitForSync:(10 * 60)];
      }
      else
      {
          // nope, check again next idle time
          [self resetIdleTimer:since];
      }
      
      return;
  }
  
  [self resetIdleTimer:maxIdleTime];
}

We also kill our timers when exiting, restart them when waking up or activating, etc.

Finally, when we go into the background, we try for one last sync before our process is suspended:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)applicationDidEnterBackground:(UIApplication *)application
{
  // ...
  bgtask = [application beginBackgroundTaskWithExpirationHandler:^{
        [self endBackgroundTask:bgtask];
        bgtask = UIBackgroundTaskInvalid;
    }];
    dispatch_async(dispatch_get_global_queue(
      DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      [mvc sync];
      // finishBackgroundTask will be called by the sync handlers
    });
}

Like any good sample app, there’s so much that this app doesn’t do. You’re invited to experiment with adding them.

  1. We don’t maintain any read/unread information, either at the feed level or for individual items. This would be a good place to try creating/syncing new databases.
  2. We naïvely grab the first <link> element we see and assume that it’s our permalink, without ever checking its rel attribute or content type.
  3. A feed’s contents are displayed as one big chunk of HTML. Individual table cells might be nice.
  4. We don’t make any attempt to become a long-running background process, since we don’t actually play audio, collect location information, etc. Might be fun to play with that.
  5. Configuring the app is done by editing the source and rebuilding. That seems rude.
  6. If you did update some sort of last-read database, wouldn’t that be a great moment to kick off a background sync? (The Wiki app included in the Zumero SDK does this when a page is created or saved)

April 09, 2013 02:31 PM

Altering a Zumero Table

Mobile offline RSS reader, Part 4

In part 3 of this series, Eric discussed three programs that do the back-end work of RSS aggregation - scanning feed lists, caching summaries and IDs, creating data files as we go.

Before we get into using that information in part 5, we need to adjust one of the schemas a bit.

The items table in each feed’s database is set up as:

1
2
3
4
5
6
7
8
CREATE VIRTUAL TABLE items
USING zumero
(
  id TEXT PRIMARY KEY NOT NULL,
  title TEXT NOT NULL,
  summary TEXT NOT NULL,
  pubdate_unix_time INTEGER NOT NULL
);

Where the id field comes from the feed items’s id or guid element, or from the first link found in the entry. In many RSS feeds, id will also be the permalink to the entry’s “destination”, e.g.

1
2
3
4
<item>
  <title>Enterprise mobile will have a lot of SQL going on</title>
  <guid>http://www.ericsink.com/entries/mobile_sql.html</guid>
  ...

But that’s not mandatory. For example:

1
2
3
4
5
6
<entry>
  <id>http://zumero.com/2013/04/04/just-released-the-zumero-development-server</id>
  <link type="text/html" rel="alternate"
   href="http://zumero.com/2013/04/04/just-released-the-zumero-development-server.html"/>
  <title>Just Released: the Zumero Development Server</title>
  ...

We still want that unique id, but if a link is available, we’ll want to store that, too.

Easy enough when creating a new items table. We’ll alter z_rss_create.cs to read:

1
2
3
4
5
6
7
8
9
10
11
12
db.Execute(
        @"CREATE VIRTUAL TABLE 
        cur.items 
        USING zumero
        (
          id TEXT PRIMARY KEY NOT NULL, 
          title TEXT NOT NULL,
          summary TEXT NOT NULL,
          pubdate_unix_time INTEGER NOT NULL,
          permalink TEXT
        );"
        );

But what about items tables that already exist? Unfortunately, SQLite does not allow alter table ... add column to run against a virtual table like Zumero’s. We’ll use the Zumero-provided alternative, zumero_alter_table_add_column().

In z_rss_update.cs, we’ll see if the new column already exists:

1
2
3
4
5
6
7
8
var query = "pragma cur.table_info(\"items\")";
List<SQLiteConnection.ColumnInfo> cols = db.Query<SQLiteConnection.ColumnInfo> (query);

foreach (var c in cols) {
    found = (string.Compare ("permalink", c.Name, StringComparison.OrdinalIgnoreCase) == 0);
    if (found)
        break;
}

If not…

1
2
3
4
5
6
7
8
9
db.Execute("BEGIN TRANSACTION;");
db.ExecuteScalar<string>(@"select zumero_alter_table_add_column(
   'cur', 'items', 'permalink TEXT');");
db.Execute("COMMIT TRANSACTION;");

// after altering a zumero table, the dbfile connection must be reopened

db.Execute("DETACH cur;", dbfile_name_for_this_feed);
db.Execute("ATTACH ? AS cur;", dbfile_name_for_this_feed);

See this fork of z_rss for all the necessary code.

In part 5, we’ll see a simple iOS RSS reader that pulls these databases in the background, and lets you browse the feed summaries and link through to the full articles.

April 09, 2013 02:26 PM

March 06, 2013

February 10, 2013

Personal Blog

Sunday Morning Password Audit

We all know about the value of strong passwords, and the essential extra value of never reusing passwords, right?

Right. Of course we do.

And we all follow that wisdom, always, without fail, right?

Right?

I mean, except for that throwaway password. You know the one. The same one you’ve been using for random I’ll-probably-never-be-here-again sites (and apps) for years and years. The one you never use for important things. I mean, who cares if anyone cracks that one? That’s why it’s OK that it’s short, and crackable, and re-used so often.

For “fun” this morning, I opened up 1Password and created a Smart Folder like so:

1Password Main Menu -

1Password Search - Items where password is like the throwaway

That blurry part there, is of course, my throwaway password of choice. That count is, indeed, 104 logins. 104 logins that were somehow trivial enough for a junk password, yet worthy of a “Save” click when I created them.

But hey, none of those are important sites, right? Nothing with financial implications or anything.

Oh, just:

I had planned to spend the rest of the morning doing my taxes; that sounds like more fun than what I ended up doing.

Changing 104 passwords takes a while, but at least I’m not doing it in a blind panic after one of those many sites had their database compromised.

Take a minute today to search your favorite password tool. You may be embarrassed by what you turn up, but console yourself this way: “At least I didn’t tell the whole internet about it like Paul did.”

You’re welcome.

February 10, 2013 04:20 PM

February 01, 2013

My Upcoming Gigs

The Bank & Blues Club, Saturday February 9, 2013

The Bank & Blues Club, Saturday February 9, 2013

701 Main St
Daytona Beach, FL
386-257-9272
http://daytonabeachmainstreet.com/thebank/

Part of the Mainstreet Live Original Music & Art Festival. 130 acts on 17 stages..

by Paul Roub at February 01, 2013 03:10 AM

January 31, 2013

January 24, 2013

January 06, 2013

January 05, 2013

January 01, 2013

December 31, 2012

My Flickr photos

Early Arrivals at the Avian New Year Party

Paul Roub posted a photo:

Early Arrivals at the Avian New Year Party

The longer I look at this, the less likely I am to walk into my backyard on a windy day. It's like the outlet in A Christmas Story.

by Paul Roub (nobody@flickr.com) at December 31, 2012 11:54 PM

December 24, 2012

December 19, 2012

My Flickr photos

Christmastime in Florida.

Paul Roub posted a photo:

Christmastime in Florida.

Enjoying the sun while waiting for the dog to do what she came out to do (chase squirrels, apparently)

by Paul Roub (nobody@flickr.com) at December 19, 2012 03:37 PM

December 16, 2012

December 04, 2012

November 20, 2012

November 19, 2012

openmikes.org blog

New Feature: Subscribe to Local Listings

openmikes.org lets you find open mikes in a variety of ways, but it's always been up to you to drop by and search. As of today, there's something new.

When you search for open mikes near you (via the "Search Near Me" section of the front page), you now have the option to subscribe to that search.

So you're searching for open mikes near Miami, and you choose to be emailed on Mondays:

Email me weekly

Each Monday, you'll receive an email like this:

What's new and updated around you, and what's happening in the week to come. Just what you were looking for, nothing else.

You can remove or update your subscriptions from your profile page:

Manage subscriptions

You'll need to register and log in for all of this to work, but you should do that anyway to add photos, receive notifications of comments on nights you submitted, etc.

by Paul Roub at November 19, 2012 01:49 AM

November 03, 2012

My Upcoming Gigs

Open Mike's, Monday November 12, 2012

Open Mike's, Monday November 12, 2012

454 N Harbor City Blvd
Melbourne, FL
321-254-5645
https://www.facebook.com/openmikes1

by Paul Roub at November 03, 2012 06:43 PM

November 01, 2012

October 04, 2012

September 30, 2012

September 28, 2012

Personal Blog

TextExpander Snippet: Extract the Real URL from a Google Search Results Link

The Problem

You’re searching Google, looking for a link to email/blog/otherwise save. In this example, you’re looking for me, but you’re confused as to how my name is spelled.

Searching Google for

Great, let’s grab that first link:

Copy Link Address

Paste that into your text editor, and you see… oh.

Link surrounded with Google tracking data

You can, of course, actually visit the link in question, then copy the URL from your address bar. Or you could edit the URL, turning %2F into / as you go. I’ve done both, thousands of times. So have you. Neither is particularly entertaining.

The Solution

I searched in vain for a TextExpander snippet to take care of this, but I didn’t turn one up. (OK, I didn’t search that hard; writing one is more fun)

Now, after copying the link, I type

;ungoogle

into my editor, and all the tracking cruft is removed, leaving me with:

Plain Link

Getting the Snippet

You’ll need to download and install the Ungoogle TextExpander Snippet, it will be preassigned an ;ungoogle shortcut. Feel free to change the shortcut as you see fit.

One prerequisite: the snippet is actually a Perl script, and you’ll need the URI::Query module installed. sudo cpan URI::Query will do the trick from the Terminal.

You can also just create a new “Shell Script” snippet of your own, and paste in the Perl:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/perl

use strict;
use warnings;

use URI;
use URI::Query;

my $googleUrl = `pbpaste`;

my $uri = URI->new($googleUrl);

if (($uri->authority =~ /google\.com/) && ($uri->path =~ /^\/url\b/) && ($uri->query =~ /\burl=/))
{
  my $q = URI::Query->new($uri->query);

  my %params = $q->hash();

  my $url = $params{'url'};

  print "$url\n";
}
else
{
  print $googleUrl;
}

September 28, 2012 10:12 PM

September 19, 2012

My Flickr photos

DSC_4753

Paul Roub posted a photo:

DSC_4753

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4747

Paul Roub posted a photo:

DSC_4747

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4715

Paul Roub posted a photo:

DSC_4715

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4713

Paul Roub posted a photo:

DSC_4713

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4708

Paul Roub posted a photo:

DSC_4708

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4699

Paul Roub posted a photo:

DSC_4699

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4696

Paul Roub posted a photo:

DSC_4696

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4692

Paul Roub posted a photo:

DSC_4692

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4690

Paul Roub posted a photo:

DSC_4690

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4689

Paul Roub posted a photo:

DSC_4689

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4687

Paul Roub posted a photo:

DSC_4687

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4685

Paul Roub posted a photo:

DSC_4685

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4683

Paul Roub posted a photo:

DSC_4683

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4682

Paul Roub posted a photo:

DSC_4682

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4680

Paul Roub posted a photo:

DSC_4680

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4678

Paul Roub posted a photo:

DSC_4678

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4677

Paul Roub posted a photo:

DSC_4677

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4676

Paul Roub posted a photo:

DSC_4676

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:58 PM

DSC_4675

Paul Roub posted a photo:

DSC_4675

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:57 PM

DSC_4674

Paul Roub posted a photo:

DSC_4674

Shuttle Endeavour is ferried away, as seen from the beach at the south end of Patrick Air Force Base.

by Paul Roub (nobody@flickr.com) at September 19, 2012 12:57 PM

August 31, 2012

August 22, 2012

Personal Blog

Chris Coyier: Don't Overthink It Grids ∞

Boiling (potentially responsive) grids down to their essence. Planning on stealing much of this, soon, for a music site near you.

If a more complex layout presents itself, people often reach for a grid framework. They assume grids are these super difficult things best left to super CSS nerds. That idea is perpetuated by the fact that a lot of the grid systems they reach for are very complicated.

I am a certified CSS nerd, but I’ve avoided rolling my own grids for just these reasons. To be fair, I reached that conclusion a few years ago when certain older browsers were still a non-fractional part of my sites’ visitors.

Life’s simpler in a post-IE7 world.

Permalink

August 22, 2012 02:12 PM

August 06, 2012

Personal Blog

Matt Gemmell: Managing Email Realistically ∞

I could quote-mine this for days. I kept bouncing back and forth between “that’s hilarious”, “I should do that” and “I shouldn’t do that… should I?”

Take a lesson from quantum mechanics: an email isn’t definitively important until you see it. If you don’t see it, it’s not important. It remains in a dead-alive, important-unimportant superposition of states. And who cares about emails like that? Not me.

Permalink

August 06, 2012 01:56 PM

July 30, 2012