Tuesday, April 28, 2009

20 Excellent User Interface components!

@davidvanvickle just sent out a tweet with this roundup of web 2.0 user interface components. Included are several takes on Image Sliders, Lightboxes, Form additions, Control tabs, etc.

Posted in the blog so I don't forget to look in to it more later.

Tuesday, April 21, 2009

How to set up WAMP on Windows XP, and other thoughts about being a 1337 web developer

Oh, hai2u.
Well, several friends from the real world asked me to put together a guide for the n00b web developer.. so here it is. By no means should this be considered an all inclusive 'i can haz websitez' tutorial. I'm not going to teach you how to write code. Go figure that part out for yourself. What I will cover is the basics of setting up your development environment so that you can start writing code / playing with scripts. I'll also pack this post full of links about things I think you should do extended reading about.

What is WAMP / Why do I need it?
WAMP is an acronym for "Windows,Apache, Mysql, and PHP/Perl/Python". Ok, so what does that mean? Well WAMP is an easy to install bundle of the Apache Webserver, MySQL Database Server, and the PHP programming language running on Microsoft Windows. I personally use a MAMP stack (Mac OS X, Apache, MySQL, and PHP) when I develop web sites. Many websites run using a LAMP Stack (Linux, Apache MySQL, and PHP). Most of the time the host operating system does not matter, and the Apache/MySQL/PHP combo work the same on Windows as they do on Linux (but not always!).Anyway many times the most daunting hurdled to learning to develop websites is getting a local web server set up correctly. WAMP makes it super-easy to get started. Additionally WAMP provides some additional tools such as phpMyAdmin for interacting with your database...

What is Apache?
Apache is the web server daemon (background process) that runs around serving up requests for web pages. Read this wikipedia article about Apache for more information. She is both a feirce, and fickle mistress, so it is best to leave the 'default' settings for Apache when you install WAMP until you understand what you are doing.

What is MySQL?
MySQL is a relational database management system. It's open source and works like a champion in a variety of scenarios ranging from tracking inventory at a small business to running large ecommerce sites. Check out this Wikipedia article about mysql to learn more OR you can head over to w3schools and learn some SQL. MySQL is not the only database server which can be used to store data for web sites though. There is also PostgreSQL, FirebirdSQL, Oracle and..erm.. Microsoft SQL Server.

What is PHP?
PHP is a recursive acronym for "Hyptertext PreProcessor". It started out as a sort of extension to PERL waaaay back in the day, but now has grown in to one of the most widely used server-side programming languages on the internet. Here is an article on wikipedia about PHP and its' background. The PHP Manual can be found at http://www.php.net/ . One thing a lot of people do not understand when they start out is that WRITING PHP IS NOT THE SAME AS WRITING HTML! Let me explain.. HTML is an interpreted document format. A web browser will look at an HTML document and use the tags as a guide to displaying your content. This is all done by the computer of the person viewing the web page. PHP is a programming language. The WEB SERVER (apache in our case) will look at our PHP file and EXECUTE the instructions found inside the file. PHP is where the business logic of your website happens. Things like saving user information, storing a new blog post, or logging in to a website are all handled by the PHP side of the website. Whatever it is you are doing with PHP, just remember that the PHP is executed on the server and the results are then sent to the web browser as HTML (or xml, or json, or whatever.. but thats another topic entirely). Seriously though, to take full advantage of the power of the dark side...errm..PHP.. you will need to spend some time learning the basics of Computer Science (control structures, looping, multi-dimensional arrays, OOP, etc).

Installing WAMP.
Ok so now are are to the part where you want to install WAMP. It's pretty simple, just download WAMP, open the installer, accept the lisence agreement (it's open source), then it will ask you where you want to install WAMP to. The default location is c:\wamp . You can change this if you want, but I normally just leave it alone. The installer will run for several minutes while it copeis files. It will ask you to locate your 'default web browser'. Choose whichever browser you prefer (Firefox right?). The next thing you come across will be a "Windows Security Alert" from the Windows Firewall. You'll want to 'unblock' the Apache HTTP Server so that it can do its thing.


The next screen you come to will ask you to set up your PHP mail parameters. Starting out you can leave these settings alone, but if your want to you can change the settings to reflect any existing SMTP gateways you have set up.

Once you're done with that just click Finish and we're done. You now have a fully functioning install of WAMP ( assuming everything went smoothly!) All you need to do is launch WAMP and you are ready to rock and roll :)

Congratulations! YOU CAN HAZ WEBSITE!
Once you have launched WAMP you will have a nifty little icon in your system tray. It gives you quick access to things like your webroot, phpMyAdmin, PHP settings, Apache settings, and the ability to start and stop some (or all) services. It also serves as a status indicator as well. If the icon is Yellow it means that some services did not start up. If it is red then it means that no services are online. White means that everything is OK and all services are reported to be running.
Where do I put my website files?
Ah, yes! That's probably the reason your even reading this in the first place. You can't figure out where to put your website files. Well, assuming that you kept the default settings you will want to stick your files in C:\wamp\www\MyWebsite\ as seen below. What is really cool about making subfolders for all of your sites is that the index.php file you see will detect the subfolders and display links to them when you browse to http://localhost (go ahead, try it!) to visit your test website go to http://localhost/MyWebsite/



Important notice about using Development Tools!
You won't get anywhere without having the right tools. For the novice web developer on Windows this can be take some time to get right. Most people will start out by acquiring a copy of Adobe Dreamweaver (it really does kick ass). For those who are braver (read: want to actually learn to code) I recommend you use Netbeans. It has GREAT support for many languages, it's open source AND it's cross platform (Runs on Windows, Linux, and Mac OS X). As a professional developer,I practically live inside of Netbeans ( I use dreamweaver to rapidly prototype interface elements, but thats doesn't even equate to 10% of my time).

Debugging!
You'll run in to problems along the way. Install a copy of Mozilla Firefox. Then get: Web Developer Toolbar, Firebug, YSlow (requires firebug), and Switch Proxy (Just to start with!). I'll write another post about firefox extensions to help you along the way later this week.

WTF, your still here?
Ok fine. I'm sure some of you ran in to problems. Please leave your comments for me below (or if your reading this post and have ANY kind of critisism then please leave it as well). You can also send your questions / comments to me on Twitter: http://twitter.com/SteveHatherley

Friday, April 10, 2009

Color Scheme by Aurora


So my daughter asked to see my website. I showed her my blog and she said she didn't like it and the colors needed to change. She's 3. I opened the color editor and we she picked the colors for everything.

I'll fix it later.. she's having a blast messing with it. Back to normal.

Wednesday, April 8, 2009

Thoughts on WildFlower updates..

This is more or less a list of things I consider "broken" or "needs better implementation" about wildflower.. basically a list of things I'll attempt to address in my branch of wildflower unless someone else beats me to it. Just a preliminary brain dump, don't expect any pearls of wisdom here.

Wildflower Post/Page Publisher
  • In TinyMCE Editor, insert image tool has awkward selection method. Currently you have to click the image button, then click the thumbnail of the image you want to select, then click the "insert selected image" button. If you click the link text for the file name it brings you to the Edit action for that file -- should just auto-insert image in to TinyMCE.
  • In TinyMCE Editor, insert image tool does not allow you to upload an image from the publisher. Requires that you use the Assets manager. Should display uploader utility in side-bar.
Wildflower "Assets" Manager
  • Should support many file types, not just images.
  • Files should be displayed with appropriate file-type icons
  • Is a thumbnail for images really necessary?
  • Needs multi-upload capability. Current implementation is very slick and intuitive for uploading 1 or 2 images, but what if you need to upload 20? It starts to become a pain in the ass at that point. It would be cool to use something like the YUI Uploader
Wildflower Users
  • No distinction between Administrative users and a regular site user
  • No ACL

Wildflower MU Specific
  • No "Root Administrator" role for all sites
  • Some models are not entirely converted yet (Sitemaps for example..)

Tuesday, April 7, 2009

Google Mini!

I took these photos back in October when I was working at Gelb. The idea was to use the Google Mini to power a PDF search for one of Gelb's dashboards. I had difficulty getting it installed though and left the company before the project was finished. Here are the pix though...





















Apache on OS X Leopard MOD_REWRITE / .htaccess issues (Mysterious 500 Internal Server Error CakePHP Apps + no dir index +403 Forbidden for phpmyadmin)

Ok, so after over a week of brokenness and screwed up Apache Brad and I finally diagnosed a problem i've been having with XAMPP.

Here's what happened / Symptoms:
I was working with wildflower and wanted to try a branch I had downloaded from GitHub. Well, somehow during archive extraction the .htaccess files did not get copied over correctly. So I jumped into the terminal and was (rather carelessly) copying the .htaccess files to their proper places.


I get the files copied over and run a few tests on the demo pages to see if my CSS and images were showing up and everything seemed to be working just fine. Oh no. I inserted some test data using a form within the application and went to jump into phpmyadmin. Well phpmyadmin was telling me that the url /phpmyadmin was forbidden on the server.

All browser requests to http://localhost also stopped working, but I could ping localhost from the terminal, but nothing would work from a browser.

So I started debugging it and got access to phpmyadmin by turning 'AllowOverride' to None in /etc/httpd.conf - but this is no good because I need mod_rewrite to work in my cake applications.

I tried completely destroying my XAMPP installation and reconfiguring it from scratch, still the errors persisted. I was either able to have access to phpmyadmin but no URL rewrite OR I could have URL-rewrite but no access to phpmyadmin. 

The Cause:
As I said before, I had been copying the .htaccess files around. I had accidentally copied .htaccess to the root directory of OS X. I have no freaking clue why, but for SOME reason, Apache on OS X picked up the misplaced cakephp .htaccess file and then attempted to apply the rewrite rules to everything underneath /

I don't know if this applies to other distributions of apache as well, but I figured  I would write a quick blurb about it in case anyone else runs across this issue.

Thursday, April 2, 2009

Updating Wildflower Multiple Site Extension to work with WF 1.3b

Update! Code at Git Hub works. I'll update this page once a few bugs are taken care of.

Wildflower is a CMS written in CakePHP. It's ao frickin simple to use as a base for my applications that I showed it to my boss on Monday ( I had figured out how to extend the admin interface for my own models which I had baked using ModelBaker. I used the difference viewer in Netbeans to merge the baked models in to WF 1.3b branch and the results were quite nice... SO.. We decided to see if we could get this multi-site extension to work. The provided branch and code samples on that page worked, but it was written against an old 'cake plugin' version of WildFlower. So I decided to fork from Klevo's 1.3b branch and try to adapt the existing "extension" to work with the new code. I would like for us to commit code back upstream if it we end up using it for other stuff.. I just need to get this initial multi-site code working with current sources for that to happen.

http://github.com/SteveHatherley/wildflower/tree/master

I have not figured out how to get Netbeans to cooperate with GitHub just yet so I don't have a way to commit my code up there.. but, I do want to share it and get some help making it work.. so I'll just attach a zip file with a SQL dump for now.

Ok so I am going to update the previous Multiple Install Extension install instructions and document the places I made changes, and to what, so yeah, credit to them and stuff.

Download Stevo's Wildflower Multi-Site Extension
Download Stevo's Wildflower Multi-Site Extension Full Schema Dump

*Remember to chmod +777 -r app/tmp/* and /app/webroot/uploads

Step 1 Wildflower Changes

We are going to be adding a new "Installs" feature to the Wildflower administration section and make it work. This verbiage should be changed to "Sites" instead of "Installs" in my opinion since we'll be managing multiple websites using a single install of WildFlower, but we'll leave it as-is for now.

Open up your code and go to /app/app_controller.php. This is your application controller and sort of like the ignition of your application.

The original Multiple Extension instructions tell us to enable Cakephp Theming, but this is not necessary in the 1.3b branch since both themes and layouts are already enabled.

We still need to check which site needs to be delivered by checking the HTTP_HOST. We will do this in a new method called checkInstall() [should be checkSite()]. This method will be called by beforeFilter() and is going to be used to check the current URL.
  • In "function beforeFilter()", add the following method call After "$this->wildflowerCallback('before');":

    $this->checkInstall();
    (Around line 46)

  • Then at the end of the app_controller class, add this function:
  /**
* Check Install
*
* Check to see which install is being used in the admin
* Assigns a global Install ID based on http host
*/
function checkInstall() {
// Load the install model
$this->loadModel('WildInstall');
// Predefine default settings.
$settings = array(
'id'=>1,
'name'=>'Default Template',
'code'=>'default',
'theme'=>'',
'layout'=>''
);
// Set the Installs Dropdown variables on the Wildflower Administration page
$wilduser = $this->Session->check('WildUser');
$skip_url = false;
if (!empty($wilduser) && $wilduser>0 && !empty($this->params['prefix']) && $this->params['prefix'] == 'wf') {
$install_id = $this->Session->read('WildInstall.id');
if (!empty($install_id) && $install_id > 0) {
$res = $this->WildInstall->findById($install_id);

if(!empty($res['WildInstall']) && is_array($res['WildInstall'])) {
$settings = am($settings, $res['WildInstall']);
$skip_url = true;
}
}
// Setting the installs pulldown menu on the admin page.
$installs_dropdown = $this->WildInstall->find('list');
$this->set('installs_dropdown', $installs_dropdown);
$this->set('install_dropdown', $settings);
}
// If you are not in the admin, try to find the Install based on the http_host
if (!$skip_url) {
$url = preg_replace("/\//",'', env('HTTP_HOST'));
$url = preg_replace("/^www./",'', $url);
$res = $this->WildInstall->find(array('WildInstall.http_host'=>"$url"));
if(!empty($res['WildInstall']) && is_array($res['WildInstall'])) {
$settings = am($settings, $res['WildInstall']);
}
}
// Set the theme based on the install settings
if (!empty($settings['theme']) && count($settings['theme'])) {
$this->theme = $settings['theme'];
}
// Set the layout based on the install settings
if (!empty($settings['layout']) && count($settings['layout'])) {
$this->layout = $settings['layout'];
}
// Write the install ID so it can be seen by the beforeFind
Configure::write('WildInstall.id', $settings['id']);

}

You can save app_controller.php and open the file app_model.php from the same directory. app_model.php contains the application model ( schema, data structure, whatever you want to call it. ). You will need to make use of beforeSave() and beforeFind() in order to add a filter to all requests based on HTTP_HOST (install_id). Because we are defining these overrides at application level they are globaly applied to all other models which extend app_model (think ${model}->find(); & ->save() requests).

Here are the functions. I do not know if I have named them correctly because things are broken. There appears to be some sort of cakephp related naming crap going on. It throws an error about invalid column "wild_install_id".. but more on that later on when I talk about what I've done to debug.. here's the function:

   /**
* Attaches an install_id to all the finds in the system
*
* @param array $passed the data passed to a model->find
*/
function beforeFind(&$passed) {
if (!empty($this->_schema['install_id'])) {
$iid = Configure::read("WildInstall.id");
$install_id_str = $this->alias . '.install_id';
if (!empty($passed['conditions']) && is_array($passed['conditions'])) {
$passed['conditions'][$install_id_str] = $iid;
} elseif(!empty($passed['conditions']) && strlen($passed['conditions'])>0) {
$passed['conditions'] .= ' AND '. $install_id_str . ' = ' . $iid . ' ';
} else {
$passed['conditions'] = array($install_id_str => $iid);
}
}
return true;
}

/**
* Attaches an install_id to all the saves in the system
*
*/
function beforeSave() {
if (!empty($this->_schema['install_id'])) {
$iid = Configure::read("WildInstall.id");
$this->data[$this->alias]['install_id'] = $iid;
}
return true;
}


Step 2 Wildflower "Installs" Controller & Model

You will need to create a controller and model for the "Installs" (Sites). I've done some re-naming in here from "Installs" to "WildInstalls" and so on (in both the controller and in the model)

@file: /wildflower/controllers/wild_installs_controller.php
class WildInstallsController extends AppController {

public $components = array('RequestHandler');
public $helpers = array('Text', 'Time', 'Wildflower.List');
public $uses = array('Wildflower.WildInstall','Wildflower.WildPage','Wildflower.WildSetting');
public $paginate = array(
'order' => 'name ASC',
'limit' => 25
);
public $pageTitle = 'Installs';

function wf_index() {
$this->WildInstall->recursive=0;
$installs = $this->paginate('WildInstall');
$this->set(compact('WildInstalls'));
}

function wf_view($id) {
$this->WildInstall->recursive = -1;
$this->set('WildInstall', $this->WildInstall->findById($id));
}

function wf_edit($id = null) {
$this->data = $this->WildInstall->findById($id);
//pr($this->data);exit;
if (empty($this->data)) $this->cakeError('object_not_found');
$this->WildInstall->save($this->data);
}

function wf_update() {
$this->WildInstall->create($this->data);
if ($this->WildInstall->save()) {
return $this->redirect(array('action' => 'view', $this->WildInstall->id));
}
$this->render('wf_edit');
}

function wf_create() {
if ($this->WildInstall->save($this->data)) {
$id = $this->WildInstall->id;
$this->Session->write('WildInstall.id', $id); // Load the current Install
return $this->redirect('/wf/settings');
}
$this->WildInstall->recursive=-1;
$installs = $this->paginate('WildInstall');
$this->set(compact('WildInstalls'));
$this->render('wf_index');
}

function wf_change() {
// The WFAdmin changes the Install id for configuration.
if (!empty($this->data['WildInstall']['id']) && $this->data['WildInstall']['id']>0) {
$this->Session->write('WildInstall.id', $this->data['WildInstall']['id']);
}
$this->redirect('/wf');
}

function delete($id) {
$id = intval($id);
if ($this->RequestHandler->isAjax()) {
$this->WildInstall->del($id, true);
exit();
}

if (empty($this->data)) {
$this->data = $this->WildInstall->findById($id);
if (empty($this->data)) {
$this->indexRedirect();
}
} else {
$this->WildInstall->del($this->data[$this->modelClass]['id'], true);
$this->indexRedirect();
}
}

function beforeRender() {
parent::beforeRender();
$this->params['current']['body_class'] = 'contact-page';
}

}


and here is the Install's model. Note: The afterSave() function will create new settings and a new default page for the new install.

class WildInstall extends AppModel {

// public $tablePrefix = 'wild_';
// public $useTable = 'installs';
public $validate = array();
public $actsAs = array('Containable');

public $hasMany = array(
'WildSetting' => array(
'className' => 'Wildflower.WildSetting'
),
);

function afterSave($created) {
$id = $this->id;
Configure::write("WildInstall.id", $id);
if($created) {
$this->recursive=1;

// Grab the WildSettings for InstallID 1
$res = $this->findById(1);
$new_settings = array();
if (!empty($res['WildSetting']) && count($res['WildSetting'])) {
foreach($res['WildSetting'] as $i => $setting) {
// Clean up fields...
unset($setting['id'], $setting['value']);
foreach($setting as $key=>$val) {
if (empty($this->WildSetting->_schema[$key])) {
unset($setting[$key]);
}
}
// Create the default settings
$this->WildSetting->create($setting);
$this->WildSetting->save();
}
}
// Create a default page based on the one found in DB.
$wildPage = ClassRegistry::init('WildPage');
$newpage = array('WildPage' => array(
'install_id'=>$id,
'slug'=>'home',
'url'=>'/',
'title'=>'Home Page',
'draft'=>1
));
$wildPage->create($newpage);
$a = $wildPage->save();
}
return true;
}

function beforeDelete() {
return false;
}

}
?>
We need to make use of the beforeSave() override at the model level in order to make our HTTP_HOST filter we defined earlier to work..

Find
 Function beforeSave()
, and replace:
        return true;

in
  • wild_comment.php
  • wild_page.php
  • wild_post.php
  • wild_user.php
  • wild_assets.php
  • Probably others too.. not sure yet
with:
        $res = parent::beforeSave();
if ($res === false) return false;
return true;

Step 3 Wildflower "Installs" views

You will need to create the View, Index, and Edit views for installs in /wildflower/views/wild_install/ . I'm having trouble copying the html into the form here so we'll just say use this stuff but remember to put it in the aforementioned folder.

Step 4 Wildflower Database Modifications

Ok seriously, f'king back up your shit. The other tutorial mentioned renaming your tables and using a prefix and so on.. this is already there and table prefixes appear to be wild_ by default. Just make sure you keep a working sql dump of your data before you push it on anything important.

So before we get in to the SQL, we need to solve a naming conflict. Originally the plugin used $useTable = "installs" in the model. We want to be using wild_installs (later to be renamed to wild_sites)..

DROP TABLE IF EXISTS `wild_installs`;
CREATE TABLE `installs` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) collate utf8_unicode_ci NOT NULL,
`code` varchar(255) collate utf8_unicode_ci NOT NULL,
`http_host` varchar(255) collate utf8_unicode_ci NOT NULL,
`layout` varchar(255) collate utf8_unicode_ci NOT NULL,
`theme` varchar(255) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `http_host` (`http_host`),
KEY `name` (`name`),
KEY `code` (`code`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `wild_installs` VALUES (1, 'Default Layout', 'default', '', '', '');

ALTER TABLE `wild_categories` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_categories` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_comments` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_comments` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_messages` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_messages` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_pages` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_pages` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_posts` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_posts` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_revisions` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_revisions` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_settings` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_settings` ADD INDEX ( `install_id` ) ;

ALTER TABLE `sitemaps` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `sitemaps` ADD INDEX ( `install_id` ) ;

ALTER TABLE `tags` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `tags` ADD INDEX ( `install_id` ) ;

ALTER TABLE `wild_assets` ADD `install_id` INT( 11 ) DEFAULT '1' NOT NULL AFTER `id` ;
ALTER TABLE `wild_assets` ADD INDEX ( `install_id` ) ;

-- Slugs should be unique per install, not per table.
ALTER TABLE `wild_pages` DROP INDEX `slug`;
ALTER TABLE `wild_pages` ADD UNIQUE `slug_install` ( `slug` , `install_id` );

ALTER TABLE `wild_posts` DROP INDEX `slug`;
ALTER TABLE `wild_posts` ADD UNIQUE `slug_install` ( `slug` , `install_id` );

ALTER TABLE `wild_categories` DROP INDEX `slug`;
ALTER TABLE `wild_categories` ADD UNIQUE `slug_install` ( `slug` , `install_id` );

ALTER TABLE `tags` DROP INDEX `name`;
ALTER TABLE `tags` ADD UNIQUE `name_install` ( `name` , `install_id` );

Step 6 Wildflower App Routing

App Routing is when you make ugly paramter strings turn in to pretty, search engine friendly urls like /blog/may/this-was-my-post. With WildFlower this means that you can have pretty url slugs for your articles and posts.

Routes are declared in /wildflower/config/routes.php. Add 'installs' to $wfControllers as seen below.

$wfControllers = array('pages', 'posts', 'dashboards', 'users', 'categories',
'comments', 'assets', 'messages', 'uploads', 'settings', 'utilities',
'widgets','installs');


*More information about customization of views, themes, etc are available on the original blog. Will expand this section later once we have the app not crashing.

Tuesday, February 10, 2009

Getting Real!

My boss just referred me to the 'Getting Real' eBook by 37Signals. I skimmed through it and was intrigued by the 'less is more' approach they have to software development. It's perfect for start-ups like my own company, Reflection Technologies. I just thought I would post a link to the eBook for my own future reference and for anyone else who might stumble across my blog..

From the 37Signals website:

Book report
Getting Real is the business, design, programming, and marketing philosophies of 37signals — a developer of web-based software used by over 1 million people and businesses in 70 countries.

Why is the book relevant?
37signals used the unconventional Getting Real process to launch five successful web-based applications (Basecamp, Campfire, Backpack, Writeboard, Ta-da List), and Ruby on Rails, an open-source web application framework, in just two years with no funding, no debt, and only 7 people.

What's in it for me?
Anyone working on a web app — including entrepreneurs, designers, programmers, executives, or marketers — will find value, fresh perspectives, and inspiration in this practical book. At under 200 pages it's quick reading too. Makes a great airplane book.

Who is 37signals?
We’re a privately-held Chicago-based company committed to building the best web-based software products possible with the least number of features necessary. Our products do less than the competition — intentionally. We’ve been in business since 1999 and love what we do.

Table of Contents:
http://gettingreal.37signals.com/toc.php

Saturday, February 7, 2009

First Look: www.michaelzrealtor.com design by Reflection Technologies


Reflection Technologies
is a partnership of programing and graphics design professionals. Part of what we do is develop websites and custom business applications for small and medium sized businesses. Our current project is for a real estate agent in The Woodlands, Texas named Michael Zabrycki. Michael has asked us to help him bring the look and feel of his brand's printed material to the web as well as bring it into the 21st century.

We started with a web page that was just a gigantic jpeg image with his picture and phone number. This is not good for search engines since they can not read pictures. We put together a temporary site and published it. You can check it out here. We also added a backlink from a few our company homepage.

The next step was to make it pretty. Jared and I are not graphics designers so we went to Dylan for some help. After a meeting at tommy bahamas and an emergency flyer reproduction effort Dylan was able to come up with this design:


I'm going to be chopping and building this into xhtml / css this weekend. If anyone has any suggestions or comments on the design let me know. I think D-Funk did an awesome job on it. The only thing I think we'll change is the Remax logo, it needs to be an official Remax Platinum logo I think..

The next phase of the project is to build a CakePHP template for the site and implement a custom copy of the new version of HomeGoat, our real estate listing platform. More on that later though ;)

Wednesday, August 6, 2008

Scientists Discover the First Ever Virus that Can Get Sick

The debate about what counts as a living thing is fuelled today by the discovery of the first virus that is able to fall "ill" by being infected with another virus. the discovery of a giant virus that itself falls ill through infection by another virus seems to suggest they too are alive, highlighting how there is no definition of what is 'living'.

read more | digg story