May 05, 2009

Since @replies can come from anybody

Someone, let's say Yahoo, could roll out their own twitter-like service (let's call it yatter). And all yahoo mail users "become" yatter users automatically, like how they became Openid accounts.

  1. when a yatter user "joe" yatts, "@twitter/charlie what are you doing?"
  2. yatter's twitter bot called "yatter" relays the tweet, "yatter/joe: @charlie what are you doing?"
  3. twitter user "charlie" sees the message in his @replies stream, and can respond, "@yatter/joe hitting my refresh button again and again"
  4. a yatter.com bot called "twitter" relays the message, "twitter/charlie: @joe hitting my refresh button again and again"
  5. yatter user "joe" sees that in his @replies stream in yatter.com.. (repeat from the top)

I'd guess it makes sense for yatter apis to be fully compatible with twitter.com, in the ma.gnolia.com vs del.icio.us kind of way. So twitter clients just need to add a new config, "hostname", and we're done.

I think yatter.com could technically allow @yatter/joe to follow @twitter/charlie. The question is, would twitter.com allow their @charlie user to follow @yatter/joe?

Yatter could use the age-old hotmail trick and append the latest status message of the mail sender to the email footer. That should pique interests of recipients. Besides, "a signature" is an existing, understood concept that users can easily see why they'd would want to update their "yatter status"..

April 27, 2009

An iPhone optimized web page

The defacto way of making a web page "optimized for iPhone" is to slap on iUI (or variants) to simulate the look & feel of a native app (i.e. the UITableView). You can click on an item in the list, and the page slides sideways to reveal another list, or more details... etc.

However, the starting point of trying to mimic meant we're aiming for the web site's experience is to be worse-or-almost-as-good compared to if it was a native app. e.g. m.cnn.com Can aim to be different instead?

In trying to mimic a native app, the iUI approach locks down the browser's width & scaling capability. I actually liked that part of browsing on the iPhone -- its automatic zoom! To zoom-in, you simply double-tap on an area of the page. To zoom out, double-tap again. (There's pinching, but it is manual & I don't like tedious things)

Unfortunately, most layouts don't make it easy for iPhone to automatically zoom-in. The kicker is, a good & fluid CSS layout actually hinders! e.g. the text is still small after double-tapping on jnd.org

Turns out, the automatic zoom is controlled [only] by the width of the page segment.. meaning, the page's font size can be infinitesimally small -- it doesn't matter. As long as the containing width is also small (e.g. contains 5 words across 1 row), the user can still comfortably zoom in and get big text with sharp font of 5 words across the entire screen width!

Taking this to an extreme, we could have all our site's content render in tiny little font inside narrow columns on 1 single page and the iPhone visitor can still effortlessly zoom in and read everything! No click, ajax, network lag, read content, back, click another, .. etc.. i.e. instead of content hierarchy behind deep navigation, we could have it based on font sizes.

Sounds like a newspaper huh?

To try this out, I'd hacked up this proof-of-concept a few days ago, and have been using it to read my RSS feeds on my bus rides the past few days. While the app itself is not there yet, the zoom interface experiment has really been working out very well!

screenshots

Have an iPhone/iPod touch? Try it and lemme know?

PS: A more extreme sell for a zoom-based UI is Microsoft's famous Seadragon demo.
PS: this whole experiment was sparked off when I tried to read the beautiful hacker-newspaper.gilesb.com on my iPhone.

March 28, 2009

9.99 Reasons to Love IE6

A friend showed me this website today: http://www.bringdownie6.com/ "Bring down!" Such angry words. There's so much negativity on the Internet regarding a browser.

Instead of 1) getting good folks to put feeble badges on websites, or 2) resigning to fate & cursing whenever you have to fire-up IE6 and check, or 3) getting bigger, better tools to do stupid things faster... Maybe we can be more constructive.

Here's an idea:

Dear Developers & Designers,

Save your sanity: At $0.00 cost to you, we make your website work in IE6!

Step 1. Register your website with us
Step 2. Just copy-paste this into your website's <head> section: <script src="http://weloveinternetexplorer.com/bff.js"></script>
Step 3. *chuckle* There's no Step 3!

How this'll work is that, all your IE6 site visitors will be gently redirected to our payment page, explaining nicely:

We're sorry but Website XYZ no longer works with your old, antique Internet Explorer browser. BUT for just US$9.99/month (1 movie ticket!) the hardworking engineers at weloveinternetexplorer.com will fixup the website for YOU, and make this problem go away for you! It'll just take 30 seconds! We accept all major credit cards & Paypal (maybe even 淘宝! Alipay (correction by @xtinegoh) )

But you choose not to :-( you may install any of these free, modern browsers and use Website XYZ through them: [firefox logo] [safari logo] [google chrome logo]

--
WeLoveInternetExplorer.com Team

If the IE6 compatibility work has not been complete yet, the above pay-wall will not be shown. Instead, we'd display a cool 1990s construction worker icon that these folks will be extremely familiar with!

Construct2_e0

All paid users can of course transparently continue to use the web site (and all other websites that uses this service).

PS: Designers & developers that would like to do Internet Explorer compatibility work (yes, all 3 of you out there, 尤其是中国的同胞朋友, Hội lập trình viên Việt Nam, and сотрудник российских программистов !!!!) Please contact me

March 23, 2009

Why pick a different domain name for asset_host - and not just subdomains

Some sites, e.g. Github.com, uses subdomain for images & assets

assets from subdomain

Whereas others, e.g. Yahoo.com, uses a different domain name.

assets from different domain

Because cookie bandwidth does add up.

PS: I spot George Oat's picture on Flickr frontpage still. I wonders if it is a form of respect or neglect.

March 19, 2009

How to really Post Load Google Ads (while keeping document.write happy & page rendering snappy)

So you have a web page and it is getting some hits. One day, you decide you might as well earn some pennies off that traffic and began copy-pasting some Google Ads into it.

But you know, Google Ads suck. They use document.write. Yep, the things we were warned against. But that's not all. Their document.write actually pulls in more javascript, which in turn say "weeeeell, while we're at it!" and start to do even more document.write! (In this aspect, Microsoft ads seem more thoughtful, or it seems from Digg's homepage).

Anyways, this chokes the browser & makes them stutter. Your web page now renders to your audience in stops and starts:

some content appear > ads appear (stall) > more content appear > ads appear (stall) > rest of content appear


A necessary evil? There are a few things that will fix to a certain extent: 1) use "script defer" or 2) hacking document.write. Not ideal in terms of fragility, and subsequent maintenance of ads embed codes.

Let's look at the problem again: 1) Google wants you to paste the script where the ad appears, 2) Wherever the script is pasted, the browser will stutter & stall the content that comes after it.

For #2, maybe the "solution" is to paste the script AFTER all content? But wait -- doesn't that mean #1 the ads get rendered there & not where I want them? Yes, but only initially.

Why not reposition these ads to where they're supposed to be after they are constructed:

all content appear > ads appear (below the fold, stall) > ads appear in position

Let's say that works, unfortunately it sound convoluted & a hassle, the site has too many existing ads to migrate & our guy managing the ads doesn't code, he just copies whatever Google provides & blah blah blah...

That's what the postload_google_ads Rails plugin is for :-) site-wide benefit for minimum fuss (upfront & subsequently)

To see it in action, see this demo. Click on "Before" and "After". They 2 pages are essentially the same, but only one of them applies an "after_filter":

The postload_google_ads plugin is an "after_filter" in Rails. This means that after your webapp has done its thing & generated the dynamic HTML, the after_filter transplant the ads' script tag to the bottom of the DOM tree, leaving behind some placeholders. This modified html is then sent back & rendered on the user's browser. After all your content renders, the ads will construct themselves (document.write all they want). After the ads are done, a little javascript repositions the rendered ads based on the absolute position of their corresponding placeholders.

Until ads nework catch up to use unobtrusive javascript, I guess I'll have to settle for this.

November 16, 2008

git svn rebase - could not detach HEAD (howto fix)

Sounds gross but that is the curt message:

$ git svn rebase
...
First, rewinding head to replay your work on top of it...
could not detach HEAD
rebase refs/remotes/trunk: command returned error: 1


Not very helpful, no clue, can't even buy a vowel. But if you try something else, the error message begin to make the problem more obvious:

$ git co refs/remotes/trunk
error: Untracked working tree file 'public/images/plugout_button.gif' would be overwritten by merge.


Well... then git-svn should've said so!

$ rm public/images/plugout_button.gif
$ git svn rebase
First, rewinding head to replay your work on top of it...
Applying ....


So there. This post is so that I commit it to my long term memory, aka Google.

October 02, 2008

hquery: an unobtrusive server script implementation

I'd previously blogged about some ideas to resolve the developer-designer gulf regarding templates. I'm happy I've finally found time to code up a proof-of-concept:



hquery - the unobtrusive server script from choonkeat on Vimeo.
Q: What is "unobtrusive server script"?

If "unobtrusive javascript" adds interaction to a web page without being inside the markup - then "unobtrusive server script" replaces data in a web page without being inside the markup (and design).

You'll get a clean separation of 1) designed web page is constructed, then 2) server data is weaved in, and finally 3) javascript hooks up the interactive portions.

The key thing is that all 3 layers are stringed together by CSS path - a concept / language that both designers and developers can communicate with.

Q: Is this a silver bullet?

No. There are constraints: everything that needs to be dynamic, need its own CSS/XPath. e.g. Google's result page markup isn't very suitable:

  <div>this is abstract<cite>citation</cite></div>

Notice how we can't address the abstract content without stepping on <cite>. When using USS, we'll need the markup to be:

  <div><span>this is abstract</span><cite>citation</cite></div>

Then both abstract and citation can be targeted independently. Furthermore, to be totally isolated from markup changes, it is best to only use classes and ids without the tag names.

Q: Is USS a Ruby on Rails thing?

Nope. "hquery" is just a library I wrote to do USS in Rails. I believe any language / framework can have its own USS renderer.

Q: How do I write javascript that needs dynamic values?

Instead of writing mixed-up code like this:

<script>
  alert("I am <%= user.name %>");
</script>


Try doing it this way (separating data from logic):

<div id="json"><script>var user = {name: 'foo'};</script></div>
<script>
  alert("I am " + user.name);
</script>


Then in your script, you can swap out the JSON data:

select "#json script" do |ele|
  ele.html "var person = " + current_user.to_json   
end


Q: Where next?

I dunno. Since hquery script is declarative, we can compile to regular <% messy %> template as runtime? Or, have build tasks that can check that corresponding HTML contain necessary elements - i.e. a new design don't break/miss out anything?

Anything else? Love to hear your thoughts!


PS: I find myself trusting Yahoo search results when its in Google skin!


July 08, 2008

So love this film

June 04, 2008

USA, Google IO and RailsConf '08

This is a brain dump, knowing that if I don't write this now, I probably won't ever.

USA
They say the weather in San Francisco is perfect, but I think I'd prefer 8 degrees (celsius) warmer.. then it'll be really perfect. (And for my friends complaining their MacBook Pro runs hot... its a geographical/design problem, you see the CPU fans will never kick in here ;-)

A "quarter" is a really unproportionately valuable coin. Its a popular choice everywhere and you'll never have enough of it. I'm not sure if I can keep up, collecting 12 of them for my weekly laundry.

On the street, there is no "green man" for pedestrians. Its a myth. The man is white. Lines across a junction means nothing, but a double-yellow in the middle of the road means it is 2-way. Turn right on red light is the default.

Google is much more valuable in the States. The level of integration (and ease of use!!) they provide with real-world services is certainly something drool-worthy for Singaporeans. For example, look at this map. Something a lot of ppl I talked to didn't realise is the information on the left pane: Public Transit. It has price, train schedules (go to options & choose when you wanna arrive). A tourist like me can really survive on Google. Just add free wifi.

The night before driving to Big Sur, we went Google Earth surfing to recce the place. After been there for real, I think Google Earth redefines WYSIWYG.

Google IO
2 things impressed me: Android demo and the food.

For the 2 of you who haven't read, the Android demo in the first keynote was really impressive. Clearly iPhone inspired, but not as sheek.

A "home" screen where you use swipe gesture to scroll. Favorite apps anchored at bottom. Press and hold to drag icons around. A Webkit browser means all their previous iPhone mods for google search, mail, etc now works the same in Android.. such coincidence. I bet screen dimensions will match as well.

Best of all, a Google Maps "Street view" was demoed. It was really, really smooth. Holding it up and pointing your device north or south will actually swivel the street view to match your direction - how cool is that! Come to think of it, a compass is for street view might be a bit gimmicky. But if the compass works for google maps itself (where the maps rotate appropriately) now THAT will be cool.
[Update: This is do-able indeed on Webkit!]

RailsConf 08
My favourite part of the conference is the first lightning talk where I signed up and demo SharedCopy. This is the response in the IRC channel (roughly the same from the floor)

Response to SharedCopy Demo [RailsConf 2008]

[screenshot donated by Chu Yeow - thanks!]

It is hard to do SharedCopy justice by describing it in words. It needs a demo. I'm glad I had the chance to do a quick one in RailsConf. My only regret is that I forgot to show the read-later feature.

Now Maglev is really interesting. Avi's showmanship definitely helped (he was putting and pulling rabbits out of the hat across different Ruby VMs). But Maglev is interesting in a different way JRuby / Rubinius is. The latter 2 effectively replaces MRI. Maglev however brings the Smalltalk way of doing things with it - if you have object persistence, why use a database? i.e. A regular joe Rails app may choose to run on MRI, JRuby or Rubinius. I don't see Maglev having much incentive (and interest) to run a regular Joe Rails app other than marketing purpose. Their vision is to run Ruby/Rails apps architected in an entirely different way. Hence, their paths don't really meet.

There are gripes about the conference though. Some keynotes were really uninspiring (compared to RailsConf '06) the upside is I got my mod_rails working during one of the keynotes! And as if finding (cheap) hotels for a conference wasn't hard enough, it had to coincide with Portland's Rose Festival. Doh!

May 26, 2008

Something's Gotta Give

Saw this clarification on TC regarding Twitter
the issue certainly isn’t with creating new messages, the issue is when you check your own messages For eg, if I am following 200 people, the query needs to check the new messages from all those people and sort them into date order. That query would be really intense link »
- from Twitter At Scale: Will It Work? via sharedcopy.com

I'd heard that earlier in the Gilmor Gang : Blaine clarified that static resources (e.g. profile images) are no issue at all, and that the the bigger issue is with each person's "home page", where multiple streams are joined and ordered chronologically. When 1 of the connected people update, all related cached "home pages" are obsolete - hence they are generated painfully often. (so don't refresh your own page so much!)

I'm not a scaling expert. Nor do I know anything about Twitter's real problems. So treat this as noise maybe.

Anyways, ignoring other things unknown and purely focusing on this particular aspect... I thought it'd be interesting to consider what we might gain, if we're just willing to give up certain things?

So.. assuming static resources ain't a problem, lets try to have more of those! A single person's stream (without friends) looks cachable - like a blog that generates html instead of serving dynamic. A single person's social graph (following who) looks cachable as well. If assumptions are wrong here, then exit(1); So a person's homepage is his own static stream with static external references to static streams of ppl he follows. Like a html page referencing a bunch of CSS. No server side join or sort. Instead, the browser, with the help of some static javascript, pulls in those resources, does the merging and sorting (and paging) and spit a pretty display similar to the current. i.e. every user's browser does its own merging and sorting, you know... like, help out will ya?

Would that be better? And what did we give up? The ability to properly browse your own Twitter homepage on a browser without JS & clients using API need a few more pulls and do merging / sorting themselves too.

Can we live with that?

Update: Slim pointed to an article in the comments, and "Part III" of that article, Eran had talked abt the same alternative:
if you only ask this once, the server side batch solution will be faster. But when the client starts asking this once a minute or more repeatedly, resources go to waste and scalability is more expensive. link »
Once the server is only serving data with limited scope, usually providing the messages of a single person with the optional perspective of the reader (to enforce access control), scaling becomes a much easier task as data can be segmented easier. link »
- from Hueniverse: Scaling a Microblogging Service - Part III via sharedcopy.com

Update: Then again, you have scoble who follows 30k other people making it impractical for the client to fetch those streams independently... I guess most systems would decide to place limits and "punt" the issue, e.g. you can have at most 5000 friends. And that's something Twitter is unwilling to let go.

Blog powered by TypePad