Theme Basics
Required Files
style.cssTheme metadata header + styles
index.phpFallback template (required)
functions.phpTheme setup, hooks, enqueue
screenshot.pngTheme preview (1200x900)
style.css Header
/* Theme Name: My Theme Theme URI: https://example.com Version: 1.0 Requires at least: 6.0 */
functions.php Setup
add_action('after_setup_theme', function() { add_theme_support('title-tag'); add_theme_support('post-thumbnails'); add_theme_support('html5', ['search-form', 'gallery']); register_nav_menus(['primary' => 'Main Nav']); });
Template Hierarchy
Page Templates
front-page.phpStatic front page
home.phpBlog posts index
single.phpSingle post
page.phpSingle page
archive.phpPost archives (date, category)
category.phpCategory archive
search.phpSearch results
404.phpNot found
index.phpUltimate fallback
Template Parts
get_header(); // header.php get_footer(); // footer.php get_sidebar(); // sidebar.php get_template_part('parts/card'); // parts/card.php get_template_part('parts/card', 'featured');
Lookup Order (Single Post)
1single-{post_type}-{slug}.php
2single-{post_type}.php
3single.php
4singular.php
5index.php
The Loop
Standard Loop

Template Tags
the_title()Print post title
the_content()Print post content
the_excerpt()Print post excerpt
the_permalink()Print post URL
the_post_thumbnail()Print featured image
the_date()Print publish date
the_author()Print author name
the_category()Print category links
Getters (Return, Not Print)
$title = get_the_title(); $url = get_permalink(); $id = get_the_ID(); $thumb = get_the_post_thumbnail_url(null, 'medium');
Custom Post Types
Register CPT
add_action('init', function() { register_post_type('product', [ 'labels' => ['name' => 'Products', 'singular_name' => 'Product'], 'public' => true, 'has_archive' => true, 'supports' => ['title', 'editor', 'thumbnail'], ]); });
Custom Taxonomy
register_taxonomy('brand', 'product', [ 'labels' => ['name' => 'Brands'], 'hierarchical' => true, 'rewrite' => ['slug' => 'brand'], ]);
Supports Options
titlePost title field
editorContent editor
thumbnailFeatured image
excerptExcerpt field
custom-fieldsMeta box for custom fields
page-attributesMenu order, parent
revisionsRevision history
Hooks & Filters
Actions (Do Something)
// Register a hook add_action('wp_head', 'my_analytics', 20); function my_analytics() { echo ''; }
Filters (Modify Data)
// Modify the excerpt length add_filter('excerpt_length', fn() => 30); // Append text to every post add_filter('the_content', function($c) { return is_single() ? $c . '

Thanks for reading!

' : $c; });
Key Hooks
initWP initialized; register CPTs here
wp_enqueue_scriptsEnqueue CSS/JS
wp_headOutput in
wp_footerOutput before
save_postAfter a post is saved
pre_get_postsModify main query before execution
the_contentFilter post content output
the_titleFilter post title output
WP_Query
Custom Query
$q = new WP_Query([ 'post_type' => 'product', 'posts_per_page' => 10, 'orderby' => 'date', 'order' => 'DESC', ]); while ($q->have_posts()) : $q->the_post(); the_title('

', '

'); endwhile; wp_reset_postdata();
Common Parameters
post_typepost, page, or custom type
posts_per_pageNumber of results (-1 for all)
category_nameFilter by category slug
tagFilter by tag slug
sSearch keyword
meta_key / meta_valueFilter by custom field
tax_queryAdvanced taxonomy filtering
date_queryFilter by date range
Modify Main Query
add_action('pre_get_posts', function($q) { if (!is_admin() && $q->is_main_query() && is_home()) { $q->set('posts_per_page', 5); } });
REST API
Built-in Endpoints
/wp-json/wp/v2/postsList / create posts
/wp-json/wp/v2/posts/{id}Get / update / delete post
/wp-json/wp/v2/pagesPages endpoint
/wp-json/wp/v2/categoriesCategories endpoint
/wp-json/wp/v2/mediaMedia library
/wp-json/wp/v2/usersUsers endpoint
Custom Endpoint
add_action('rest_api_init', function() { register_rest_route('myplugin/v1', '/items', [ 'methods' => 'GET', 'callback' => fn($req) => new WP_REST_Response( get_posts(['post_type' => 'item', 'numberposts' => 20]) ), 'permission_callback' => '__return_true', ]); });
Fetch from JavaScript
const res = await fetch('/wp-json/wp/v2/posts?per_page=5'); const posts = await res.json(); posts.forEach(p => console.log(p.title.rendered));
Functions
Post Functions
get_posts($args)Retrieve array of posts
wp_insert_post($arr)Create or update a post
wp_delete_post($id)Trash or delete a post
get_post_meta($id, $key)Get custom field value
update_post_meta($id, $k, $v)Set custom field value
User & Auth
wp_get_current_user()Current logged-in user
is_user_logged_in()Check login status
current_user_can($cap)Check capability
wp_create_nonce($action)Generate security nonce
wp_verify_nonce($nonce, $a)Verify nonce
Utility Functions
esc_html($str)Escape for HTML context
esc_attr($str)Escape for attribute context
esc_url($url)Sanitize URL
wp_kses_post($html)Allow only safe post HTML
sanitize_text_field($s)Strip tags and extra whitespace
absint($val)Absolute integer
Enqueue
Enqueue Styles & Scripts
add_action('wp_enqueue_scripts', function() { wp_enqueue_style('theme-style', get_stylesheet_uri(), [], '1.0'); wp_enqueue_script('theme-js', get_theme_file_uri('/js/app.js'), ['jquery'], '1.0', true); });
Enqueue Functions
wp_enqueue_style($h, $src)Register + enqueue CSS
wp_enqueue_script($h, $src)Register + enqueue JS
wp_localize_script($h, $n, $d)Pass PHP data to JS
wp_dequeue_style($handle)Remove enqueued style
wp_dequeue_script($handle)Remove enqueued script
Pass Data to JavaScript
wp_enqueue_script('my-app', get_theme_file_uri('/js/app.js')); wp_localize_script('my-app', 'myData', [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('my_action'), ]); // JS: console.log(myData.ajaxUrl)
Common Patterns
Custom Page Template
AJAX Handler
add_action('wp_ajax_my_action', 'handle_my_action'); add_action('wp_ajax_nopriv_my_action', 'handle_my_action'); function handle_my_action() { check_ajax_referer('my_action', 'nonce'); wp_send_json_success(['msg' => 'OK']); }
Shortcode
add_shortcode('greeting', function($atts) { $a = shortcode_atts(['name' => 'World'], $atts); return '

Hello, ' . esc_html($a['name']) . '!

'; }); // Usage: [greeting name="Zhi"]