How To Build A WordPress CMS Theme – Part 5: Coding The Homepage
Whew, here we are again! We’ve got a long way to go today, so let’s skip the fluff and get right down to the coding!
Last week we finished up the header code, and this week we’ll be coding the homepage. In case you’re just joining us, here are the previous tutorials:
Remember you can see the demo of the WordPress version here, and see the regular HTML/CSS site here. You can also download everything in Part 4 . Ready? Let’s go!
Chapter 16: Coding the Homepage
Let’s first take a look at our homepage HTML. If you look at the site, you’ll see we have a main image and some text up top, and some image buttons beneath that. Nothing too difficult:
<div id="featured"> <h2>Our Story</h2> <p>Sophie discovered her passion for creating cakes after an exhaustive search throughout Toronto and Ottawa for her own wedding cake ended in disappointment. "Everyone was trying to convince me to settle for the cake of the week, but the cake is a centerpiece none of them were expressing what I wanted to say ..."</p> <p><a href="about.html">Read More</a></p> </div> <!-- END Featured Section --> <div id="links"> <ul> <li><a href="about.html"><img src="images/artist.jpg" alt="artist" width="221" height="175" /><span>the artist</span></a></li> <li><a href="gallery.html"><img src="images/cakes.jpg" alt="cakes" width="221" height="175" /><span>cakes</span></a></li> <li><a href="about.html"><img src="images/experience.jpg" alt="experience" width="224" height="175" /><span>the experience</span></a></li> <li><a href="http://sophiebifieldcakecompany.wordpress.com"><img src="images/blog.jpg" alt="blog" width="222" height="175" /><span>blog</span></a></li> </ul> </div><!-- END Links -->
Now in WordPress, it should always be your goal to make everything as editable as possible for your client. Let’s get started with the PHP and functions and see how we can do this. Open up index.php.
First, we’ll need to wrap the loop around our content, so it can eventually be controlled dynamically:
<?php get_header(); ?> <?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <div id="featured"> <h2>Our Story</h2> <p>Sophie discovered her passion for creating cakes after an exhaustive search throughout Toronto and Ottawa for her own wedding cake ended in disappointment. "Everyone was trying to convince me to settle for the cake of the week, but the cake is a centerpiece none of them were expressing what I wanted to say ..."</p> <p><a href="about.html">Read More</a></p> </div> <!-- END Featured Section --> <div id="links"> <ul> <li><a href="about.html"><img src="images/artist.jpg" alt="artist" width="221" height="175" /><span>the artist</span></a></li> <li><a href="gallery.html"><img src="images/cakes.jpg" alt="cakes" width="221" height="175" /><span>cakes</span></a></li> <li><a href="about.html"><img src="images/experience.jpg" alt="experience" width="224" height="175" /><span>the experience</span></a></li> <li><a href="http://sophiebifieldcakecompany.wordpress.com"><img src="images/blog.jpg" alt="blog" width="222" height="175" /><span>blog</span></a></li> </ul> </div><!-- END Links --> <?php endwhile; ?> <?php get_footer(); ?>
Now, since there’s multiple areas of content, how do we decide how to split it up for the client? What’s usually best, is to put the main chuck of content (our featured section) into the WYSIWYG, and the rest into custom fields or even custom post types.
Let’s move the main content area inside of the featured div into the WordPress’s admin. Create a page called ‘Home’ and drop the content there. Save the page and come back to index.php.
Now add in the_content() where you removed the h2 and paragraph tags:
<?php get_header(); ?> <?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <div id="featured"> <?php the_content(); ?> </div> <!-- END Featured Section --> <div id="links"> <ul> <li><a href="about.html"><img src="images/artist.jpg" alt="artist" width="221" height="175" /><span>the artist</span></a></li> <li><a href="gallery.html"><img src="images/cakes.jpg" alt="cakes" width="221" height="175" /><span>cakes</span></a></li> <li><a href="about.html"><img src="images/experience.jpg" alt="experience" width="224" height="175" /><span>the experience</span></a></li> <li><a href="http://sophiebifieldcakecompany.wordpress.com"><img src="images/blog.jpg" alt="blog" width="222" height="175" /><span>blog</span></a></li> </ul> </div><!-- END Links --> <?php endwhile; ?> <?php get_footer(); ?>
If you save the page and try to check it in the browser – nothing happens. That’s because right now, WordPress doesn’t know what page to grab content from. We have to tell WordPress with a query, to take the content from our newly created Home page.
Note: Some people prefer to do “templates” in WordPress, especially for the homepage. This consists of a separate PHP page with a special tag. You’d then create a page, choose that template in the sidebar, and then go to Settings > Reading to set that page as the homepage. That’s a lot of unnecessary work for both you and client, which is why I suggest doing it the way I do below.
Here’s the query telling WordPress to pull the content from the page called “Home”:
<?php get_header(); ?> <?php query_posts('pagename=Home'); if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <div id="featured"> <?php the_content(); ?> </div> <!-- END Featured Section --> <div id="links"> <ul> <li><a href="about.html"><img src="images/artist.jpg" alt="artist" width="221" height="175" /><span>the artist</span></a></li> <li><a href="gallery.html"><img src="images/cakes.jpg" alt="cakes" width="221" height="175" /><span>cakes</span></a></li> <li><a href="about.html"><img src="images/experience.jpg" alt="experience" width="224" height="175" /><span>the experience</span></a></li> <li><a href="http://sophiebifieldcakecompany.wordpress.com"><img src="images/blog.jpg" alt="blog" width="222" height="175" /><span>blog</span></a></li> </ul> </div><!-- END Links --> <?php endwhile; ?> <?php get_footer(); ?>
Refresh the page and look! The featured content should be showing up now!
Let’s look at the four image links below. There are several ways we could code these for the client, and depending on how technical minded your client is or how often they want to change content, should help you decide which way to go with these. For the sake of the tutorial, let’s say our clients know basic HTML and are planning on changing these links weekly. In that case, it’s best to just drop them in as a custom field.
When doing custom fields, you should try to automate as much as you can for the client. In our example above, we don’t need the client to enter the div, ul, or li tags, we just need him to enter the link, the image they want to use, and the title.
So copy and paste each link into a separate custom field, and name each custom field “Link”. You can have as many custom fields as you’d like with the same name. You’ll also need to change the image path to match yours. Also be sure to add the custom fields in the order you want to links appear.
Now we can delete the links from our code and replace it with the get_post_meta function that will echo out our custom fields:
<?php get_header(); ?> <?php query_posts('pagename=Home'); if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <div id="featured"> <?php the_content(); ?> </div> <!-- END Featured Section --> <div id="links"> <ul> <li><?php echo get_post_meta($post->ID, 'Link', true);?></li> </ul> </div><!-- END Links --> <?php endwhile; ?> <?php get_footer(); ?>
Save the page and refresh in your browser…where’d all of our links go??? It should only display one at this point.
When using multiple custom fields with the same name, you can’t just echo the get_post_meta function like you’d normally do. Instead, you need to replace that with a foreach that will also surround each link with a li tag:
<?php get_header(); ?> <?php query_posts('pagename=Home'); if ( have_posts() ) while ( have_posts() ) : the_post(); ?> <div id="featured"> <?php the_content(); ?> </div> <!-- END Featured Section --> <div id="links"> <ul> <?php $link = get_post_meta($post->ID, 'Link', false); ?> <?php foreach($link as $link) { echo '<li>'.$link.'</li>'; } ?> </ul> </div><!-- END Links --> <?php endwhile; ?> <?php get_footer(); ?>
And BOOM! How easy is that? Compare it to the original HTML site and it looks just the same, but is now controllable by the client.
Next Week
We move on to coding the footer! Please let me know if you have any questions or issues regarding this week’s post in the comments below. See ya next week!

I’m curious to know what changes were made to the functions.php file to support this. Is that coming in a future post?
@Megan there’s be no changes at all to functions.php file. Although, you might want to keep in mind that I did start off from my hijinks files template
I see now. A note to other WordPress newbies, Custom Links are hidden by default when editing a Page. It can be enabled by selecting the ‘Screen Options’ pull down box in the upper right corner and checking the ‘Custom Fields’ checkbox.
Ugh yes I forgot that as of version 3.1, they hide custom fields as default. That drives me crazy now :/
This needs to be a video series. Reading these so far have been good, but watching them would probably make this one hell of a comprehensible tutorial on theme building.
Never thought of that. I was planning on making this an eBook afterwards, but I’ll think about a video series as well.
Great job so far Amber, and congrats to you and your husband
Hey Amber, working through this and getting hung up when I try to add the value to the custom fields section. I’m adding this chunk of code:
<a href="/?page_id=5″> <img src="/images/artist.jpg” alt=”artist” width=”221″ height=”175″ />the artist
and it all is coming up on the homepage, but the link and the image wont work correctly. Getting this error:
Access forbidden!
You don’t have permission to access the requested object. It is either read-protected or not readable by the server.
If you think this is a server error, please contact the webmaster.
Error 403
localhost
9/13/2011 2:21:50 PM
Apache/2.2.14 (Win32) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.8l mod_autoindex_color PHP/5.3.1 mod_apreq2-20090110/2.7.1 mod_perl/2.0.4 Perl/v5.10.1
Am I doing something wrong or is this just a problem with my local host environment? When I use absolute URLs everything works peachy.
Thanks and great tutorials, seriously helping me out a ton!!
Hi Amber,
Great posts!
Just a question the relative urls in the custom content don’t work for me (eg. /images/artist.jpg). Since wordpress prefers us to use absolute urls like before the image call, is there a way around this?
Would love a post on creating custom admin content areas! Do you already have one??
Thanks so much!
Leonie
Relative URLs work, you just need to make sure you include the real path, which isn’t images/image.jpg, but wp-content/themes/your-theme/images/image.jpg or you could use the function bloginfo(‘template_url’) to dynamically call that URL
Hi Amber, these are great lessons. I have a question about how you handle the “home” link in the site menu. Obviously if you put the WYSIWG-created “Home” page in the menu, it won’t go to the actual index…it goes to the page with the text content for the index. Do you put a custom URL for the index in the menu instead? Thanks.
Nope, it actually automatically create a custom home link for you already, it’s always the top link under pages. If you also have a page called “Home” (which I always do), it will show two “home” links, the top one will be the one that actually goes to the homepage – you’ll have to manually update it though if you move the site.
Hi Amanda, this may be out of the scope of the tutorials. Is there a way to add a jquery tabs in the sidebar that will show recent posts in one tab and archives in another. Or can you direct me to a decent tutorial that will show how to create my own tabs? I can create the tabs – it’s the custom implementation of WordPress that I have trouble with.
Thanks
It’s Amber…
All you need to do is just drop in WordPress’s functions for those in each tab section. For archives, you’d use wp_get_archives, for recent posts you’d need to run another query. Check out the WordPress Codex, it’s very helpful.
Sorry about the name (administering dope slap)
Amber i get stucked with this part:
Here’s the query telling WordPress to pull the content from the page called “Home”:
When i add it nothing happens when i refresh the page. I thought i must be a typo, but after pasting the code from your site, still nothing happens.
I just update tot the latest WordPress, but i don’t think that have anything to do with it.
Can you help me out?
Hey Bas! I can’t see your code. Can you post it on codesnipp.it so I can take a look?
Thanks!
I don’t have Twitter i added a copy of it to my dropbox http://dl.dropbox.com/u/27323380/amberweinberg.zip
I used Hijinks as start.
Have you tried changing it to pagename=home ? Pagename is actually supposed to call the permalink, not the actual name of the page. Not sure why they named it that.
I just did, but Home or home does not work too.
The dropbox link i added in my previous post is the complete theme i am working on, following your tutorial, so you can add it to WordPress to see for yourself.
Unfortunately I don’t have the time to install it and try for myself, but have you tried to query by page id instead? I believe it’s page_id= to do it.
page id instead does work. But it is still strange it doesn’t work.
Hello Amber,
I have followed your tutorial and have two problem with part 5 – coding the homepage.
First I put the “featured” div starting with and ending with Read More between ….the_post(); ?> and
At this point, I do not see Read More. Even if path syntax is wrong, I think I should still see the text Read More.
Next, I load the links into custom fields but all I see are the alt tag and the image title (span). Perhaps the syntax is wrong so now I try all possible permutations including (‘template_url’), (‘url’) and (‘url_directory’). None of these work.
If I add links, they are seen but the image is not seen. The images are in /my_theme/images.
In the custom fields I use name of Link and value of <img src="/images/contact.png” />. All I see are four black dots where pictures should be.
I have read and tried your instructions over and over but it is still the same. What am I doing wrong?
thank you
Did you create a read more link in the homepage content? As for custom fields, you can not put php in them, so using bloginfo(‘template_url’) would not work there.
thank you for replying.
I did not create a Read More link. I just pasted from your article. Even so, the words Read More are not there.
I do not know about the custom fields, I just follow the instructions. do I just use html syntax?
thank you
Can you paste your code somewhere into pastebin?
Hey Amber, for some reason I’m super confused about how to get the sidebar on just the blog page (not sure how relevant it is to this specific part of the tutorial, but that’s what I’m on with my own blog at the moment).
Could you point out how to enable the sidebar on just the blog page (similar to your own website), please?
If you only want it on the blog, just remove the get_sidebar function from the bottom of the templates on everything but archive.php and single.php
if you want different sidebars, just use if(is_archive) or other conditionals to switch them
http://imageshack.us/photo/my-images/687/widgetu.jpg/
One thing I notice is that when I go to widgets, it says sidebar is not active at all. On other themes, that particular sidebar pane isn’t visible and it’s easy enough to set it to single pages. I’m a noob with the widgets aspect, but would this be why it won’t show up for me on the custom theme?
I’ve checked my pages and only the archive/single pages have get sidebar function, as you suggested.
http://imageshack.us/photo/my-images/13/categoriesn.jpg/
http://imageshack.us/photo/my-images/577/categories2.jpg/
Never mind, I figured it out! I’ve thrown up 2 screens in case anyone else has my problem.
I just had to move the categories widget into the sidebar in the widgets area. First screen is it showing up on my blog page, just have to re-position it.
Thanks Amber, issue was bothering me for a while. lol
This may be a dumb question, but if the “home” template is in index.php how do you display the posts for a “blog” page?
You use the archive.php page for the posts