Developing a WordPress Theme from Scratch

Developing a WordPress Theme from Scratch

You know HTML, CSS, and JavaScript. You can make beautiful websites. Maybe you’ve heard about WordPress, but aren’t entirely sure how to implement it, or why you might need it. Maybe a client asked for WordPress, but you’re not really familiar with it. Maybe you’ve worked with it before, but don’t know how to make your own theme from scratch. Whatever the case, this article is for you.


All you need to start is a website. Any website will do. You don’t need to know any PHP, or have any prior experience with WordPress. Your website can be custom, or built on Bootstrap/some other framework.

You do need to know how to set up a local server environment. Fortunately, if you don’t know how, I wrote a short, sweet article about getting set up with one. It will only take a few minutes, so go ahead and do that first.


  • Install WordPress locally
  • Take an existing HTML website and convert it into a custom WordPress theme

I already know what WordPress is and how to install it! Show me how to create a custom theme.

What can WordPress do for me?

WordPress was originally built as a blogging platform, but is now what is known as a CMS – Content Management System.

Any website that you intend to make updates to can benefit from a CMS. If it’s a blog, you want to be able to add posts. If it’s a restaurant website, you want to be able to add and update menus. If it’s a company website, you want to be able to update prices, packages, and so on. This website is a custom theme running on WordPress. (Open source, too!)

If someone is paying you to make a website, it’s because they don’t know how or don’t have time to deal with code. It needs to be as simple as possible for the client. WordPress can help with all this and more.

Getting started: The design

I can’t stress enough how much it doesn’t matter what you use for your design – Bootstrap, Foundation, Skeleton, custom CSS. The point is that you have a website and you like how it looks.

I’m going to take an existing simple starter template and convert it into WordPress for this article.

Blog Template for Bootstrap

This is one of the default themes on Bootstrap’s official website.

I have conveniently set up a GitHub repository of the code that you can pull to a local directory and follow along with me.

Don’t know how to use Git/GitHub? You can remedy that by reading my Getting Started with Git article. If you just want to get started without dealing with Git, just create a directory on your computer with index.html and blog.css and you’re ready to go.

Installing WordPress

There are plenty of articles out there about how to install WordPress. They make the process seem long and scary, and the first time you do it, it can definitely be a bit confusing. Here is the official guide to getting set up.

Since we’re using a local server and MAMP, I already know you have all the prerequisites to installation, and FTP is not necessary.

Create a place for WordPress to live
Make an empty directory on your computer somewhere, and point your localhost or virtual host to that directory.

Download WordPress
Go to the WordPress download page and download the latest version of WordPress.

Unzip WordPress
Unzip WordPress and place the contents of the folder into your directory.

Create a database
Now, if you go to your local server in the browser, assuming the servers are on and everything is pointed to the right direction, you’ll get this message.

You’ll learn to love that message. In MAMP, click Open WebStart page. Find this near the top:

Click on phpMyAdmin. Click Databases > create database. I’m going to call mine startwordpress. That’s all you need to do in phpMyAdmin!

Configure WordPress
Alright, final step. Find wp-config-sample.php in your directory.

It will look exactly like this.

Don’t be nervous. Change the database name, username, and password, from this:

/** The name of the database for WordPress */
define('DB_NAME', 'database_name_here');
/** MySQL database username */
define('DB_USER', 'username_here');
/** MySQL database password */
define('DB_PASSWORD', 'password_here');

to this:

/** The name of the database for WordPress */
define('DB_NAME', 'startwordpress');
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'root');

Find this:

$table_prefix  = 'wp_';

And change it to literally anything else with numbers and letters. For security. ‘xyz_’ or “735hjq9_”, etc.

$table_prefix  = 'xyz77_';

Go to and replace the entire ‘put your unique phrase here’ with that generated code.

Save the file as wp-config.php in your directory.

Now, when you go back to your website and refresh, you should see this screen.

You’ll have to input a few things – username, password, e-mail address, and then you’re done. Congratulations, you have successfully installed WordPress! You will be redirected to /wp-login.php, where you can input your credentials to log into the backend. If you go to your main URL, You will see the default WordPress blog and “Hello, World!” post.

Creating your custom theme

Outside of configuring WordPress, almost everything you do in WordPress will be in the wp-content folder; everything else is core code, and you don’t want to mess with that.

From this point on, the WordPress Codex and StackOverflow will become your best friends. I’ll show you how to build a basic theme, but how you choose to customize your themes beyond that is totally up to you.

In Finder, follow the path of wp-content > themes to arrive at your themes folder. You’ll see the WordPress default themes – twentyfifteen, twentyfourteen, twentythirteen – and index.php. Create a new directory for your theme; I called mine startwordpress.

A WordPress theme needs only two files to exist – style.css and index.php.

In your custom theme folder, create style.css. It simply contains a comment that alerts WordPress that a theme exists here. Change the name, author, description, and so on.

Theme Name: Start WordPress
Author: Tania Rascia
Description: Bootstrap Blog template converted to WordPress
Version: 0.0.1
Tags: bootstrap

Remember the Bootstrap blog source code from earlier in the article? Move those two files – index.html and blog.css – to your custom theme folder. Rename index.html to index.php.

Your theme has now been created. Go to the WordPress dashboard, and click on Appearance > Themes. You’ll see the theme in the collection with all the default themes.

Activate the theme and go back to your main URL. Yep, it’s that simple. You’ve technically created a custom theme already. Of course, it doesn’t do anything yet beyond what a static HTML site can do, but you’re all set up now.

There is one thing you might notice – blog.css is not being loaded. Bootstrap’s main CSS and JS files are loading via CDN, but my local css file isn’t loading. Why?

My local URL may be, but it’s really pulling from wp-content/themes/startwordpress. If I link to blog.css with <link href="blog.css">, it tries to load, which does not exist. Learn right now that you can never link to anything in a WordPress page without some PHP.

Fortunately, this is easily remedied. There’s a few ways to do this, but I’ll show you the easiest way to start.

Locate where you linked to the CSS stylesheet in the head of index.php.

<link href="blog.css" rel="stylesheet">

We need to tell it to dynamically link to the themes folder. Replace your code with this.

<link href="<?php bloginfo('template_directory');?>/blog.css" rel="stylesheet">

If you reload the page, you’ll see that CSS is now loading in. The concept will be the same for images, javascript, and most other files you have in the themes folder, except PHP files.

Note that this is not the most correct way to load scripts into your site. It’s the easiest to understand and it works, so it’s how we’ll do it for now.

Dividing your page into sections
Right now, everything is in index.php. But obviously we want the header, footer and sidebar on all the pages to be the same, right? (Maybe some pages will have slight customization, but that comes later.)

We’re going to divide index.php into four sections – header.php, footer.php, sidebar.php and content.php.

Here’s the original index.php. Now we start cutting and pasting.

Header – header.php
Everything from <!DOCTYPE html> to the main blog header will be in the header file. The header usually contains all the necessary head styles and the top navigation to the website. The only addition I will make to the code is adding <?php wp_head(); ?> right before the closing </head>.

<!DOCTYPE html>
<html lang="en">

	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta name="description" content="">
	<meta name="author" content="">

	<title>Blog Template for Bootstrap</title>
	<link href="" rel="stylesheet">
	<link href="<?php bloginfo('template_directory');?>/blog.css" rel="stylesheet">
	<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
	<!--[if lt IE 9]>
      <script src=""></script>
      <script src=""></script>
	<?php wp_head();?>


	<div class="blog-masthead">
		<div class="container">
			<nav class="blog-nav">
				<a class="blog-nav-item active" href="#">Home</a>
				<a class="blog-nav-item" href="#">New features</a>
				<a class="blog-nav-item" href="#">Press</a>
				<a class="blog-nav-item" href="#">New hires</a>
				<a class="blog-nav-item" href="#">About</a>
	<div class="container">

		<div class="blog-header">
			<h1 class="blog-title">The Bootstrap Blog</h1>
			<p class="lead blog-description">The official example template of creating a blog with Bootstrap.</p>

Footer – footer.php
Same deal for the footer as the header. It will include whatever visible footer you have, your JS links (for now) and <?php wp_footer(); ?> right before </body>. Since I included the .container div in the header, I’m going to close it in the footer.

    </div> <!-- /.container -->

		<footer class="blog-footer">
      <p>Blog template built for <a href="">Bootstrap</a> by <a href="">@mdo</a>.</p>
        <a href="#">Back to top</a>

    <script src=""></script>
    <script src=""></script>
<?php wp_footer(); ?> 

Sidebar – sidebar.php
Most websites, especially blogs, will have a side area for including content such as archives, tags, categories, ads, and whatnot. (Content removed for brevity.)

<div class="col-sm-3 col-sm-offset-1 blog-sidebar">
	<div class="sidebar-module sidebar-module-inset">
		<p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>
	<div class="sidebar-module">
		<ol class="list-unstyled">
			<li><a href="#">March 2014</a></li>
			<!-- More archive examples -->
	<div class="sidebar-module">
		<ol class="list-unstyled">
			<li><a href="#">GitHub</a></li>
			<li><a href="#">Twitter</a></li>
			<li><a href="#">Facebook</a></li>
</div><!-- /.blog-sidebar -->

Content – content.php
If the sidebar is where all the secondary information goes, the content is where all the articles and main content of the website go. (Content removed for brevity.)

<div class="blog-post">
	<h2 class="blog-post-title">Sample blog post</h2>
	<p class="blog-post-meta">January 1, 2014 by <a href="#">Mark</a></p>

	<p>This blog post shows a few different types of content that's supported and styled with Bootstrap. Basic typography, images, and code are all supported.</p>

<!-- the rest of the content -->

</div><!-- /.blog-post -->

The index file should be pretty sparse now. In fact, it should only be this:

<div class="row">
	<div class="col-sm-8 blog-main">
	</div> <!-- /.blog-main -->
</div> 	<!-- /.row -->

Now we’re going to add everything back in. Here’s your new index.php.

<?php get_header(); ?>

	<div class="row">

		<div class="col-sm-8 blog-main">

			<?php get_template_part( 'content', get_post_format() ); ?>

		</div> <!-- /.blog-main -->

		<?php get_sidebar(); ?>

	</div> <!-- /.row -->

<?php get_footer(); ?>

Even if you’ve never used PHP before, this code is all very self explanatory. get_header();, get_sidebar(); and get_footer(); are all functions that look for their respective .php files and insert the code. Of course, they all go inside their own <?php ?> tags to let the server know to parse them as HTML. The content function is slightly different, but it does the same thing.

If you re-load your URL, your entire site is now loaded, just as before. You will notice a top bar if you’re logged in to the back end.

Main Settings

Before we start pulling in posts and pages, we need to configure some main settings of WordPress. For example, my title right now is “The Bootstrap Blog”, hard coded in HTML. I want the <title> and h1 of my site to be changeable through the back end.

In your dashboard, go to Settings > General. Set your title.

In header.php, change the contents of the title tag and main h1 tag to this code:

<?php echo get_bloginfo( 'name' ); ?>

And the description to this one.

<?php echo get_bloginfo( 'description' ); ?>

Finally, I want the title to always take me back to the main blog page. bloginfo('wpurl'); is the code that will do that.

<a href="<?php bloginfo('wpurl');?>"><!-- site title --></a>

Here’s the full code in case you’re confused.

<div class="blog-header">
	<h1 class="blog-title"><a href="<?php bloginfo('wpurl');?>"><?php echo get_bloginfo( 'name' ); ?></a></h1>
	<p class="lead blog-description"><?php echo get_bloginfo( 'description' ); ?></p>

We’ve finally made the first dynamic change to the page. The front end should reflect what you put in your settings.

Now go to Settings > Permalinks. By default, WordPress is set to Day and name, which is a really ugly URL structure. Click on Post name and apply the changes.

The Loop

The most exciting part is being able to dynamically insert content, and in WordPress we do that with The Loop. It’s the most important function of WordPress. All of your content is generated through a loop.

In the dashboard, if you click on Posts, you will see a “Hello, world!” post in there by default. Our goal is to display that post in the blog.

The Loop itself is quite simple.

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

<!-- contents of the loop -->

<?php endwhile; endif; ?>

It explains itself – IF there are posts, WHILE there are posts, DISPLAY the post. Anything inside the loop will be repeated. For a blog, this will be the post title, the date, the content, and comments. Where each individual post should end is where the loop will end. We’re going to add the loop to index.php.

Here’s your new index file.

<?php get_header(); ?>

	<div class="row">

		<div class="col-sm-8 blog-main">

			if ( have_posts() ) : while ( have_posts() ) : the_post();
				get_template_part( 'content', get_post_format() );
			endwhile; endif; 

		</div> <!-- /.blog-main -->

		<?php get_sidebar(); ?>

	</div> <!-- /.row -->

<?php get_footer(); ?>

The only thing inside your loop is content.php, which will contain the contents of one single post. So open content.php and change the contents to this:

<div class="blog-post">
	<h2 class="blog-post-title"><?php the_title(); ?></h2>
	<p class="blog-post-meta"><?php the_date(); ?> by <a href="#"><?php the_author(); ?></a></p>

 <?php the_content(); ?>

</div><!-- /.blog-post -->

It’s amazingly simple! the_title(); is the title of the blog post, the_date(); shows the date, the_author(); the author, and the_content(); is your post content. I added another post to prove at the loop is working.

Awesome. Let’s make the sidebar dynamic, as well. There should be a description and archive list in the sidebar. In the dashboard, I’m going to edit my user description to say “Front end web developer and professional nerd.”

Delete all the lis under Archives and change it to this code.

<ol class="list-unstyled">
	<?php wp_get_archives('type=monthly'); ?>

For my description, I’m going to pull in metadata from my user account.

<p><?php the_author_meta( 'description' ); ?> </p>

Now this content is being pulled in dynamically as well.

Here’s my blog so far.

Menu and Pages

Okay. Now we know how to make a blog, and edit some sidebar content. Only one main aspect of this page remains – the navigation, and where it leads. Well, there are two main aspects to WordPress – Posts and Pages. They’re very similar in that they both use the Loop. However, pages are where you put content that isn’t a blog post. This is where the CMS aspect of WordPress comes in – each individual page can be as customized as you want.

In the dashboard, I added a page so we can see two. First, we’re going to edit the navbar so that the links lead to the pages. Back in header.php, find and change this code.

<div class="blog-masthead">
	<div class="container">
		<nav class="blog-nav">
			<a class="blog-nav-item active" href="#">Home</a>
			<?php wp_list_pages( '&title_li='); ?>

wp_list_pages(); will list all the pages you have in an unordered list. 'title_li=' is telling the code not to add a “Pages” title before the list. Unfortunately for us, this looks terrible; the original blog.css has the links coded in a tags, not li tags.

Fortunately, this is a very easy fix. I’m just going to apply the style from one to the other. Add this to blog.css

.blog-nav li {
    position: relative;
    display: inline-block;
    padding: 10px;
    font-weight: 500;	
.blog-nav li a {
    color: #fff;

Much better.

Page – page.php

I want the pages to have a different layout than the blog posts; I don’t want sidebars on them. Think of index.php as the blog-index and page.php as the page-index. I’m going to create page.php, which will be very similar to the index except have a full 12-wide grid instead of an 8-wide content and 4-wide sidebar.

<?php get_header(); ?>

	<div class="row">
		<div class="col-sm-12">

				if ( have_posts() ) : while ( have_posts() ) : the_post();
					get_template_part( 'content', get_post_format() );
				endwhile; endif; 

		</div> <!-- /.col -->
	</div> <!-- /.row -->

<?php get_footer(); ?>

When I click on my sample page, the layout is now different than the blog post layout.


There is much, much more to learn about WordPress. I sincerely hope this article opened a world of possibilities to you. Now you know that any website can be converted into a WordPress theme – without using plugins, widgets, or someone else’s theme.

If something was unclear, please let me know. If I’ve posted any blatantly incorrect information, please let me know! Any feedback is greatly appreciated! My aim was to make the article I wish I had in front of me when I first started learning how to use WordPress and PHP.

I’ve also uploaded the entire theme as it stands at the conclusion of this post to GitHub.

View Source on GitHub Migrating WordPress

Part Two

Update 1/14/16

In part two, I discuss additional functionality for WordPress, such as paginaton, comments, functions, custom post types, and more.

Go to Part 2

142 comments on “Developing a WordPress Theme from Scratch”

  • Bert-Jan van den Brink says:

    Hi Tania,

    You Rock. and you should give paid courses. I know i would gladly pay for content like this. This was a huge eye-opener for me and it made my day.

    Just wanted to let you know!

    Kind regards,

  • nidhi says:

    how to create sidebar section?? please explain

  • nidhi says:

    how to create sidebar section? where we will put sidebar content? please explain

  • Binu Mathew says:

    To be frank, this is a good article, it have basic details about how to develop a theme in wordpress, let me share with some of my psd2html guys πŸ™‚

  • Mark Hallam says:

    Would be great if you had an index for this series on each page so we could skip ahead to relevant information. Thanks.

  • Janet Fuller says:

    Hi Tania,

    Thank you very much for your professional tips. I have problem with my website. My website is and my problem is that when I put this link anywhere such as Facebook, Twitter and Pinterest, preview image comes blank.

    Can you help me out ?


  • Is it feasible to create a theme truly from scratch? I mean literally from scratch: No framework, no parent theme, no anything.

  • Manish sharma says:

    Wow,thanks to share this.

  • rahul808 says:

    Thanks for the tutorial

  • El Mehdi says:

    Thank you very much for this tutorial!
    i’m thing part 2 this afternoon πŸ™‚

  • Gediminas says:

    Great tutorial, Tania! I had problems with a the loop at first. A tip for everyone who already had been using WordPress. Go to Settings > Reading and make sure Front page displays latest posts and not a static page.

  • Pierre says:

    Hi Tania, I greatly appreciate your excellent post!

    I’ve worked through everything, but still end up with the below heading just above my posts. I will appreciate your guidance on how to remove it!

    The Bootstrap Blog
    The official example template of creating a blog with Bootstrap.

    • Pierre says:

      Hi, I worked through the process again and realized that I did not delete the original “blog title” ….. need I say more…. πŸ™‚

  • Rashed khan says:

    Hello Tania,

    nice and very Helpful tutorial. I want to learn single page wordpress theme development. Can you give me good tutorial that will be good for everybody.

  • Hein Htet Aung says:

    It’s pretty awesome. Thank you that’s what I need.

  • Sandeep says:

    Hi Tania,

    Thank you so much for this useful article about wp. I searched best tutorial to learn and develop my own theme from scratch. This is the one really useful for beginner like me.

  • yahya says:

    Terima kasih atas panduannya, sangat mudah dan bisa saya ikuti.
    Terus berkarya, masih banyak yang membutuhkan artikel ini.

  • dan says:

    Hey thank you for taking time to write this article. You’re awesome. I have few questions hope you answer them.

    What happens to the theme if I upgrade WordPress when it asks?
    Will it go along or need to change some changes to the theme to reach the upgrade? (heard of child theme)
    If a plugin is upgraded which part of the theme effects? example: Recent Posts plugin.

    I’m new to WordPress wanted to start a huge database site on this platform. I’m so worried to start developing the site. I Have many questions.

  • Ewan says:

    Really excellent tutorial, thanks a lot!

  • Tilo says:

    Hello. After cutting and pasting, my index file does not look like that. I have the pager class with previous and next still there. Where was that supposed to go?

  • Matias says:

    Hi, I have a doubt. I’m not a WP guy, but I have some years coding in different programming languages.

    My question is why would you need something like this:

    if ( have_posts() ) : while ( have_posts() ) : the_post();

    As far as I understand both ‘if’ and ‘while’ statements will evaluate booleans. My understanding is that the ‘while’ statement alone should suffice, unless I’m missing something. Maybe is just the way things are done in WP. Can you please explain that part?

    Aside from that, I found your post very interesting. Thanks.

    • mementototem says:

      In this tutorial, yes, it useless to use if and while combine.

      But this make for: if no post then display ‘some message’ like post new entry or something like that, but she omitted it

    • Tania says:

      The if isn’t exactly necessary, but that’s the way it’s usually written in WordPress, and it gives you the option to do something after the if and before the while. You can just use while if you prefer.

  • Ivan says:

    Thanks very much. This is a great piece of info.
    Kind regards.

  • Very helpful post. I may be my first step in wordpress.

  • yinkdesigns says:

    Please what is the difference between style.CSS and blog.css

    • style.css is going to be used by WordPress to detect and display information about the theme. You could as well use it for styling your page, no problem at all! This is, you could even copy all the styling from blog.css and paste it in style.css and add that sheet instead of blog.css.

      While blog.css (and other styling files you might have) are not mandatory, you MUST have a style.css if you want the theme to be listed in your themes tab.


    • Anonymous says:

      Dear only Change the name

      Blog.css > <link href="/blog.css” rel=”stylesheet”>
      style.css > <link href="/style.css” rel=”stylesheet”>

  • Anonymous says:

    What happened to the little white arrow under selected page in the header navigation? It seems to have disappeared after changing the blog.css file. Just curious.

  • You’re a lifesaver.
    I have always been a visual-tactile learner so it always helps me when learning to work along with someone as they do it. This provided me with a really good idea of the kind of workflow and thought process needed to work with wordpress themes.
    That’s the hard part imo.
    Thank you so much!

  • Alex Valius says:

    Thanks Tania! You’re my hero! I just needed a simple WordPress blog and you save me a lot of time for that!

  • dweep says:

    as usual great article. I tried hard to build one.

  • Shashi says:

    Thank you soo much…..i loved the way to explained in this article. pls publish like this more you made my day by learning custom wordpress. thanks sister. we need you to come more like this. god bless u

  • Thank you!
    Much appreciated
    Excellent Article!. I don’t understand wordpress before read this articles. all your articles are very usefull. i hope you continue post articles. i read all your article because i like it. it learning me more about web development. and i make my first wordpress theme from learning here and i upload in my website soon.

  • Tofa Hassan says:

    What a wonderful tutorial, thanks a lot.

  • Tofa Hassan says:

    Thank you Tania…

  • Brockney C says:

    Wow, thank you so much!

    I am more familiar with Joomla CMS and recognise that the ability to use WordPress too is important. This is a great starting point and much appreciated!

    Your site has been bookmarked for sure and I’m looking forward to digging deeper!

    Cheers πŸ™‚

  • cedric says:

    thanks to tutorials like yours I was able to make the first version for WordPress of my theme generator available on
    So thank you

  • gaurav singh says:

    hi mam . now i am beginner wordpress developer . so plz help me guide me . how to convert html static page to dynamics in wordpress

  • Justin Velalloor says:

    It is an awesome article which is helpful. i like it.

  • I have the same wish and you have fulfilled it. Thanks so much!

  • Tomas says:

    Hi its me again. This time with a name. πŸ™‚ Juts for completion, i am using XAMPP. Also here are some screenshot from what i have done:

    I rly do not see any mistake. Maybe something change since u have made tutorial?

  • Anonymous says:

    I stuck pretty early. I created new folder for my theme in themes folder and add files index.php, style.css, blog.css. Then i went to the wordpress options to activate my theme but i cant see it there. Where could be the problem?

    • Tania says:

      Your style.css needs to be in the root of the folder and have the proper comments.

      • Tomas says:

        It is in root. The problem was that the theme was not enbaled yet. I need to go mysites/networkadmin/themes and there enable the theme. Then i could see it in appearance/themes and activate it. Maybe someone will ahve similar issue a this will help him.

        Thank you

  • Jess says:

    Hello Tania,

    I am experienced in customizing other themes and wanted to try to make my own, so I found your site via search. Having experience with WordPress already, I found it easy to follow your instructions and I now can see how each file fits into the whole. I set up the server using Cloud 9 and am running everything from there. I did have a problem in renaming my stylesheet which I am still trying to resolve, but beyond that I found it a quick and easy guide! Thanks very much and I look forward to doing part 2 now.

  • jjerro says:

    Hi Tania, thank you for everything you provides here, i have created my own template based on your tutorials. but there’s a problem, i’ve created 2 sidebars; left and right, but the second[right] sidebar seems doesn’t showing in my index.php, it is loaded in admin widget page, and functioning, i can drag/drop any widget but nothing shows in homepage. here’s my functions.php:

    //register widget if ( function_exists('register_sidebars') ) 
    register_sidebar(array( 'name'=>'sidebar', 'before_title' => ' ', 'after_title' => ' ', 'description' => 'Drag widget to this area to show it in left sidebar.')); `register_sidebar(array( 'name'=>'right', 'before_title' => '
    <h4 class="in-widget-title">
      ', 'after_title' => '
    ', 'description' => 'Drag widget to this area to show it in right sidebar.'));
  • femibams says:

    Hi tania, nice tutorial, i got stuck at the last part, i created the page.php file but i’m getting this error when i try to open the “new page” link – “The requested URL /wordpress/new-page/ was not found on this server.”

  • Agustin says:

    I love you very very much after reading this wonderful tuturial.Yes Tania,you are so great and beauty that not just for your appearance but also your wisdom

  • Jerro says:

    Tania, only one word: Superb! I’ve been wandering to create my own template but i was confused about the basic functions and features. you saved me. thank you very much.
    I’m looking forward to your future articles.

    bookmarking your site now. πŸ™‚ πŸ™‚

  • Uchenna says:

    Tania Thanks once more. I am having a problem with my menu Currently this is what i have in my blog.css

    • Tania says:

      It’s hard for me to tell what your site looks like and what it’s missing by posting the entirety of your code. If you show me an example of how the site looks, I might be able to help you.

  • Uchenna says:

    sweetie. Thanks for this guide. I love you. Please My Menu still dispays abnormal even though I followed all you said. Can you guide me from this point

  • Paul J says:

    Great article and very helpful. Seem to be stuck on one little thing though. Have added to the blog-nav but the link to my page takes me to 404 Not Found page.
    Have set Permalinks to PostName but I can’t view my page on them (local set up) eg http://wordpress/my-new-page/
    What could I be missing?
    Thanks Paul

  • Dylan says:

    Thanks for the tutorial! It’s been super helpful so far, but I’m running into a problem pretty early on. When I break the index.php into header, footer, content, & sidebar .php files, my site stops loading entirely. I get an error (500) message that says “The localhost page isn’t working. Localhost is currently unable to handle this request.” If I go back to the original index.php code everything works again. Any ideas? Is that a server issue? (I’m using MAMP, by the way.)

    Anyway, thanks again!

    • Tania says:

      Try doing it one at a time. Most likely a <?php ?> is not being closed, or an if statement is missing a bracket. Try just doing the header or footer, and see how it goes.

  • Sujith says:

    Thank you so much. But the date is showing only on the top post in a page..and not on any other posts. Other posts show only the author. Why is it so?

  • Naresh Kumar says:

    Thank’s Tania,Wonderful tutorial

  • Anonymous says:

    Very nice post, thank you ^v^

  • Srivin Prabhash says:

    Hey ,

    Thanks for the tutorial .. But i would like to know about single.php .. How to make that page which is open when we click on a Readmore button ..

    Thanks !

    • Tania says:

      < ?php the_permalink; ?> will lead to your single page.

      • Srivin Prabhash says:


        Thanks for the reply.I linked my post title to it’s permalink using the the_permalink() func. Now it’s opening with the URL. But how to make the template for single post. I mean I created the single.php file and just echo the content, but it’s not showing post content.

        Note : I have made post name structure in Permalink Options.

        Thanks !
        Srivin Prabhash

  • X says:

    Terrible… This is a tutorial for people who already know what their doing… Or for people who only littarly copy your every move.. Some explenation on Why/Where certain file names/links etc. come from would be nice…

    • WP1331 says:

      I’m sorry, but I don’t agree… Started today with wordpress and following this tutorial I was able to create my whole theme from scratch. Congratulations to the author, terrific article!

  • Wonderful tutorial Tania; Thank you very much for this!

  • Christy says:

    Wonderful tutorial, thank you so much! That was very helpful and easy to understand!

  • Umair says:

    Explanation Appreciated !! never seen such neat and clean explanation :).

  • Shane says:

    Great article Tania πŸ™‚ Was very easy to follow and I finally got round to coding my first WordPress Theme.

    Thanks for the help! Now onto Part 2!

  • Rishabh Jain says:

    Hi I wanted to create another theme for WordPress and that theme has a header background image there can be a slider too .. My question is in which file should i include the slider markup in header.php or in index.php

  • Aravind says:


  • Kenan says:

    This is one of the best tutorial i have ever come across. Thanks for this

  • Dan I M says:

    Not so long ago I learned the fundamentals of html, css, js and php because I wanted to start learning how to create my own WP themes using Bootstrap and Foundation. This article is very thorough and clear in introducing the basic concepts of WordPress. Thank you!.!.! Are there any articles that talk about customizing WP Theme frameworks such as Reverie by ThemeFortress?

  • Mladen says:

    It was very easy to follow. I am coming from NodeJS enviroment, and i always thought that this WP thing is complicated. Now i see its not. One more thing could be done here. For example, pages should not have date and posted by info on the screen. So we can just create for example, page like page-content.php, where we will not include those info, and insted of
    get_template_part( ‘content’, get_post_format() ); we just put
    get_template_part( ‘page-content’, get_post_format() );
    And thats it, it looks less like a post and more like a page πŸ™‚ Cheers πŸ˜€

  • Darrell says:

    Just want to say cheers for this awesome introduction to wordpress!!!

  • Alain Elemia says:

    Thank you very much! Very informative! Thanks thanks thanks!

  • jl says:

    Hello! I keep getting “ERR_CONNECTION_REFUSED” when I try to access Also pointed this to my http.condf file and restarted my servers.

    Would greatly appreciate any help, thank you!

  • jl says:


    I have trouble moving beyond the unzipping of WP contents. I moved them to a folder called ‘learnphp’ on my Desktop. But when I tried to go to, it gave me the error message – ERR_CONNECTION_REFUSED.

    I did the exact same steps in your tut to setting up virtual hosts. I also pointed in my http:condf.

    Would greatly appreciate some advice! πŸ™‚

    • Tania says:

      I would try to get a basic “Hello, World!” working in PHP before beginning on setting up WordPress. Since WP issues are different than setting up the server issues. It’s hard to say what part in the process you may have missed. So you have a vhost in httpd.conf pointing to the exact folder where your index.php is, and all the ports set?

      • jl says:

        Hey yep,

        So I got “Hello, this is a test page in the year of 2016.” in, which is a result of displaying the index.php file from the earlier tutorial. My workflow is:

        Desktop > learnphp > unzip WP to there, alongside with the index.php file from the prev tutorial.
        In AllowOverride in http:conf, I only Allow All for the SymLinks as below:

        Options FollowSymLinks ExecCGI
        AllowOverride All
        Order deny,allow
        Allow from all

        (for the rest, AllowOverride remains set to None)
        In http:conf, I added the following:

        DocumentRoot “C:/Users/User/Desktop/learnphp”

        DocumentRoot “C:/Users/User/Desktop/learnphp”

        And I also added these two lines to my hosts file (in Notepad++ though)

        And all these are done with constant restarting of servers on MAMP as well.

        I think the steps in the tutorial are very thorough already, but I’m not sure where I’m missing out on.

        • Tania says:

          If your test page is working, than you do NOT need to worry about your configuration anymore. If regular PHP works, everything is good. Now it’s about WordPress. You need to make sure you’re connecting to the database correctly. Make sure you’ve created the database in PHPMyAdmin and have it set to localhost, root, root.

        • Emma Page says:

          Firstly ,thanks dear for the deep knowledge on WordPress.Your article will really help out for many begineers.I have not seen your blog before,else would have learnt from it.

          Haha,I used to learn WordPress From TemplateToaster Blog.

  • Andrea Sanchez says:

    Hi there!! Great tutorial, I have to say, I was stuck in the database configuration for a couple of days, because I kept getting Error connecting with DataBase, after going through a lot of googling, I discovered my mistake was in the DB password, instead of input “root” I had to leave it blank, that was it! Everything worked fine after that. Hope this helps someone in the same situation.

    • Tania says:

      Interesting, were you setting it up on a live server? If you have phpMyAdmin set up on your host, it might be an empty password if you haven’t defined it, but on MAMP it will be root, which is why I didn’t think about that.

  • ali says:

    URL by post name is not working for pages.I checked the github source also and the code i have is similar and i did change the settings > permalinks to PostName. But it shows an error when click the page link. When iam doing it with ‘Plain’ or any other settings in Permalinks, it works except only for ‘Post Name’. Kindly see what is wrong in here.

    • Tania says:

      Are you doing this on a live server? Does your .htaccess file have 666 permissions or higher?

      There should be something like this in the file:

      <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteRule ^index\.php$ - [L]
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . /index.php [L]
      • R K says:

        I am having this same problem and I am on localhost. I also switched the post type and it worked, as this person did, but when I have it set to the one you specify I get a 404 page. Any ideas?

  • Rohit says:

    Tania nice tutorial. Never knew it was that easy…Hats off

    • Mahmoodur Rashid says:

      Awesome tutorials . I can say that anyone else in world would not be able to teach as easily as you .Thanks for the wonderful article

  • Govindaraj says:

    Really good guide for newbie to develop wordpress theme.


  • Hello, Tania.

    First off, thank you very much for this fantastic tutorial.

    I’m stuck at the following part:

    “Fortunately, this is a very easy fix. I’m just going to apply the style from one to the other. Add this to blog.css

    .blog-nav li {
    position: relative;
    display: inline-block;
    padding: 10px;
    font-weight: 500;
    .blog-nav li a {
    color: #fff;

    Do I have to change this code for another? In that case, for which one? I just tried to add it to blog.css but the navigation menu unfortunately doesn’t change its appearance.

    Thanks a lot!

    • Tania says:

      Well, it should definitely work if it’s being loaded.

      1. Make sure you’ve changed out the original navigation for the wp_list_pages() code.

      2. If that doesn’t work, try putting the CSS in <style> tags in the head of your document.

  • Nemanja says:

    Hi Tania, Thank you for your work, its simple and its best start. I have one q tough, its about last thing and page.php. The issue that i came across is that link take me to page, but nothing gets displayed.It says:
    Not Found

    The requested URL /wordpress/this-is-new-post/ was not found on this server.

    So pls help me with that issue since i get same problems when i go in part 2 of tutorial about single.php

    • Tania says:

      I’m confused as to why wordpress/ is in your URL. Try going to Settings and pressing “Update Permalinks”. Otherwise, as long as you put the code for page.php in /wp-content/themes/yourtheme, it should work.

  • Dee says:

    Hi Tania,
    I’ve created a folder in the themes folder for my new theme and added the index.php, style.css and blog.css. It looks all set, but it doesn’t appear at all when I go on Appearance > Themes on the Dashboard. My MaMP is running etc.
    Any ideas?

    I tried uploading and installing as a zip but it doesn’t seem to let me edit it within the code on my computer when I do this.

    • Tania says:

      If WordPress is running, and you have a folder in /wp-content/themes with index.php and style.css, it should appear. The CSS file needs the comment at the top. If you send a screenshot, maybe I can help more.

  • Deepa says:

    This tutorial is simple and effective. Great learning place for the wordpress beginners. Thanks

  • mugianto says:

    it will be great if you make this tutorial on video like this:

    sadly it wrote on Indonesian Language Y_Y
    it will more easy to understand for begginer like me

  • Mark says:

    Hi Tania, I had to post to say a massive thank you for taking the time to do this, so that people like me can benefit – for free. It’s a phenomenal tutorial and I wish it had been around when I last looked at doing this 2 years ago. A brilliant resource that I’m sure many people like me are very grateful to benefit from.


  • Yan says:

    Probably the best guide I have ever read on wordpress theme development. Great job. Much appreciated.

  • Harman Gulati says:

    simple and easy explanation. Awesome Stuff Mam

  • Marie Thomas says:

    This is really a great informative tutorial for wordpress development.Tania I really appreciate your willingness to learn more about web development.Keep updating more about wordpress.Looking forward for some new posts.

  • Razvan Maftean says:


    I got stuck at installing WordPress. After unzipping it, I copied the content of the folder and pasted it in my website’s folder which includes all my HTML & CSS files, however I don’t get any error message. The website loads normally as before.

    Any idea where I went wrong? I’m using MAMP on Windows 7.

    • Tania says:

      Yes, the reason that doesn’t work is because HTML files will override PHP files. If you have an index.html in the same folder, that will load instead of index.php. You should install WordPress into a fresh, clean directory for all learning purposes, and keep a backup of your HTML and CSS files elsewhere.

      • Razvan Maftean says:

        When I do that I get a page for setting up wordpress, no error page. Did I setup something wrong with MAMP?

        • Tania says:

          If you get a page for setting up WordPress, it means MAMP is correctly installed, and you should follow the instructions for the setup. The installation is slightly different depending on whether you created a wp-config.php or not, but either way it should be pretty straightforward. As long as you don’t get a “Error establishing a database connection” message, you’re doing fine.

  • MCHL says:

    Hi, I tried to follow your tutorial. Firstly I got stuck on the step with PhpMyAdmin. The user root and password root in the wp-config.php didn’t work, because apparently you have to define password root in PhpMyAdmin user settings too. Secondly now I am stuck on the apperance step. It says “WPtest – Stylesheet is missing.”, but as far as I can see, index.php is linking to blog.css :(.

    • MCHL says:

      Well, nevermind on the apperance thing. I forgot how to read πŸ˜› I though the blog.css was meant to replace the style.css. But the first thing was an issue with PhpMyAdmin.

  • Carlos says:

    I followed each step and when I go to appearance the new theme details is not showing up. it shows blank but when I hit customize the blog site shows up. Any reason why this is happening? I am using Opera browser.

    • Tania says:

      Are you trying to customize is through the Appearance tab? This very simple WordPress theme is not set up with the customizer, so any customization will have to be done through the code.

  • Ryan says:

    Ah this tutorial is going to become very handy in the next few days. I made a website for one of my friend’s small businesses with Bootstrap but he would prefer using a CMS like WordPress. Thanks πŸ™‚

    P.S. My path is similar to yours, I grew up making websites starting at 13 years old on notepad and a little bit of dreamweaver, loved every minute of it over my teenage years but eventually pursued other interests. Fast forward 14 years later, and here I am diving back into HTML/CSS and Bootstrap the past month. Looking back, I wish I would have just pursued a career in web dev, it’s so fun creating and getting the satisfaction of completing projects.

    I am seriously considering a career change, I am wondering if you could comment on the path you took to get where you are now. Also wondering if you’re doing this as a career now or as an independent learning experience and any other tips you’d like to offer.


    • Tania says:

      Hi there! I’m glad you found my tutorial useful. There was no good, easy guide that I could find about that task, so I set out to make it easier for others in the future.

      As far as the career change, I do work as a web developer now. I’ve never had a class or course on anything web development related, but I made many websites throughout the years for a hobby.

      Deciding to change careers was not easy – it’s hard to leave everything you know, everything you’ve studied and already know you’re good at and successful, but it the end it was easily the right choice for me. The first thing I did was begin perusing online for freelancing jobs. I didn’t have much of a profile at all to go off, but I managed to find work. I didn’t even know JavaScript, PHP, or any back end language at the time – only HTML and CSS.

      From there, I found an unpaid internship position with an acquaintance who had a web development company. I interned for a few months there, as well as working a regular job for some income, and looked for junior web development positions in the meantime. Most didn’t respond, but eventually some did, I interviewed, and got the job.

      All I can say is, just as with anything else, what you learn is up to you. Flexibility is key above all things, and a good attitude. If you’re willing to learn and open minded, you’ll get there.

      • Ryan says:

        Very cool, thanks for sharing πŸ™‚ Knowing others have been able to accomplish a similar goal is encouraging.

        I’m glad you were able to find success doing something you love. I look forward to more of your tutorials and blogs!


  • Sumir says:

    Hi Thank you for the tutorial! I learnt alot, because of the way you explained it.
    I have two suggestions :

    1. Uhm, I faced some confusion deciding what to do with the below code becuase it is not mentioned πŸ™‚ Eventually, I put it in the content.php

    <a href="#" rel="nofollow">Previous</a>
    <a href="#" rel="nofollow">Next</a>

    2. Please can you host the finished product somewhere, so that we can compare before and after code.

    Thanks again!

    • Tania says:


      1. Sorry, I didn’t get that far in the tutorial. I’m planning a part two! What you’re referring to is pagination.

      In your loop, you have this:

      <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
      <!-- content -->
      <?php endwhile;?>

      At this point, you can type this:

      <?php previous_posts_link();?>
      <?php next_posts_link(); ?>
      <?php endif; ?>

      And you will have your pagination.

      2. All the source is on GitHub, here, but I can upload one page of what it looks like. You won’t be able to see the PHP code live because it gets processed by the server.

  • jsmith says:

    This guide is excellent! Thank you! Do you know of any good resources to help me get started to add a simple custom plugin to this theme as well? I want to work on learning how to integrate plugins.

    • Tania says:

      Thank you, I’m so glad you found it useful! what kind of plugin do you want to add? Are you talking about creating your own plugin? Or are you talking about integrating existing plugins with your custom theme? Let me know and I can direct you to a source or work on an article.

  • antonio says:

    hey. i’m a law student, a newbie to all this (gesture with arm implying “everything!” yelled in a community way), but i wanted to create a wordpress based site with a good theme without spending too much money (or any, if possible). I reckon this message may put me in the ranks of nigerian princes crying for help, but i swear i just want a simple advice from someone who knows her internet stuff (sorry for getting too technical).
    so, basically: 1- can i edit a wp theme without paying for a premium one [i was thinking in a three collumns one, where in each column theres a box with image+text, with “read more”]?
    2- if not, is creating a wp hosted site a good idea?

    sorry for the trouble, and thank you for this tutorial. I felt like I knew things about stuff

    • Tania says:

      Knowing things about stuff is always important! You can definitely do anything you want with in WordPress without paying for a custom theme. If you don’t want to go through the effort of making your own theme, like this tutorial teaches, there’s a host of free WordPress themes out there. Here is the official WordPress theme page, where you can find plenty of free themes.

      The only thing that will cost you is hosting your website, and there are plenty of cheap and even free options for that.

Leave a Reply

Your email address will not be published.

Markdown is enabled in comments. If you would like to post code in your comments, please indent your code by four spaces. HTML/PHP code must be escaped. Failure to do so will make me sad.


    def print_hi(name)
      puts "Hi, #{name}"