Building A Blog
Back in the early days of this blog, I didn’t have the luxury of programming languages like PHP to do a lot of the heavy lifting. I simply didn’t have the knowledge to use them – and even if I did, I was also severely limited by the servers that were hosting the content. They didn’t support server-side scripting or have databases for storing information. I had to maintain each page by hand, manually editing the content and shifting posts around as I wrote new ones. The process was tedious and required an inordinate amount of maintenance. The best thing to happen to this blog was to switch from static-content models, where I hand-crafted each page entry, to a dynamic model, that loads content stored from a database into pre-made shells. The advantages are numerous. Besides eliminating the need to meticulously manage content on every page, I can also automatically categorize, cross-link, and tag posts. End-users such as yourself benefit from features like searching across entries, a rich comment system, and a consistent user interface.
Unlike the “old days”, where server-side scripting was scarce, you’d be crazy in this day and age not to utilize some kind of blogging framework, or at minimum a scripting language with an underlying database. One thing I’ve learned, however, is that there is a fairly good gap between understanding a markup language (like HTML) and a programing language like PHP or JavaScript. If you’re relatively new to programming – and more used to drag-and-drop what-you-see-is-what-you-get (WYSIWYG) environments (like Dreamweaver)- then using these kinds of technologies can be a little intimidating at first. While I’m not going to give you a crash course in computer programming (at least not right now) – you don’t really need to have an extremely in-depth knowledge of the programming language just to get something put together. If you know HTML, then you probably already know more than you might think you know. You know?
If you already have a good layout in HTML and CSS ready, then converting it from a static page of text into an interactive blog system is really not too difficult. Programming the system from complete scratch – starting with a blank page and an empty database is, however, a daunting task – even for a seasoned programmer. Taking advantage of a system like WordPress is far more practical, and it takes all the complicated pieces out of the equation. You don’t need to know how to program – you just need to know how to put all the pieces together.
Before I start the tutorial, let me briefly explain the big picture. WordPress is a PHP-based system. PHP code is executed on the server, pulls data from a database, and outputs HTML-formatted text. This HTML is then sent to your browser, which renders the page.

It can also output pieces of JavaScript, which run in your browser, and let you do things like connect to Facebook, or just validate a form. The goal, then, is to modify existing WordPress code to output HTML in you’re pre-designed format instead of their default format. These ‘formats’ are simply called Themes in WordPress. With just an hour or so of work, you can take your layout and a default WordPress Theme, and turn it into a highly-customized website.
It’s probably easier than you might assume. If you’re interested, just follow along below:
What You’ll Need
- WordPress (http://wordpress.org/download/), v.2.8.4 or higher
- Pre-made layout (See #3 for a good sample)
- MySQL & PHP-Enabled web-server (I use MAMP locally, http://www.mamp.info/en/downloads/index.html. If you’re using Windows, you could use WAMP, but I’d recommend that instead you just stop right now and do what any right minded web-professional would do – go buy a damn Mac already. Seriously. Go ahead and run to the store – I’ll wait here until you get back.)
What To Do:
1. Download and install MAMP by dragging it to your Applications folder. Just double click it – and your done setting up a local website. The files are stored by default at ~/Sites/, and the website address is http://localhost:8080/. You also need to download and install WordPress, follow it’s instructions, as follows:
Original Ray’s “Famous 5-minute install”
1. Unzip the package in an empty directory.
Put this in your MAMP directory, like ~/Sites/wordpress
2. Open up wp-config-sample.php with a text editor like WordPad or similar and fill in your database connection details.
WordPad? Surely, they jest. If you like free, trying TextWrangler. If you’re serious about coding, Eclipse will do in a pinch, but it’ll pinch back. Recommended: Coda or BBEdit.
As for the Mysql DB credentials – the MAMP Homepage (http://localhost/MAMP/?language=English) will tell you what your credentials are.
3. Save the file as wp-config.php
4. Upload everything.
Actually, just do this locally first. Open up the page in a browser, aka http://localhost/wordpress and follow along. You’ll do this again on the webserver once we’re all finished. At a later point in time, consider adding version control systems like Git or SVN. I’ll cover each in a later tutorial.
5. Open /wp-admin/install.php in your browser. This should setup the tables needed for your blog. If there is an error, double check your wp-config.php file, and try again. If it fails again, please go to the support forums with as much data as you can gather.
6. Note the password given to you.
Did you ‘note’ it?
7. The install script should then send you to the login page. Sign in with the username admin and the password generated during the installation. You can then click on ‘Profile’ to change the password.
Please change the password to something good and secure, letters, numbers, symbols and all, and something you’ll actually remember.
2. Locate the Default theme: ~/Sites/wordpress/wp-content/themes/default. Make a copy of it, and rename it default_original.
3. We’ll edit the existing default theme. For reference, here is the layout I started with. I’ve highlighted how each section is going to be cut up, so you can see how the original code breaks down into the separate header, body, footer, and sidebar sections in WordPress.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta name="author" content="Andy Hoffner" />
<meta name="keywords" content="andy hofner, hoffner, javascript, code, tech, apple, php, mysql, code samples, ramblings" />
<meta name="description" content="The homepage of Andy Hoffner, programmer from Boulder Colorado. Focuses on coding, tech
& video game news, and ramblings." />
<meta name="robots" content="all" />
<title>AndyHoffner.com - Home</title>
<style type="text/css" media="all">
@import "main.css";
</style>
</head>
<body onload="window.defaultStatus='AndyHoffner.com';" id="andyhoffner">
<div id="container">
<div id="linkList">
<div id="linkList2">
<div id="lselect">
<h2>Articles</h2>
<ul>
<li><a href="/">Article 1</a></li>
</ul>
<h2>Post Categories</h2>
<ul>
<li><a href="/">Category 1</a></li>
</ul>
<h2>Post Archives</h2>
<ul>
<li><a href="/">Archive 1</a></li>
</ul>
</div>
</div>
</div>
<div id="intro">
<div id="pageHeader">
<h1>
<li><div id='leftbkg'></div><div id='rightbkg'></div><div id='centerbar'></div>
<div id='logotext'></div><span>AndyHoffner.com</span></li>
<li><div id='tab1'></div><div id='tab2'></div></li>
</h1>
<h2><span>The Place You Go For Things</span></h2>
</div>
<div id="quickSummary">
<p><span>There but for the grace of god...</span></p>
</div>
<div id="preamble">
<h3 id='article1'><span>Building A Blog-based Website From Scratch</span></h3>
<p>This is where the body text goes!</p>
<h3 id='article2'><span>Basic Layered Layouts</span></h3>
<p>This is also where body text goes!</p>
<p><h4><span> -Andy</span></h4></p>
</div>
</div>
<div id="footer">
<a href="http://andyhoffner.com" title="Temp Link!">Home</a>
<a href="http://andyhoffner.com" title="Temp Link!">Home away from home</a>
<a href="http://andyhoffner.com" title="Temp Link!">no place like home</a>
</div>
</div>
</body>
</html>
4. If you take a look at the default theme’s contents, you’ll see these pieces match up to files in there almost exactly, header.php, footer.php, sidebar.php and the body goes in index.php. The following steps will tell you how to take the code above and integrate it into each of these files.
5. First, open header.php. Remove all the lines in red. Add in the pieces from your header, which are in blue.
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" <?php language_attributes(); ?>>
<head profile="http://gmpg.org/xfn/11">
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<title><?php wp_title('«', true, 'right'); ?> <?php bloginfo('name'); ?></title>
<title>AndyHoffner.com - Home</title>
<link rel="stylesheet" href="<?php ">php php ">bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />
<link rel="stylesheet" href="wp-content/themes/default/main.css" type="text/css" media="screen" />
<style type="text/css" media="screen">
<?php
// Checks to see whether it needs a sidebar or not
if ( empty($withcomments) && !is_single() ) {
?>
#page { background: url("<?php bloginfo('stylesheet_directory'); ?>
/images/kubrickbg-<?php bloginfo('text_direction'); ?>.jpg") repeat-y top; border: none; }
<?php } else { // No sidebar ?>
#page { background: url("<?php bloginfo('stylesheet_directory'); ?>
/images/kubrickbgwide.jpg") repeat-y top; border: none; }
<?php } ?>
</style>
<?php if ( is_singular() ) wp_enqueue_script( 'comment-reply' ); ?>
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?> onload="window.defaultStatus='AndyHoffner.com';" id="andyhoffner">
<div id="page">
<div id="header" role="banner">
<div id="headerimg">
<h1><a href="<?php echo get_option('home'); ?>/"><?php bloginfo('name'); ?></a></h1>
<div><?php bloginfo('description'); ?></div>
</div>
</div>
<hr />
<div id="container">
<div id="intro">
<div id="pageHeader">
<h1>
<li><div id='leftbkg'></div><div id='rightbkg'></div><div id='centerbar'></div>
<div id='logotext'></div><span>AndyHoffner.com</span></li>
<li><div id='tab1'></div><div id='tab2'></div></li>
</h1>
<h2><span>The Place You Go For Things</span></h2>
</div>
6. Now open up footer.php. Same deal, delete red, add your custom content in the blue. Little footnote here (pun intended) – removing the “Powered By WordPress” thing is optional – I just wanted to display it in a different place, and didn’t want the extra content mucking up the layout just yet. Please include it in your design wherever you feel warranted!
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>
<hr />
<div id="footer" role="contentinfo">
<!-- If you'd like to support WordPress, having the "powered by" link somewhere on your blog
is the best way; it's our only promotion or advertising. -->
<p>
<?php bloginfo('name'); ?> is proudly powered by
<a href="http://wordpress.org/">WordPress</a>
<br /><a href="<?php bloginfo('rss2_url'); ?>">Entries (RSS)</a>
and <a href="<?php bloginfo('comments_rss2_url'); ?>">Comments (RSS)</a>.
<!-- <?php echo get_num_queries(); ?> queries. <?php timer_stop(1); ?> seconds. -->
</p>
</div>
</div>
<div id="footery">
<a href="http://andyhoffner.com" title="Temp Link!">Home</a>
<a href="http://andyhoffner.com" title="Temp Link!">Home away from home</a>
<a href="http://andyhoffner.com" title="Temp Link!">no place like home</a>
</div>
</div>
<?php wp_footer(); ?>
</body>
</html>
7. Sidebar.php – red = bad, blue = good, black = neutral. I pretty much have blown this whole file out, took a lot of content/features out with it – feel free to keep them if you like their look in your sidebar.
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
?>
<div id="sidebar" role="complementary">
<ul>
<?php /* Widgetized sidebar, if you have the plugin installed. */
if ( !function_exists('dynamic_sidebar') || !dynamic_sidebar() ) : ?>
<li>
<?php get_search_form(); ?>
</li>
<!-- Author information is disabled per default. Uncomment and fill in your details if you want to use it.
<li><h2>Author</h2>
<p>A little something about you, the author. Nothing lengthy, just an overview.</p>
</li>
-->
<?php if ( is_404() || is_category() || is_day() || is_month() ||
is_year() || is_search() || is_paged() ) {
?> <li>
<?php /* If this is a 404 page */ if (is_404()) { ?>
<?php /* If this is a category archive */ } elseif (is_category()) { ?>
<p>You are currently browsing the archives for the <?php single_cat_title(''); ?> category.</p>
<?php /* If this is a yearly archive */ } elseif (is_day()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for the day <?php the_time('l, F jS, Y'); ?>.</p>
<?php /* If this is a monthly archive */ } elseif (is_month()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for <?php the_time('F, Y'); ?>.</p>
<?php /* If this is a yearly archive */ } elseif (is_year()) { ?>
<p>You are currently browsing the <a href="<?php bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for the year <?php the_time('Y'); ?>.</p>
<?php /* If this is a monthly archive */ } elseif (is_search()) { ?>
<p>You have searched the <a href="<?php echo bloginfo('url'); ?>/"><?php echo bloginfo('name'); ?></a> blog archives
for <strong>'<?php the_search_query(); ?>'</strong>.
If you are unable to find anything in these search results, you can try one of these links.</p>
<?php /* If this is a monthly archive */ } elseif (isset($_GET['paged']) && !empty($_GET['paged'])) { ?>
<p>You are currently browsing the <a href="<?php echo bloginfo('url'); ?>/">
<?php echo bloginfo('name'); ?></a> blog archives.</p>
<?php } ?>
</li>
<?php }?>
</ul>
<ul role="navigation">
<?php wp_list_pages('title_li=<h2>Pages</h2>' ); ?>
<li><h2>Archives</h2>
<ul>
<?php wp_get_archives('type=monthly'); ?>
</ul>
</li>
<?php wp_list_categories('show_count=1&title_li=<h2>Categories</h2>'); ?>
</ul>
<ul>
<?php /* If this is the frontpage */ if ( is_home() || is_page() ) { ?>
<?php wp_list_bookmarks(); ?>
<li><h2>Meta</h2>
<ul>
<?php wp_register(); ?>
<li><?php wp_loginout(); ?></li>
<li><a href="http://validator.w3.org/check/referer" title="This page validates as XHTML 1.0 Transitional">
Valid <abbr title="eXtensible HyperText Markup Language">XHTML</abbr></a></li>
<li><a href="http://gmpg.org/xfn/"><abbr title="XHTML Friends Network">XFN</abbr></a></li>
<li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art
semantic personal publishing platform.">WordPress</a></li>
<?php wp_meta(); ?>
</ul>
</li>
<?php } ?>
<?php endif; ?>
</ul>
</div>
<div id="linkList">
<div id="linkList2">
<div id="lselect">
<h2>Articles</h2>
<ul>
<?php wp_list_pages('title_li='); ?> <!-- This fetches a list of pages with an <;;li> tag without a headline -->
</ul>
<h2>Post Categories</h2>
<ul>
<?php wp_list_categories('show_count=1&title_li='); ?> <!-- This does the same -->
</ul>
<h2>Post Archives</h2>
<ul>
<?php wp_get_archives('type=monthly'); ?>
</ul>
</div>
</div>
</div>
8. Finally, the body:
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
<?php get_header(); ?>
<div id="content" class="narrowcolumn" role="main">
<div id="quickSummary">
<p><span>There but for the grace of god...</span></p>
</div>
<div id="preamble">
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>
<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
<h23><a href="<?php the_permalink() ?>" rel="bookmark"
title="Permanent Link to <?php the_title_attribute(); ?>"><span><?php the_title(); ?></span></a></h23>
<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>
<p>
<div class="entry">
<?php the_content('Read the rest of this entry »'); ?>
</div>
<p class="postmetadata"><?php the_tags('Tags: ', ', ', '<br />'); ?> Posted in <?php the_category(', ') ?> |
<?php edit_post_link('Edit', '', ' | '); ?>
<?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?></p>
</p>
</div>
<?php endwhile; ?>
<div class="navigation">
<div class="alignleft" ><?php next_posts_link('« Older Entries') ?></div>
<div class=alignleft"><?php previous_posts_link('Newer Entries »') ?></div>
</div>
<?php else : ?>
<h2 class="center">Not Found</h2>
<p class="center">Sorry, but you are looking for something that isn't here.</p>
<?php get_search_form(); ?>
<?php endif; ?>
</div>
<?php get_sidebar(); ?>
<?php get_footer(); ?>
9. You should also check out single.php. This page will be used to show an entry all by itself on a single page, if someone does a search, or is browsing the archives. It is also where people will add comments.
<?php
/**
* @package WordPress
* @subpackage Default_Theme
*/
<?php get_header();?>
<div id="quickSummaryfull">
<p class="p6"><span> 
<div class="alignleft"><?php previous_post_link('« %link') ?></div>
<div class="alignleft"><?php next_post_link('%link »') ?></div>
</span></p>
</div>
<br />
<div id="content" class="widecolumn" role="main">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="navigation">
<div class="alignleft"><?php previous_post_link('« %link') ?></div>
<div class="alignleft"><?php next_post_link('%link »') ?></div>
</div>
<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
<h2><?php the_title(); ?></h2>
<div class="entry">
<?php the_content('<p>Read the rest of this entry »</p>'); ?>
<?php wp_link_pages(array('before' => '<p><strong>Pages:</strong> ', 'after' => '</p>',
'next_or_number' => 'number')); ?>
<?php the_tags( '<p>Tags: ', ', ', '</p>'); ?>
<p class="postmetadata alt">
<small>
This entry was posted
<?php /* This is commented, because it requires a little adjusting sometimes.
You'll need to download this plugin, and follow the instructions:
http://binarybonsai.com/wordpress/time-since/ */
/* $entry_datetime = abs(strtotime($post->post_date) - (60*120)); echo time_since($entry_datetime);
echo ' ago'; */ ?>
on <?php the_time('l, F jS, Y') ?> at <?php the_time() ?>
and is filed under <?php the_category(', ') ?>.
You can follow any responses to this entry through the
<?php post_comments_feed_link('RSS 2.0'); ?> feed.
<?php if ( comments_open() && pings_open() ) {
// Both Comments and Pings are open ?>
You can <a href="#respond">leave a response</a>, or <a href="<?php trackback_url(); ?>"
rel="trackback">trackback</a> from your own site.
<?php } elseif ( !comments_open() && pings_open() ) {
// Only Pings are Open ?>
Responses are currently closed, but you can <a href="<?php trackback_url(); ?> "
rel="trackback">trackback</a> from your own site.
<?php } elseif ( comments_open() && !pings_open() ) {
// Comments are open, Pings are not ?>
You can skip to the end and leave a response. Pinging is currently not allowed.
<?php } elseif ( !comments_open() && !pings_open() ) {
// Neither Comments, nor Pings are open ?>
Both comments and pings are currently closed.
<?php } edit_post_link('Edit this entry','','.'); ?>
</small>
</p>
</div>
</div>
<?php comments_template(); ?>
<?php endwhile; else: ?>
<p>Sorry, no posts matched your criteria.</p>
<?php endif; ?>
</div>
<?php get_footer(); ?>
10. Go ahead and check out your changes, http://localhost/wordpress/. You might have to tweak the layout or the main.css file, especially if any of your custom CSS names match the names in WordPress. Remember that CSS is a last-come, last-serve language – whichever declaration is read last will be the one that counts. I had you order you’re CSS file after the WordPress ones for just this reason, anything in your CSS file will overwrite the settings in WordPress. If you’d like, you can merge the two files and clean up any re-declarations. In the long run it’ll be easier to manage, but in the short run it’ll be a pain to sort out all the correct pieces. I’ll show you a short cut on how to do this in another post.
11. Once it looks right, you should make a new thumbnail picture for it. Open the site in a web-browser, take a picture (Cmd-Shift-4), open it in Preview, and resize it (Tools->Adjust Size) to no larger than 300 wide and 225 tall. You should also give your theme a name & author (that’s you). Open style.css and edit Theme Name, Description, and Author. In the Theme URI, put your web address (ex. http://andyhoffner.com), and Version should just be 1.0.
12. Now its time to get it running on your web server. The easiest way is to install a clean WordPress instance, following their “5 Minute Install” all over again. Then, copy your customized “default” template to the server, and just rename it to something unique. This way, you can keep the default template on file for emergency cleanups, or just simple reference.
13. To switch to and activate your new template, log into WordPress (htttp://yourremotewebserveraddress.com/wp-login.php), Click Appearance from the menu on the left, and you should see your new theme, with name and custom thumbnail. Click Activate.
14. You’re done! Congratulations!
Keep checking in for Part 3 of the series!
-Andy