My personal bird Pokédex

Besides my eBird lists and my general blog posts, I’ve been wanting to create something like a wiki or Pokédex to create entries for birds I see. Somewhere I can record information and personal anecdotes about each species I like.

birddex page

Besides my eBird lists and my general blog posts, I’ve been wanting to create something like a wiki or Pokédex to create entries for birds I see. Somewhere I can record information and personal anecdotes about each species I like.

I thought about the wiki idea for a while, but the more I thought about it, the more it felt like overkill and an overcomplicated solution.

EDIT 12/27/22: I reflected more on the wiki idea and after much thought and experience I decided to take the plunge with a dedicated wiki. The more I built out pages on this site, while it was fun, it was a bit tedious. was launched late last year using the Wiki.js platform. I’m hosting it on my own server and it’s been super fun to organize all of the information into various sections. Check it out!

Using WordPress’ Custom Post Types

I’m savvy with adding custom WordPress functionality, so I decided to research how I could use it to create bird entries. From this research, I discovered the idea of custom post types. With this knowledge, I could create a BirdDex.

In essence, I could create a custom ‘Bird’ post type and then gain the ability to add bird entries that would live at

I proceeded to create a new Bird custom post type and began thinking of what I would put on these new entries. Photos, audio, and a nice, bold layout were a must. I also wanted the ability to include blog posts that mention that species.

Building a layout

I took advantage of WordPress’ newish block builder and GeneratePress blocks to construct a layout for an individual bird entry. I saved this group of blocks as a template so it can be reused on other entries to avoid rework.

birddex entry

What’s in each entry

Details of my observations

The tables detail when I first saw the bird and what type of media I captured.

This section was created using tables and WordPress Dashicons. I learned that custom code needs to be added to the page to enable non-logged-in users to see the Dashicons.

Notes & Observations

A flexible notes section for all my thoughts and words.

The Notes & Observations section I’m using as a place to add thoughts and experience with the species. It will accommodate as many notes as I need.

Captured media

A place where I can include my photos and recordings

This section was created with column blocks and a GeneratePress grid block to serve as the layout. From there, I upload the photos and embed my audio clips using HTML code from Macaulay Library.

A place for posts

A feed of posts that mention the species.

This section was created with a simple Query Loop block. I tagged the posts that mention the species and just included that tag in the block and set the limit to three posts.

Building the BirdDex page

birddex page
The main BirdDex page with search and the recent nine bird entries.

Next, I needed to create a page for the actual BirdDex that would display recent bird species and a search feature.

To accomplish this, I created a new regular page, added a search bar (with HTML shown below), and a Query Loop block.

The Query Loop block lets me display ‘Bird’-type posts and choose from a variety of layouts. I chose a basic grid layout with nine entries displayed and added pagination by clicking on the Post Template block, then added a Pagination block.

The code

I added this code to the functions.php file in my child theme to create the ‘Bird’ custom post type. This gives it a cute location with a book icon in the admin sidebar.

 * Register a custom post type called "bird".
 * @see get_post_type_labels() for label keys.
function wpdocs_codex_bird_init() {
    $labels = array(
        'name'                  => _x( 'Birds', 'Post type general name', 'textdomain' ),
        'singular_name'         => _x( 'Bird', 'Post type singular name', 'textdomain' ),
        'menu_name'             => _x( 'Birds', 'Admin Menu text', 'textdomain' ),
        'name_admin_bar'        => _x( 'Bird', 'Add New on Toolbar', 'textdomain' ),
        'add_new'               => __( 'Add New', 'textdomain' ),
        'add_new_item'          => __( 'Add New Bird', 'textdomain' ),
        'new_item'              => __( 'New Bird', 'textdomain' ),
        'edit_item'             => __( 'Edit Bird', 'textdomain' ),
        'view_item'             => __( 'View Bird', 'textdomain' ),
        'all_items'             => __( 'All Birds', 'textdomain' ),
        'search_items'          => __( 'Search Birds', 'textdomain' ),
        'parent_item_colon'     => __( 'Parent Birds:', 'textdomain' ),
        'not_found'             => __( 'No birds found.', 'textdomain' ),
        'not_found_in_trash'    => __( 'No birds found in Trash.', 'textdomain' ),
        'archives'              => _x( 'Bird archives', 'The post type archive label used in nav menus. Default “Post Archives”. Added in 4.4', 'textdomain' ),
        'insert_into_item'      => _x( 'Insert into dex post', 'Overrides the “Insert into post”/”Insert into page” phrase (used when inserting media into a post). Added in 4.4', 'textdomain' ),
        'uploaded_to_this_item' => _x( 'Uploaded to this dex post', 'Overrides the “Uploaded to this post”/”Uploaded to this page” phrase (used when viewing media attached to a post). Added in 4.4', 'textdomain' ),
        'filter_items_list'     => _x( 'Filter birds list', 'Screen reader text for the filter links heading on the post type listing screen. Default “Filter posts list”/”Filter pages list”. Added in 4.4', 'textdomain' ),
        'items_list_navigation' => _x( 'Birds list navigation', 'Screen reader text for the pagination heading on the post type listing screen. Default “Posts list navigation”/”Pages list navigation”. Added in 4.4', 'textdomain' ),
        'items_list'            => _x( 'Birds list', 'Screen reader text for the items list heading on the post type listing screen. Default “Posts list”/”Pages list”. Added in 4.4', 'textdomain' ),
    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'bird' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
	  'menu_icon'          => 'dashicons-book',
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
	  'show_in_rest'       => true,
    register_post_type( 'bird', $args );
add_action( 'init', 'wpdocs_codex_bird_init' );

I used the following code to render a search box that only searches the post type of ‘bird’.

<form role="search" method="get" class="searchbox" action="/bird/">
    <input style="width:100%" type="text" class="textbox strong" name="s" id="s" value="" placeholder="Search...">
    <input type="hidden" name="post_type" value="bird">            

In conclusion

It has been fun to go through the exercise of building out this personal database of birds. I look forward to adding more species and documenting my experiences.