tag:blogger.com,1999:blog-25619945687689214312024-02-06T19:26:00.502-08:00Sordina ProductionsSordina Productions - Minimalist Web-DesignLyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-2561994568768921431.post-88007539052099475952013-05-01T06:34:00.000-07:002013-05-01T06:34:01.877-07:00Marketing by 'N'Hi all.<br />
<br />
I've recently completed a new site for up and coming graphic-designer / photographer, Natalie Spa. The site is called <a href="http://marketing-by-n.net/">Marketing by 'N'</a> and was written in Ruby on Rails.<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrIx0LPMhnbLg7dHyJsH5VvI43CZW0vA1bIQs7Bcv-stt5ka286uIvSDWLlYJmfmkZVkmVEM8ku2y1yVdV9av5eJ7Mar4UGvPul2armM7cAT5K-yPIvazPnijCgzsZez2HECKwT2KtzCt1/s1600/Screen+Shot+2013-05-01+at+9.31.22+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="297" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrIx0LPMhnbLg7dHyJsH5VvI43CZW0vA1bIQs7Bcv-stt5ka286uIvSDWLlYJmfmkZVkmVEM8ku2y1yVdV9av5eJ7Mar4UGvPul2armM7cAT5K-yPIvazPnijCgzsZez2HECKwT2KtzCt1/s320/Screen+Shot+2013-05-01+at+9.31.22+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Marketing by 'N'</td></tr>
</tbody></table>
<br />
<br />
This project introduced me to the joys of ruby-gem conflicts in the way that only a bath of fire can. So many tears were shed at the hands of incompatible versions of rails, active-scaffold, acts-as-taggable-on, etc. I'm glad they all got sorted out in the end.<br />
<br />
I'm sure you'll enjoy the services that Natalie is offering on this site if you take a look :-)Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com1tag:blogger.com,1999:blog-2561994568768921431.post-27416384997276476552013-04-13T06:09:00.000-07:002013-04-13T06:09:08.551-07:00HaskellI want Haskell to be my primary language for new projects.<br />
<br />
It isn't currently, and I don't think it will be for a while. This is due to difficulties I have with the libraries I need to get things done. Yesod is wonderful, but I don't fully grok it yet. I can almost always get web-development done faster in another language. A deep understanding is often required to make progress, this takes time. But still, I love it.<br />
<br />
I feel that I'm on the edge of programming nirvana, with just a small deficit in my understanding preventing me from leveraging this language in order to be the most productive I've ever been. So... Why?<br />
<br />
<br />
<h2>
What is it about this language that keeps me coming back?</h2>
<div>
<br /></div>
<br />
I first played with Haskell in first-year com-sci on my own time as I had heard that it was a really cool piece of technology. It was around the time that I was experimenting with all sorts of .... languages; From Python to Prolog, Scheme to SML, BASIC to Brainfuck. I gave Haskell an ernest shot but I found it incomprehensible and impenetrable. It was mostly my own fault. When trying a new language there are two main ways to go about it -<br />
<br />
<br />
<ol>
<li>Take what you know from elsewhere and see how it fits, or</li>
<li>Drink the Cool-aid</li>
</ol>
<br />
<br />
Unfortunately for me I tried the first option, one which Haskell doesn't lend itself to very readily. I would attempt things that I would often do in other languages, such as making heterogeneous lists, class-hierarchies, singletons, etc. While Haskell can do all of these things, they are usually used as intermediate techniques and not brought to bear on simple problems. So I looked at the code I wrote and thought - What is this ugly crap? Why does it have to be this complicated? This isn't intuitive at all.<br />
<br />
I gave Haskell a break for the next two years.<br />
<br />
<br />
<h2>
Haskell Again</h2>
<div>
<br /></div>
My next attempt at learning Haskell was to work through the Project Euler [2] problems. I blazed through the first 50 of these mostly by using brute-force solutions that were more than fast enough given Haskell's native speed. This time I started to understand the Haskell way of getting things done.<br />
<br />
I've subsequently published about 35 Haskell repositories to Github [3] and contributed back to around 4 well known projects.<br />
<h2>
<br /></h2>
<h2>
Why do I think Haskell's ideas will be part of the future of programming?</h2>
<div>
<br /></div>
<div>
<br /></div>
<div>
Haskell features several concepts that are just too good to ignore.</div>
<div>
<br /></div>
<h3>
<br /></h3>
<h3>
Static types</h3>
<div>
<br /></div>
Haskell's type-system is second to <strike>none</strike> many research-languages, but is very good none-the less. After using Java, C, and C++ extensively in undergraduate studies, Ruby felt like programming nirvana to me and so I attributed this to the power of dynamic type-systems. My bad. In actual fact many languages have very primitive and prohibitively cumbersome type-systems. Haskell's is the complete opposite. Powerful, Terse, Expressive, and if needed, implicit.<br />
<br />
Many fans of dynamic languages say that you don't gain anything from a static type-system as you should be unit testing your code. I don't disagree that tests are a very valuable tool, but types and tests do not fulfil the same role, although there is some overlap. A good design of your program's types will negate the need for many tests, and the ones that you do need to write will be assisted by having a strong static type system to help generate values, and guide the design of your tests.<br />
<br />
I have found that my workflow is somewhat different when writing Haskell. I engage heavily in Type-Driven-Development. Writing out my program as a data-transformation pipeline and ensuring that the types of the segments line up, leaving the bodies undefined initially, filling in the pieces in the most-obvious fashion, then engaging in equational reasoning to refactor my source into a better form.<br />
<h3>
<br /></h3>
<h3>
A good REPL</h3>
<div>
<br /></div>
<div>
It's true that Haskell's REPL isn't as good as a good lisp's, but it is certainly better than the average REPL. The ability to test the types of ad-hoc values, browse module, and jump into an editor where required really speeds up your workflow. Also, the ability to script the REPL comes in very handy for writing Vim scripts, etc.</div>
<h3>
<br /></h3>
<h3>
Laziness [4]</h3>
<div>
<br /></div>
<div>
This is a contentious point, but the ability to not have to worry about the order of my source-code really frees me up in terms of concentrating on the obvious first. When I wrote a project in Clojure it was jarring having to declare my functions or write them in their dependent order. Even most OO languages are more flexible than this tanks to functions being grouped into classes.</div>
<div>
<br /></div>
<div>
Haskell is certainly the laziest language I've ever used, with perhaps the exception of Prolog. The canonical fibonacci definition of (fibs = 1:1:zipWith (+) fibs (tail fibs)) goes a ways to demonstrate the depth that this laziness descends to.</div>
<h3>
<br /></h3>
<h3>
Good syntax</h3>
<div>
<br /></div>
<div>
Some people consider syntax to be largely irrelevant to the quality of a programming language, I am not one of these people. I'm from that camp that the more often you use something, the better quality that thing should be. That's why I bought a good razor to shave with, etc. If I'm going to be battling with syntax every time I define a function, declare a type, construct a data-structure, meta-program, etc. I will GET PISSED OFF. Full stop. So far, Haskell's syntax has not pissed me off. This is a very good thing. GHC's extensions also go a long way to help with many sticking points: Just yesterday I discovered the View Patterns [5] extension that generalises pattern matching to abstract data. You could try a new extension every week for a year and still have some left over.</div>
<h3>
<br /></h3>
<h3>
Speed</h3>
<div>
<br /></div>
<div>
Haskell isn't the fastest language in the world, but it is fast. And you can tweak it to be very fast. And if you can't do that, then the FFI is first-rate. So far I haven't had any issues with speed, although obviously you're going to be mostly limited by the algorithm you use. Thankfully, in Haskell, refactoring your algorithms is pure joy!</div>
<h3>
<br /></h3>
<h3>
A great compiler</h3>
<div>
<br /></div>
<div>
GHC is possibly the world's most advanced compiler. Well, I jest, but it's up there with LLVM that's for sure. The optimisations that it performs are mostly high-level at this stage, but they can be quite amazing.</div>
<h3>
<br /></h3>
<h3>
A great community</h3>
<div>
<br /></div>
<div>
I have not yet come across any abrasive personalities from the Haskell community. Also, nobody is beyond reach. You can literally talk to anyone in the community without fear of rebuke (provided you're not totally out of line). There are great mailing-lists, irc-channels, Google Plus communities, etc. Everyone is super friendly and super helpful [6].</div>
<div>
<br /></div>
<div>
The only issue you will come across is the tendency of some people to offer up more general solutions than you might be looking for. This is usually a kind of humor, however, looking into the concepts alluded to is rarely a waste of time.</div>
<div>
<br /></div>
<h2>
<br /></h2>
<h2>
Links</h2>
<br />
<ol>
<li><a href="http://www.haskell.org/haskellwiki/Haskell">Haskell</a></li>
<li><a href="http://www.haskell.org/haskellwiki/Haskell">Project Euler</a></li>
<li><a href="http://github.com/sordina">Sordina's Github</a></li>
<li><a href="http://en.wikipedia.org/wiki/Lazy_evaluation">Lazy Evaluation</a></li>
<li><a href="http://hackage.haskell.org/trac/ghc/wiki/ViewPatterns">View Patterns</a></li>
<li><a href="http://www.reddit.com/r/haskell/comments/1bcqvw/trolling_haskell/">Trolling Haskell</a></li>
</ol>
<br />
<br />Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-72963992127535533522012-08-16T09:08:00.003-07:002012-08-16T09:09:04.008-07:00Meteor - An Exciting DevelopmentIf you haven't seen the <a href="http://news.ycombinator.com/item?id=4049250">Hacker News post</a> about Meteor being <a href="http://gigaom.com/cloud/scoop-meteor-gets-9m-in-funding/">funded $9M</a> this month, then let me tell you a little about this framework since it is the first web-framework I have been excited to use <b><i>in practice</i></b> in a long time.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="margin-left: auto; margin-right: auto;"><a href="http://www.blogger.com/goog_1953904642"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH8ssRKr0DIofSLNNXd28WGkKishME-o74TQ1VfaPjYphlv67uqhAdUUs5BQ6QAtofIkrQpH8C4uTMuS7trm1tnaeORUle5YuKuodvfjInzwn4O9gg-mjyc_Brxg5g9thGgmattTx1PWsk/s1600/Screen+Shot+2012-08-16+at+11.26.39+PM.png" /></a></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="http://meteor.com/">Rapidly develop Web-Applications</a></td></tr>
</tbody></table>
<br />
The premise is quite simple -<br />
<br />
<ul>
<li>A pub/sub model</li>
<li>A (locally cached) DB API from the client</li>
<li>Template data-dependency driven updates</li>
</ul>
<div>
<br /></div>
<div>
But what does that mean in practice?</div>
<div>
<br /></div>
<div>
<ul>
<li>Create Collection Objects (Mongo Tables) on your Server and Client</li>
<li>Create event hooks in your client code that update your DB and your Session appropriately</li>
<li>Define templates that render your objects (and others to render the page-chrome)</li>
<li>Create dynamic subscriptions to data</li>
<li>Create parameterised data publications on your server</li>
</ul>
<div>
That's about it for a basic app. I have created a small example app at <a href="http://mathfriends.meteor.com/">mathfriends.meteor.com</a>.</div>
</div>
<div>
<br /></div>
<div>
So what do each of these practical steps involve?</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHrlsXTEbjxgy3Zm0EBRLXGV_e0r2UTasNdBsmhTQKpeIsEcmp73qQ5Aaq2c9dXFv3n_FmeF1JjMZuGTLlrWWHd3fkfNeYzuB0YTHDwZ_T1vhrgAdGpOTDugV8vKiOkfPS9fkcQCThqCQ/s1600/Screen+Shot+2012-08-16+at+11.39.20+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="133" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimHrlsXTEbjxgy3Zm0EBRLXGV_e0r2UTasNdBsmhTQKpeIsEcmp73qQ5Aaq2c9dXFv3n_FmeF1JjMZuGTLlrWWHd3fkfNeYzuB0YTHDwZ_T1vhrgAdGpOTDugV8vKiOkfPS9fkcQCThqCQ/s320/Screen+Shot+2012-08-16+at+11.39.20+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The <a href="http://mathfriends.meteor.com/">MathFriends</a> Example App</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<i>"Create Collection Objects (Mongo Tables) on your Server and Client"</i></div>
<div>
<i><br /></i></div>
<div>
This is achieved by using the Meteor API to create new Collection objects:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9maDrHYVS1hTBvWGbYy-5yumOxhs1QKlYgxgQ4-w-c20vwN5vKvRVf_tEZhzJBMgvJakzQbOJaTF2FLjYZmiiOh-xj9bJurx36lefDq5A514qeHTUZDtG3eZom7fFMo0T_EGPlSPTadjH/s1600/Screen+Shot+2012-08-16+at+11.47.28+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="56" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9maDrHYVS1hTBvWGbYy-5yumOxhs1QKlYgxgQ4-w-c20vwN5vKvRVf_tEZhzJBMgvJakzQbOJaTF2FLjYZmiiOh-xj9bJurx36lefDq5A514qeHTUZDtG3eZom7fFMo0T_EGPlSPTadjH/s320/Screen+Shot+2012-08-16+at+11.47.28+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Defining 'Snippets' and 'Users' Collections</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<i>"Create event hooks in your client code that update your DB and your Session appropriately"</i></div>
<div>
<br /></div>
<div>
This involves listening for an event and updating your DB or Session accordingly. Logging out the current user is as easy as you might expect:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha_1jAdu1ycNQ3fVQym8ksKCgiJr_PqwqbGfLbifhJtNZqg0gTqDZnH3sc3KPZ18RfO-JiGBqa1gURnw_5IIyElS5IUEGdXPLgA9res5SHAaMCEvnxTwIxrbWZdMsDIdvDlTUlw7ixQs4M/s1600/Screen+Shot+2012-08-16+at+11.44.31+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="20" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEha_1jAdu1ycNQ3fVQym8ksKCgiJr_PqwqbGfLbifhJtNZqg0gTqDZnH3sc3KPZ18RfO-JiGBqa1gURnw_5IIyElS5IUEGdXPLgA9res5SHAaMCEvnxTwIxrbWZdMsDIdvDlTUlw7ixQs4M/s400/Screen+Shot+2012-08-16+at+11.44.31+PM.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Listen for a 'logout' click - Set the user to null.</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<i><br /></i></div>
<div>
<i>"Define templates that render your objects (and others to render the page-chrome)"</i></div>
<div>
<br /></div>
<div>
The templating engine used by default is <a href="http://handlebarsjs.com/">Handlebars</a>. The variable scope is determined by the data collections being looped over, and the functions bound to that template in your client-side js:</div>
<div>
<i><br /></i></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUhxgorJXJaBFIHL5Pzxlmmg-VnIqvU4x67p1rBHv2WSCnpbgQTEQ0cC6ezCUWmHCmcLLB_IAfvJP4cJShX-yty8m0QZsb-ZVpNqzX6u1GnAwgjAINvlfn1ZsFgcabJ9730Xxb9y7MnSmY/s1600/Screen+Shot+2012-08-16+at+11.51.02+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="154" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhUhxgorJXJaBFIHL5Pzxlmmg-VnIqvU4x67p1rBHv2WSCnpbgQTEQ0cC6ezCUWmHCmcLLB_IAfvJP4cJShX-yty8m0QZsb-ZVpNqzX6u1GnAwgjAINvlfn1ZsFgcabJ9730Xxb9y7MnSmY/s320/Screen+Shot+2012-08-16+at+11.51.02+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Showing the list of MathFriends users.</td></tr>
</tbody></table>
<div>
<i><br /></i></div>
<div>
<i>"Create dynamic subscriptions to data"</i></div>
<div>
<br /></div>
<div>
Subscriptions to data-sources can be handled manually, however, Meteor provides a way to automatically update the subscription when the dependencies change:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhezEMDa5PUl3AdjmP2UwCYm6uZt_ffbMRsg5yAGwAI2PpUKjxhcSig39HvHIng3cH1lKiG0qISiqtvVnsjRXMIPFvrS2t4vWmYSv5sH8SoDLLoGxALdlWJ_C9FHdemraoMVBri6nDIM3Am/s1600/Screen+Shot+2012-08-16+at+11.55.11+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="43" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhezEMDa5PUl3AdjmP2UwCYm6uZt_ffbMRsg5yAGwAI2PpUKjxhcSig39HvHIng3cH1lKiG0qISiqtvVnsjRXMIPFvrS2t4vWmYSv5sH8SoDLLoGxALdlWJ_C9FHdemraoMVBri6nDIM3Am/s320/Screen+Shot+2012-08-16+at+11.55.11+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Adding a dynamic data-subscription.</td></tr>
</tbody></table>
<br />
<div>
<i>"Create parameterised data publications on your server"</i></div>
<div>
<i><br /></i></div>
<div>
Every subscription references a corresponding publication. These may be parameterised arbitrarily:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRefMv1hFpgI8GA_75clDnYlstZD7AG6bh7SJg1siL2hNQ1J14rMKkgrRspeB40ew19P30c-niFJY9V_h9v-MgXJzTMrsWr9NAVHL2vwx2lGAWdgIWQfp6IsxumkRNJ5JzzJEk9ZPmxNxx/s1600/Screen+Shot+2012-08-16+at+11.57.58+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRefMv1hFpgI8GA_75clDnYlstZD7AG6bh7SJg1siL2hNQ1J14rMKkgrRspeB40ew19P30c-niFJY9V_h9v-MgXJzTMrsWr9NAVHL2vwx2lGAWdgIWQfp6IsxumkRNJ5JzzJEk9ZPmxNxx/s320/Screen+Shot+2012-08-16+at+11.57.58+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Creating a data-publication parameterised by the currently selected user.</td></tr>
</tbody></table>
<br />
<br />
<br />
<div>
What does this buy us?</div>
<div>
<br /></div>
<div>
It means that when your data-store is updated, the changes are propagated to the clients and re-rendered automatically. Thanks to a local-cached subset of the data-store, interface affecting changes are re-rendered instantly on the client that made them.</div>
<div>
<br /></div>
<div>
Does this mean that your entire page is rendered every time you make a small change? No.</div>
<div>
<br /></div>
<div>
The changes are diffed against the dom and spliced in without updating large sections of the page unnecessarily.</div>
<div>
<br /></div>
<div>
Quite amazing.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
There are currently a couple of major caveats, but the main one is:</div>
<div>
<ul>
<li>Auth is a work in progress</li>
</ul>
<div>
This is currently being addressed in the <a href="https://github.com/meteor/meteor/tree/auth">auth branch on Github</a>.</div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
If you would like to take a look at the example site I was demonstrating, <a href="http://mathfriends.meteor.com/">it is also available on Github</a>.</div>
Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-34721192157895081152012-07-14T10:40:00.002-07:002012-07-14T10:40:56.066-07:00New Logo<div>
Finally got around up updating the logo for this blog:</div>
<div>
<br /></div>
<br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc56bP-JfjDz341_97ljSiF0xIAuzejgZv8qQYQvlXPIeAfd6qiIbH89Yg_niuVR3XYlXd9KpFHRO-7BiaF4_DFa1CDNPqj-482yjKElTcMAfcIDpTwiUlfsjCFbH2JLyek1IuWOoJVGxq/s1600/Screen+Shot+2012-07-15+at+1.14.05+AM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhc56bP-JfjDz341_97ljSiF0xIAuzejgZv8qQYQvlXPIeAfd6qiIbH89Yg_niuVR3XYlXd9KpFHRO-7BiaF4_DFa1CDNPqj-482yjKElTcMAfcIDpTwiUlfsjCFbH2JLyek1IuWOoJVGxq/s1600/Screen+Shot+2012-07-15+at+1.14.05+AM.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Mute - Signifies Minimalism</td></tr>
</tbody></table>
<br />
What do you think?Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-17241744001545502772012-07-14T10:28:00.001-07:002012-07-14T10:30:48.403-07:00Priam Bacich - MusicianI have recently published a small static-site for musician - <a href="http://priammusic.net/">Priam Bacich</a> in conjunction with Natalie Spa. For this project I've taken a back-seat in the design department as Natalie was keen to put her skills to the test, so I focused purely on the technical details.<br />
<br />
This site was an entirely static affair, which allowed me more flexibility with how I generated the content. I explored several Ruby based static-site generation frameworks, however, I found that the most effective method for me was to reuse the dynamic-site frameworks using <a href="http://www.sinatrarb.com/">Sinatra</a> I had previously developed and just crawl these locally with wget.<br />
<br />
The result of this was that I could save development time by having the site update automatically for inspection during development without having to run an 'export' task between changes.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr_RHk2A2rDdz-UZV3r7o9dF_sWoxqOtYgqdZNm7DAN30wjXQIUv2A6dESD3wlDxFdhVcjzs2gKf3Ta-xtTsxRHg-rrdWdFzDQtaRXXd-g1ZSaFxN2Ld7as3vdM5EXvVBuvDjzSPXzWo-Y/s1600/Screen+Shot+2012-07-15+at+1.17.01+AM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr_RHk2A2rDdz-UZV3r7o9dF_sWoxqOtYgqdZNm7DAN30wjXQIUv2A6dESD3wlDxFdhVcjzs2gKf3Ta-xtTsxRHg-rrdWdFzDQtaRXXd-g1ZSaFxN2Ld7as3vdM5EXvVBuvDjzSPXzWo-Y/s320/Screen+Shot+2012-07-15+at+1.17.01+AM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Priam Bacich on the Web</td></tr>
</tbody></table>
<br />
I've also begun experimenting with <a href="https://www.cloudflare.com/">Clourflare</a> to speed up load-times for static content. If you haven't used this service before I'd recommend giving it a try. There are few times that I've experienced a truly water-tight abstraction, but this is one of them. Absolutely, stunningly well done. The fact that this is offered for free boggles my mind.<br />
<div>
<br /></div>
<div>
I'll be writing a post about Cloudflare soon as I feel that I've just glimpsed the tip of the ice-berg here.</div>Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-14671277766995817832012-03-10T22:04:00.000-08:002012-03-10T22:04:44.178-08:00Meta-Circular StartupI'm investigating abstracting the process of bootstrapping by bootstrapping the process of abstraction introspectively. More to come.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-22188776252827375402011-12-09T23:05:00.001-08:002011-12-09T23:06:27.501-08:00A New Site - S.K. Dental<div>Sordina Productions is pleased to announce the arrival of a new site in our portfolio - <a href="http://skdentalperth.com.au/">S.K. Dental</a>:</div><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwxcRd0MvuSgWnMiSEJEcyAv96Y9JH_SBlOefi6IYMNjWaImT1WfhnC5kYJIyycX_ZOy9NMa3pYLse_J7BzthLa3YURA6REgMmrsjyPeQKlbmg7l4WtYpeK9RB_ZOWU6DjBguO8JpQp0WA/s1600/Screen+shot+2011-12-10+at+2.48.43+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjwxcRd0MvuSgWnMiSEJEcyAv96Y9JH_SBlOefi6IYMNjWaImT1WfhnC5kYJIyycX_ZOy9NMa3pYLse_J7BzthLa3YURA6REgMmrsjyPeQKlbmg7l4WtYpeK9RB_ZOWU6DjBguO8JpQp0WA/s320/Screen+shot+2011-12-10+at+2.48.43+PM.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">S.K. Dental's Homepage</td></tr>
</tbody></table><br />
<br />
<br />
Owned and run by <a href="http://skdentalperth.com.au/team#sk">Seng Kian Gan</a>, <a href="http://skdentalperth.com.au/">S.K. Dental</a> offers the latest in dental and periodontal care for Perth residents.<br />
<br />
S.K, as he likes to be called, has been a wonderful client for Sordina Productions and together we are striving to ensure that your experience with S.K. Dental's new homepage is as smooth and enjoyable as possible.<br />
<br />
For this site, Sordina Productions has chosen to use a combination of Ruby tools including:<br />
<br />
<br />
<ul><li>Sinatra</li>
<li>Haml</li>
<li>Sass</li>
<li>Heroku</li>
<li>... and many more.</li>
</ul><br />
<br />
This has enabled us to rapidly prototype new ideas, and in conjunction with the dead simple rerun gem and Git branches, the ability to switch a staging site between completely different designs with no downtime:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgft5ZHdMZFxZbYuOt0EMutbrR9bdwT4WuiaspnqABnhMVBYHLc-psnNNHNol-wGcU8pX0gkiz1kAOullwg4lysmnczB6oFrlVTl0E_rG2O0B8I8x6tRID_2-4aB5aKyvTCfJXUzSHHqruv/s1600/rerun.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="35" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgft5ZHdMZFxZbYuOt0EMutbrR9bdwT4WuiaspnqABnhMVBYHLc-psnNNHNol-wGcU8pX0gkiz1kAOullwg4lysmnczB6oFrlVTl0E_rG2O0B8I8x6tRID_2-4aB5aKyvTCfJXUzSHHqruv/s320/rerun.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Rerun is used to unsure that the server is restarted when special resources are changed.</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVLJwvJ59l-lV9LzNeSiPKPiEuC8FZGndHaKgBI2aLY0Ff_E2fixyFmCZVdhF8n0x-tV7DWsbPfuaofXyelnOYnAY8mRLNZy37jLrUuv4GLqN-W-QU5ih4ZuEsmr4ppl_zoHdxDZ7lh2x5/s1600/master.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVLJwvJ59l-lV9LzNeSiPKPiEuC8FZGndHaKgBI2aLY0Ff_E2fixyFmCZVdhF8n0x-tV7DWsbPfuaofXyelnOYnAY8mRLNZy37jLrUuv4GLqN-W-QU5ih4ZuEsmr4ppl_zoHdxDZ7lh2x5/s320/master.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The site is currently rendering the 'Master' branch.</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfYWZokSaJW-BlMglGa5u17gSBANeuVWCH3Yksgxaurwe-K_xCoEeNg3ar3j4zmKQRUawPT1rBnn3OxE8EUaOMcpzsk3q4n9gRBBZaWvAL0t-vXI24bqPvruCa2LQDZZc1diiVt_v1bJJ/s1600/branch.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="29" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjfYWZokSaJW-BlMglGa5u17gSBANeuVWCH3Yksgxaurwe-K_xCoEeNg3ar3j4zmKQRUawPT1rBnn3OxE8EUaOMcpzsk3q4n9gRBBZaWvAL0t-vXI24bqPvruCa2LQDZZc1diiVt_v1bJJ/s320/branch.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The branch is switched to 'Abstract Art'.</td></tr>
</tbody></table><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFGCpdUYiVelnsP_0EKRGKm3pbVtdXSv1NBfIIvEjpVOoHbTIjxvnbeyEp6nrlEpoN1LYlp2gDSDRr7sb7DvElR8tmVPyLiJYUVgNe4F9v4cgAJNsRb2uwe2kvabeETPB1nsfIXQ1yWW8I/s1600/art.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFGCpdUYiVelnsP_0EKRGKm3pbVtdXSv1NBfIIvEjpVOoHbTIjxvnbeyEp6nrlEpoN1LYlp2gDSDRr7sb7DvElR8tmVPyLiJYUVgNe4F9v4cgAJNsRb2uwe2kvabeETPB1nsfIXQ1yWW8I/s320/art.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Upon refresh, the browser now displays the new branch.</td></tr>
</tbody></table><br />
<br />
Easy as pie!<br />
<br />
I shouldn't neglect to mention that S.K. Dental is based in <a href="http://skdentalperth.com.au/contact">Forrestfield</a>. Please consider them for your next dental appointment!Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-4106856154040102712011-04-19T09:09:00.000-07:002011-04-19T09:09:28.313-07:00A New Logo in the WorksI've just finished work on a new logo:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD8Y4qb41oW5Ks2mO4TamaANMKuIGZqp1W3kls4clWMQuSbVIPQ-HM_qV66-seXva1HMRI5NZ2ShQFBNarh5Zlan70pgeiErr7X98gTzfPq1vRURB2S5Aze20WF9yCAcw7VB8FftHzp16P/s1600/Screen+shot+2011-04-19+at+11.51.41+PM.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgD8Y4qb41oW5Ks2mO4TamaANMKuIGZqp1W3kls4clWMQuSbVIPQ-HM_qV66-seXva1HMRI5NZ2ShQFBNarh5Zlan70pgeiErr7X98gTzfPq1vRURB2S5Aze20WF9yCAcw7VB8FftHzp16P/s400/Screen+shot+2011-04-19+at+11.51.41+PM.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"Mute"</td></tr>
</tbody></table><br />
This accompanies a total site-style redesign.<br />
<br />
It is surprisingly involved changing logos after even such a short time. I had previous thought the process would be trivial, however, there are actually many considerations to be made.<br />
<br />
I decided on the original logo as a temporary measure. It was better to have something than nothing, and it was a direct visual translation of "sordina". I knew that it wasn't immediately identifiable, but logos are often abstract anyway so I didn't attribute much urgency to finding a better one. The new logo is also a direct translation of "sordina".<br />
<br />
I chose the name Sordina Productions as an homage to music and minimalism. The word "sordino" is often present on musical scores. This is in reference to instructions involving an instrument's mute. The previous logo was modelled after my cello mute. It had great sentimental value, but was almost totally unrecognisable. The new logo's metaphor should be almost completely self-evident.<br />
<br />
I chose the concept of a mute in reference to "turning down the volume" of today's websites. Websites, more often than not, are cluttered affairs that are the visual equivalent of several obnoxious people shouting at you all at once.<br />
<br />
My answer to this is minimalism - "hitting the mute button on the web"Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-70344288902831877342010-10-25T21:30:00.000-07:002010-10-25T21:30:55.694-07:00Shut Down in Mid FlightWe were shut down today during our pitch to a japanese restaurant in Mt Lawley.<br />
<br />
The manager at was determined not to even see us once he had heard that we were selling a website. I think that this experience shows that it is extremely valuable to establish even a superficial relationship with the business manager/owner before pitching a site. How to actually accomplish this is another problem.<br />
<br />
From a business point of view this rejection is by no means a major roadblock. We can always recycle the site. However, I had eaten at the establishment many times in the past and I find their lack of a web-presence disturbing.<br />
<br />
<br />
C'est la vie.<br />
<br />
<br />
Onwards and upwards.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-35313714289824016982010-10-23T21:56:00.000-07:002010-10-23T21:56:48.699-07:00Phone-Targeted CSSAfter reading over the source of <a href="http://lessframework.com/">the Less CSS Framework 2</a>, I have implemented a phone-targeted rendering approach for client sites (soon to be ported to sordina.net).<br />
<br />
The full size page:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKcjSYnn00gO-08yNupe9E8OLKzfZ7bA3S1Wh8rcMNNMMC9O3vggUo4T8SxKzY87hjicnab5oUbIlLyKy0YzpIDOTsm770GDsjY5lgSU2nWY_G_F0j_X_Kq390X0nDuxfIGwyLuMWB9cpF/s1600/Picture+1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKcjSYnn00gO-08yNupe9E8OLKzfZ7bA3S1Wh8rcMNNMMC9O3vggUo4T8SxKzY87hjicnab5oUbIlLyKy0YzpIDOTsm770GDsjY5lgSU2nWY_G_F0j_X_Kq390X0nDuxfIGwyLuMWB9cpF/s320/Picture+1.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Chrome</td></tr>
</tbody></table><br />
The phone-targeted page:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPVl71wy5IMCF0-ePja0KPXYdFrNV_KKvRGGQ4xrp9Cp0lI6tNV4SeLiBTi1T75eyEoxmb9-4y9WPNTKGmFjO9GjzP4z_AHW-G23LXdGywRHi56l6r_7tBINuVg7QniJVqIARZYYaKBKyv/s1600/Picture+2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPVl71wy5IMCF0-ePja0KPXYdFrNV_KKvRGGQ4xrp9Cp0lI6tNV4SeLiBTi1T75eyEoxmb9-4y9WPNTKGmFjO9GjzP4z_AHW-G23LXdGywRHi56l6r_7tBINuVg7QniJVqIARZYYaKBKyv/s320/Picture+2.png" width="209" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">iPhone</td></tr>
</tbody></table><br />
A smaller sized layout is kept in mind at all stages of the design process, and finally customized when the bulk of the site is finished.<br />
<br />
The trick lies almost entirely in the @media selector:<br />
<br />
<blockquote>@media only screen and (max-width: 756px)</blockquote><br />
This allows for conditionally applied layouts.<br />
<br />
I have found that two layouts is the most optimal number, as it allows for a customized browsing experience from phones, but at the same time doesn't overwhelm the developer with what essentially boils down to a constraint satisfaction problem when trying to eliminate browser glitches.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-68074457883606049492010-10-11T04:27:00.000-07:002010-10-11T04:27:04.138-07:00Easy Email with SendGridIn order to get up and running with email quickly and painlessly, I have been using <a href="http://docs.heroku.com/sendgrid">the Heroku SendGrid plugin</a>. Heroku creates some environment variables for use with your mail-library of choice when you install sendgrid:free. The problem with this is that you can't use these locally without setting them in your environment explicitly. Luckily you can work around this by referencing a file not in version control containing your sendgrid username and password, etc. Like so:<br />
<br />
<blockquote># Load private passwords for local development</blockquote><blockquote># This file is not checked into version control and is used to store account information for development</blockquote><blockquote>if File.exist?("private_env.yaml")</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>YAML.load_file("private_env.yaml").each do |key,val|</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>ENV[key] = val</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>end</blockquote><blockquote>end</blockquote><br />
Then create the yaml file referenced:<br />
<br />
<blockquote>---</blockquote><blockquote>SENDGRID_DOMAIN: localhost.localdomain # sordina.net</blockquote><blockquote>SENDGRID_PASSWORD: XXXXXX</blockquote><blockquote>SENDGRID_USERNAME: XXXXXX@heroku.com</blockquote><blockquote> </blockquote>In order to determine these variables, just use the following command in your application:<br />
<br />
<blockquote>heroku config -long</blockquote><br />
Now you are able to use the environment variables to send email with (in this example) <a href="http://github.com/benprew/pony">Pony</a>:<br />
<br />
<br />
<blockquote>post '/contact' do</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>Pony.mail(</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:to => 'maydwell+sordina@gmail.com',</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:from => params[:email],</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:subject => "sordina.net feedback from [#{params[:name]}].",</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:body => params[:comment],</blockquote><blockquote><br />
</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:via => :smtp,</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:via_options => {</blockquote><blockquote><br />
</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:address => 'smtp.sendgrid.net',</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:port => '25',</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:authentication => :plain,</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:user_name => ENV['SENDGRID_USERNAME'],</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:password => ENV['SENDGRID_PASSWORD'],</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>:domain => ENV['SENDGRID_DOMAIN']</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>})</blockquote><blockquote><br />
</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>redirect '/thanks'</blockquote><blockquote>end</blockquote><div><br />
</div><br />
<br />
Done!<br />
<blockquote> </blockquote><blockquote> </blockquote>Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-43186932200453080262010-09-15T00:20:00.000-07:002010-09-15T00:22:20.212-07:00The Amazing InternetIt's easy to take it all for granted, but sometimes you have to stop and smell the roses.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF3B67YfUE7Gif62HrmCrLXhUDgvTmryNiY2USG9a6PN3s-xNe8JNDD7qhJ9GGZiONuraafH8EvS04PrdK20r52YtsFy4Yun6zGEFnuZ1qdxoiETLLmjB88JGRZ7NyRbzV_ZWsZsg-2tsh/s1600/out.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjF3B67YfUE7Gif62HrmCrLXhUDgvTmryNiY2USG9a6PN3s-xNe8JNDD7qhJ9GGZiONuraafH8EvS04PrdK20r52YtsFy4Yun6zGEFnuZ1qdxoiETLLmjB88JGRZ7NyRbzV_ZWsZsg-2tsh/s320/out.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">My cubical.</td></tr>
</tbody></table><br />
<br />
I'm sitting in my back garden, researching potential clients using a virtual reality view of the world to walk down Beaufort Street wirelessly. Playing music from my laptop through my speaker-system in the lounge next-door with audio-streaming software. Talking to my friends from all over the world. Automatically translating articles written in German and Japanese into less-than-perfect, but still comprehensible English. Using open-source software written purely for the benefit of mankind with no reward expected other than attribution. Publishing opinions and photography, however irrelevant, that millions of people could view instantly if they so chose.<br />
<br />
I guess I'm becoming a techno-hippie because the internet feels almost utopian to me right now. The people who are trying to lock it down don't have your best interests at heart.<br />
<br />
Either way, I don't think I care about that hover-car so much anymore.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-39425263527901015902010-09-13T07:30:00.001-07:002010-09-13T07:35:31.783-07:00Asynchronous JavascriptThere are many javascript frameworks and tools that can help the besieged web-developer in their quest to slay the dragon. I personally use jQuery for even the most menial of tasks thanks to its <a href="http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/">beautiful monadic design</a>, however, even the miniscule 72k of minified jQuery source is still going to slow down page-load on slow connections. Combine this with CSS resources, other javascript files, and what-have-you, and your page will stall on grandma's computer.<br />
<br />
The very simple solution I have implemented on sordina.net is to create a small asynchronous function that triggers a download of resources using setTimeout:<br />
<br />
<br />
<blockquote>/*</blockquote><blockquote> * Simple async callback function for loading external scripts without</blockquote><blockquote> * slowing down the page.</blockquote><blockquote> */</blockquote><blockquote>function async(element,options,callback){</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>function f(){</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>var e = document.createElement(element)</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>for(var i in options) { e[i] = options[i] }</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>if(callback) {</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>if(element == "link") {</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>if(options['type'] == 'text/css') onloadCSS(element, callback)</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>} else {</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>e.onload = callback</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>}</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>}</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>document.getElementsByTagName('head')[0].appendChild(e)</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>}</blockquote><blockquote><span class="Apple-tab-span" style="white-space: pre;"> </span>setTimeout(f,0); // This makes the function asyncronous</blockquote><blockquote>}</blockquote><div><br />
</div><div>I began thinking about this issue as I was sitting on a wireless connection that had multi-second pings. Requests to jQuery, Google Font Directory, and other external resources were slowing down the loading of my page even though I was developing it from a web-server on my laptop.</div><div><br />
</div><div>Now that I am using the "async" function the page loads very quickly in this scenario, with dynamic and stylistic functionality being loaded into the page as resources become available. So long as you are designing your pages to use graceful degradation, this shouldn't be a major issue.</div><div><br />
</div><div>Until next time, let me know if I've just blogged any hideous bugs!</div><div><br />
</div>Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-21774172293983258722010-09-10T14:37:00.000-07:002010-09-10T14:37:55.875-07:00Tyler API<a href="http://github.com/Sordina/Tyler">Tyler</a> is now integrated into <a href="http://sordina.net/">sordina.net</a> at <a href="http://sordina.net/Tyler">http://sordina.net/Tyler</a><br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr4HGkGH9tXFHBARMAVKGEewqNG31yJ_W-OpWmZGjq-BM8g6LQCmSItCTWQbhdmF7LHfrLsIXzsqQsmbZcfnFjSY1_qP1X6aX96aE-cB1hEJdB1F7dhF0kO8ZuZtwgQBOrrp8fCPSo8DpE/s1600/Picture+5.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr4HGkGH9tXFHBARMAVKGEewqNG31yJ_W-OpWmZGjq-BM8g6LQCmSItCTWQbhdmF7LHfrLsIXzsqQsmbZcfnFjSY1_qP1X6aX96aE-cB1hEJdB1F7dhF0kO8ZuZtwgQBOrrp8fCPSo8DpE/s320/Picture+5.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The early-nerd catches the internet-worm.</td></tr>
</tbody></table><br />
That was a fun couple of hours.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-28005061199886687332010-09-10T08:45:00.000-07:002010-09-10T09:10:41.150-07:00Google Font DirectoryI have been using <a href="http://code.google.com/webfonts">Google Font Directory</a> for Sordina Productions' fonts.<br />
<br />
Not only does this give a reasonably unique look to the site and the blog, but the process of using the fonts is incredibly intuitive. Nevertheless...<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY6FY7g174sS4B71MrKvU-GNpr9CKpUahjMQAr0LxkCZb1k24-sr48uSZElHAfXnwEPH5mtuyZvisNLTgotiqXgkf2cr0Db_l0R_H18HlKOnd1V3aHZ7tMF-1SwSV1BFYtNZdevlskIinu/s1600/Picture+1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY6FY7g174sS4B71MrKvU-GNpr9CKpUahjMQAr0LxkCZb1k24-sr48uSZElHAfXnwEPH5mtuyZvisNLTgotiqXgkf2cr0Db_l0R_H18HlKOnd1V3aHZ7tMF-1SwSV1BFYtNZdevlskIinu/s320/Picture+1.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Custom Fonts on Blogger</td></tr>
</tbody></table><br />
<br />
To use Google Font Directory fonts on your website, or in this case, on your blogger blog -<br />
<br />
Acquiring the font CSS:<br />
<ul><li>Find a font you like at <a href="http://code.google.com/webfonts">http://code.google.com/webfonts</a></li>
<li>Click the font example</li>
<li>Click "Get the code"</li>
<li>Copy the "href" attribute from the <link> example</li>
<li>Paste this into your browser's URL bar</li>
<li>Copy the code displayed</li>
</ul><div><br />
</div><div>Integrating them into your blog:</div><div><ul><li>Click "Design" on your blogger blog</li>
<li>Click "Template Designer"</li>
<li>Click "Advanced"</li>
<li>Click "Add CSS"</li>
<li>Paste the code you copied here</li>
<li>Use CSS selectors to apply the font family to various blog elements as shown below</li>
</ul><div><br />
</div></div><div>Here is a snippet for your blog title:</div><div><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">@font-face {</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"> font-family: 'IM Fell English SC';</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"> font-style: normal;</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"> font-weight: normal;</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"> src: local('IM Fell English SC'), url('http://themes.googleusercontent.com/font?kit=h3Tn6yWfw4b5qaLD1RWvzwewtCADHBbarjY1nYW8lZc') format('truetype');</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">}</div></blockquote><blockquote><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">h1 { font-family: 'IM Fell English SC', arial, serif !important; }</div></blockquote></div><div><br />
</div>I've found no issues with using this technique in all the browsers I have tested with. Just make sure that you list some fall-back fonts so you don't get caught out when godzilla destroys the Google font servers.Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-84042178737262209962010-09-08T06:54:00.000-07:002010-09-10T08:27:02.606-07:00Simple Timelines in LaTeX<div class="separator" style="clear: both; text-align: left;">I spent some time finding a style of timeline that suited a business-plan. There are several packages available on CTAN, however these are often horizontal (which is highly space-inefficient), immature, or just plain broken. Ideally a slight diagonal deviation from vertical would fit my aesthetics perfectly, but the complexity factor skyrockets compared to the very simple solution based on tables that I found.</div><div class="separator" style="clear: both; text-align: center;"><br />
</div><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjeoO4xgJJRcg-9fKdcEp4LSV1BT-BoJjy39GV7WFCXhZTkF8wG2UDg6saXTeT6DovKkB3NWbUzptXXLSWipCgXUOzisXBesHdA4FG8P4kmtWctk65-MzroYWfayxfBGvUEjIQOx6FufEd/s1600/Picture+2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjeoO4xgJJRcg-9fKdcEp4LSV1BT-BoJjy39GV7WFCXhZTkF8wG2UDg6saXTeT6DovKkB3NWbUzptXXLSWipCgXUOzisXBesHdA4FG8P4kmtWctk65-MzroYWfayxfBGvUEjIQOx6FufEd/s320/Picture+2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An example timeline, taken from Sordina Productions' business-plan.</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"><br />
</div><div class="separator" style="clear: both; text-align: left;">The following code is quite inflexible in its handling of bullet-points, so I actually use the \foo command explicitly in my table in order to optionally allow space to be added between entries.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><br />
<blockquote><br />
\documentclass{article}<br />
\usepackage[pdftex]{graphicx}<br />
<br />
% Work around table restrictions.<br />
\newcommand{\foo}{\hspace{-2.3pt}$\bullet$ \hspace{5pt}}<br />
<br />
\begin{document}<br />
<br />
\scalebox{1.2}{<br />
\begin{tabular}{r |@{\foo} l}<br />
<br />
September 2010 & Domain-name registered\\<br />
September 2010 & Landing-site built and deployed\\<br />
September 2010 & Marketing blog deployed on Blogger\\<br />
September 2010 & Business plan completed\\<br />
September 2010 & Business name registered\\<br />
September 2010 & First client retained\\<br />
October 2010 & New-business grants applied for\\<br />
October 2010 & One month retrospective conducted\\<br />
<br />
\end{tabular}<br />
}<br />
<br />
\end{document}<br />
<br />
<br />
</blockquote>Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0tag:blogger.com,1999:blog-2561994568768921431.post-80543246664384766242010-09-07T06:43:00.000-07:002010-09-07T18:45:21.014-07:00Tiling Paper TextureUsing the new ruby-based tiling library <a href="http://github.com/sordina/Tyler">Tyler</a>, the paper texture you see on <a href="http://sordina.net/">sordina.net</a> and <a href="http://sordinaproductions.blogspot.com/">Sordina Productions on Blogger</a> has been created.<br />
<div><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo1pywnAEg5riA0NjSKnJu5AiXEa-hIqQtzuKAKbk2SvuIlSQmRKJmSMazKmY91hDgRWaY5f2RHlMi2xgopXw2IEYBmUaIwRzrmeOVtBiWlHYMLyGdX_LPWKJT9GfrVXmUPNCJLzzEEm6Y/s1600/background3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo1pywnAEg5riA0NjSKnJu5AiXEa-hIqQtzuKAKbk2SvuIlSQmRKJmSMazKmY91hDgRWaY5f2RHlMi2xgopXw2IEYBmUaIwRzrmeOVtBiWlHYMLyGdX_LPWKJT9GfrVXmUPNCJLzzEEm6Y/s200/background3.png" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tiling Paper Texture</td></tr>
</tbody></table><br />
</div>Lyndonhttp://www.blogger.com/profile/07659299997770823258noreply@blogger.com0