Add a searchable book catalogue to WordPress: a plugin you can build today

· 4 min read

A lot of organisations have a physical collection of books they want to make visible on their website. An astronomical society, a reading group, a community centre, a school department. The need is always the same: a list of titles with author, year, and subject, and a way for visitors to search or filter it.

The plugins that exist for this job have overbuilt it. Library Management System, Book Review Library, Books Gallery: they ship with borrowing workflows, member accounts, loan periods, and overdue notices. An astronomical society listing forty books about telescopes does not need a fines system.

A plugin that only displays books is small. It needs a custom post type, two meta fields, a subject taxonomy, and a shortcode that renders a filterable table. That is around eighty lines of code and a single PHP file.

What one build gives you

  • Books custom post type with author and year meta fields and a subject taxonomy
  • A [book_catalogue] shortcode that renders a searchable, filterable table
  • Subject filter links generated automatically from the taxonomy terms in use
  • Alphabetical sort with keyword search by title and optional subject filtering

What it does not do

  • Loan tracking: no borrowing, returning, holds, due dates, or overdue notices
  • Member or patron accounts of any kind
  • ISBN lookup or automatic import of book metadata from an external database
  • Cover image fetching from a feed or ISBN API
  • Pagination: all books render on one page by default

Library Management System does these. This covers the part most sites use.

The prompt

Loads into the composer so you can edit it first. Nothing is built, and nothing is charged, until you send it.

Build a WordPress plugin called Book Catalogue. Plugin Name: Book Catalogue. Description: Displays a searchable list of books from a custom post type with subject filtering. Single PHP file. No dependencies beyond WordPress core. Register a custom post type called `book` with: label Books, singular_name Book, menu_name Library, public true, has_archive false, supports array containing only title, show_in_menu true, rewrite slug books, show_ui true. Register a flat taxonomy called `book_subject` attached to `book` with: label Subjects, singular_name Subject, hierarchical false, public true, show_admin_column true, show_ui true, rewrite slug book-subject. Add a meta box with id `book_meta` and title Book Details to the book post type on add and edit screens. The meta box contains two fields: Author (text input, name book_author) and Year Published (number input, name book_year, min 1000 max 2099). Output a nonce field using wp_nonce_field with action book_meta_nonce. On save_post: verify the nonce with check_admin_referer('book_meta_nonce'), return early if doing_autosave or if current_user_can('edit_post',$post_id) is false, save book_author with sanitize_text_field, save book_year with absint only if the value is between 1000 and 2099 inclusive otherwise save 0. Register a shortcode `book_catalogue`. The shortcode function should: 1. Read $_GET['book_search'] with sanitize_text_field and $_GET['book_subject'] with sanitize_key. 2. Build $args for WP_Query: post_type book, posts_per_page -1, orderby title, order ASC. If book_search is not empty add s to the args. If book_subject is not empty add a tax_query: taxonomy book_subject, field slug, terms book_subject value. 3. Render a search form: method GET, action empty string, one text input named book_search with the current search value set via esc_attr, a submit button labelled Search. Include a hidden input for book_subject if it is currently set so the subject filter persists through a keyword search. 4. Render subject filter links: call get_terms with taxonomy book_subject, hide_empty true. Output an All link pointing to the current page URL without book_subject. For each term output a link pointing to the current page URL with book_subject set to the term slug, using esc_html for the term name and esc_url for the URL. Use add_query_arg to build the URLs. Wrap the links in a paragraph. 5. Run the query. If no posts found output a paragraph saying No books found. Otherwise output an HTML table with a thead row containing columns Title, Author, Year, Subjects. For each post output a tr with: post_title escaped with esc_html, book_author meta escaped with esc_html, book_year meta output only if it is greater than 0 escaped with esc_html, and the subject terms as a comma-separated list of term names using get_the_terms($post_id,'book_subject') escaped with esc_html per term, or a hyphen if none. 6. Use ob_start and return ob_get_clean. No inline JS. No external CSS. No AJAX. No database tables. No block registration.

Build this pluginAbout 55 credits · the free plan includes enough for one

What the plugin does

A Books section appears in the WordPress admin menu. Each book is a post: the title goes in the title field, and a meta box below the editor holds Author and Year Published. Subjects are a flat taxonomy, the same way tags work on standard posts. You can add as many subject terms as you need from the edit screen.

On the front end, the [book_catalogue] shortcode renders a search form above a table of all books. Visitors can type a keyword to filter by title, click a subject link to filter by taxonomy term, or combine both. The table is sorted alphabetically by title. When no results match, a short message says so.

  • Books custom post type with title, author, year, and subject fields
  • [book_catalogue] shortcode for any page or widget area
  • Keyword search by book title
  • Subject filter links generated from the taxonomy terms currently in use
  • Both filters work together: keyword narrows within the selected subject

Adding and organising books

Adding a book works like adding any WordPress post. Fill in the title, open the meta box, type the author name and year, and assign one or more subjects from the taxonomy panel on the right. Save. The book appears in the catalogue immediately.

Subjects are created as you go. The first time you type a subject term and save a book, it exists. Every subsequent book can use it. The shortcode generates the filter links automatically from whichever terms are actually attached to books, so a subject disappears from the filter list as soon as its last book is removed.

There is no separate catalogue settings screen. The shortcode takes no required attributes. Drop [book_catalogue] onto a page and the entire collection appears.

What this plugin does not do

The plugin lists books. It does not manage a physical lending collection. There is no concept of a copy being available or checked out, no reservation queue, no member accounts, no due dates, and no overdue notices. If a visitor needs to know whether a book is on the shelf, this plugin cannot tell them.

It also does not fetch book data from an external source. Author, year, and subject are whatever you type in. If you want to import records from an ISBN database or pull cover images automatically, you need a plugin that talks to a third-party API. This one does not.

For a site running an actual lending library, where members borrow physical books and staff need to track who has what, a full library management system is the honest answer. The catalogue a full system produces looks similar; the machinery behind it is not.

Extending the plugin

Because you own the code, adding a field is a follow-up message. Ask Steem to add a Publisher field and it will add the meta box input, the sanitization, and the table column. Ask it to add pagination if the collection grows large: set posts_per_page to 20 and add page links below the table.

The shortcode can also be filtered by subject attribute: [book_catalogue subject="astronomy"] renders only books in the astronomy subject term. Useful if you want a separate page per subject without duplicating the shortcode logic.

A second small build that some collections will want: a book detail page that shows a larger entry with a longer description field. That is a second meta box and a single-book template. Ask for it separately once the catalogue is working.

Questions

How do I put the catalogue on a page?

Create or edit any WordPress page, add the shortcode [book_catalogue] in the body, and publish. The full catalogue appears at that URL. You can add the shortcode to more than one page if you want the catalogue in multiple places.

Can I filter by subject when placing the shortcode?

Yes. Use [book_catalogue subject="your-subject-slug"] to show only books in one subject term. The slug is the URL-friendly version of the term name, visible in Subjects > Edit in the admin.

Can I add more fields, like publisher or ISBN?

Yes. Ask Steem to add the field: name the input, describe where it should appear in the table, and the generated code will add the meta box input, sanitization on save, and the table column. Each field is a short addition to the existing file.

What if I have several hundred books?

By default the shortcode loads all books on one page. If the list becomes unwieldy, ask Steem to add pagination: set posts_per_page to a fixed number and add previous and next links below the table.

The prompt

Loads into the composer so you can edit it first. Nothing is built, and nothing is charged, until you send it.

Build a WordPress plugin called Book Catalogue. Plugin Name: Book Catalogue. Description: Displays a searchable list of books from a custom post type with subject filtering. Single PHP file. No dependencies beyond WordPress core. Register a custom post type called `book` with: label Books, singular_name Book, menu_name Library, public true, has_archive false, supports array containing only title, show_in_menu true, rewrite slug books, show_ui true. Register a flat taxonomy called `book_subject` attached to `book` with: label Subjects, singular_name Subject, hierarchical false, public true, show_admin_column true, show_ui true, rewrite slug book-subject. Add a meta box with id `book_meta` and title Book Details to the book post type on add and edit screens. The meta box contains two fields: Author (text input, name book_author) and Year Published (number input, name book_year, min 1000 max 2099). Output a nonce field using wp_nonce_field with action book_meta_nonce. On save_post: verify the nonce with check_admin_referer('book_meta_nonce'), return early if doing_autosave or if current_user_can('edit_post',$post_id) is false, save book_author with sanitize_text_field, save book_year with absint only if the value is between 1000 and 2099 inclusive otherwise save 0. Register a shortcode `book_catalogue`. The shortcode function should: 1. Read $_GET['book_search'] with sanitize_text_field and $_GET['book_subject'] with sanitize_key. 2. Build $args for WP_Query: post_type book, posts_per_page -1, orderby title, order ASC. If book_search is not empty add s to the args. If book_subject is not empty add a tax_query: taxonomy book_subject, field slug, terms book_subject value. 3. Render a search form: method GET, action empty string, one text input named book_search with the current search value set via esc_attr, a submit button labelled Search. Include a hidden input for book_subject if it is currently set so the subject filter persists through a keyword search. 4. Render subject filter links: call get_terms with taxonomy book_subject, hide_empty true. Output an All link pointing to the current page URL without book_subject. For each term output a link pointing to the current page URL with book_subject set to the term slug, using esc_html for the term name and esc_url for the URL. Use add_query_arg to build the URLs. Wrap the links in a paragraph. 5. Run the query. If no posts found output a paragraph saying No books found. Otherwise output an HTML table with a thead row containing columns Title, Author, Year, Subjects. For each post output a tr with: post_title escaped with esc_html, book_author meta escaped with esc_html, book_year meta output only if it is greater than 0 escaped with esc_html, and the subject terms as a comma-separated list of term names using get_the_terms($post_id,'book_subject') escaped with esc_html per term, or a hyphen if none. 6. Use ob_start and return ob_get_clean. No inline JS. No external CSS. No AJAX. No database tables. No block registration.

Build this pluginAbout 55 credits · the free plan includes enough for one

Read next

Other plugins you can build this way

Each loads into the composer, ready to edit.