Installation

1. Clone & Install

git clone <repository-url>
cd homeplate
npm install

2. Start the Server

node server.js

3. Run the Installer

Navigate to http://localhost:3000 and follow the wizard to configure your database, choose a template, and create your admin account.

4. Access Your Site

  • Admin Panel: /admin
  • Public Site: /

Requirements

  • Node.js 14.0.0+
  • MySQL 5.7+ or MariaDB 10.3+
  • npm or yarn

Custom Port

To use a port other than 3000, create a .env file before starting:

echo "PORT=8080" > .env

Template Basics

Templates live in the templates/ directory. Each template is a folder containing HTML files. Homeplate uses a drop-in system — any valid HTML file can become a CMS template.

How It Works

Place special shortcodes in your HTML. The CMS replaces them with content from the database when the page loads. Everything renders server-side, so content appears immediately with no JavaScript required.

<!DOCTYPE html>
<html>
<head>
  <title>{{text:site_name}}</title>
</head>
<body>
  {{include:header.html}}

  <main>
    <h1>{{text:site_name}}</h1>
    {{block:hero_content}}
    {{data:view:featured_products}}
  </main>

  {{include:footer.html}}
</body>
</html>
Full Freedom Templates can use any CSS framework, CDN, font, or JavaScript library. There are no restrictions on what you can load.

Content Blocks

Content blocks are editable regions that editors manage through the admin panel at Content in the sidebar.

How to Use Them

Add a shortcode to your template. The admin panel detects it automatically — no registration needed.

Text Blocks

Returns plain text with all HTML stripped. Use for headings, labels, and short strings.

Syntax

<h1>{{text:site_name}}</h1>
<p>{{text:hero_subtitle}}</p>
<title>{{text:page_title}}</title>

Example

If an editor sets site_name to “My Store”, the output is:

<h1>My Store</h1>

Rich Text Blocks

Returns full HTML content with formatting. Use for body copy, feature sections, and any content that needs rich formatting.

Syntax

<div class="content">
  {{block:about_content}}
</div>

<section>
  {{block:feature_section}}
</section>

Example

If an editor writes rich text with bold, links, and paragraphs, all formatting is preserved in the output.

Includes

Include shared HTML files. Great for headers, footers, and navigation that repeat across pages.

Syntax

<body>
  {{include:header.html}}

  <main>
    <!-- page content -->
  </main>

  {{include:footer.html}}
</body>

The included file is injected inline, so it shares the same scope and styles as the parent template.

Data Blocks & Views

Data blocks are collections of structured content — products, blog posts, team members, testimonials, etc. You define a schema, editors add items, and you display them with views.

Step 1: Create a Data Block

In the admin panel under Data, create a new block and define its fields (title, description, price, images, etc.).

Step 2: Add Items

Editors add records through the admin panel — products, posts, or whatever the collection holds.

Step 3: Create a View

A view defines how items render. You write an HTML template for a single item, and the CMS loops through all matching items.

Data Views

Use the data:view shortcode to render a view in your template.

In Your Template

<section>
  <h2>Featured Products</h2>
  <div class="product-grid">
    {{data:view:featured_products}}
  </div>
</section>

View Template (written in the admin panel)

<div class="product-item">
  <a href="/product/{{data:id}}">
    <div class="product-card">
      {{data:attr:images}}
      <h3>{{data:attr:title}}</h3>
      <p class="price">${{data:attr:price}}</p>
      <p>{{data:attr:description}}</p>
      {{if_sellable}}
        <div class="actions">
          {{shopping:product:quantity}}
          {{shopping:product:add_to_cart}}
        </div>
      {{endif}}
    </div>
  </a>
</div>

Placeholders Available in Views

PlaceholderWhat It Outputs
{{data:id}}The record's ID
{{data:attr:title}}The title field
{{data:attr:fieldname}}Any field from your schema
{{data:text:fieldname}}Field value with HTML stripped

Filtering Views

Static Filters (Admin Panel)

When editing a view, set a Filter Config to control which items appear:

{
  "filters": [
    { "attribute": "category", "operator": "=", "value": "Electronics" },
    { "attribute": "price", "operator": "<=", "value": 100 }
  ]
}

Dynamic Filters (in your template)

Pass filters via query string in the shortcode:

{{data:view:products?category=Electronics}}

Operators

OperatorMeaning
=Equals
!=Not equals
> >=Greater than / greater than or equal
< <=Less than / less than or equal
LIKEContains text (case-insensitive)
INValue is in an array
NOT INValue is not in an array

Template Files

config.json

{
  "name": "template-name",
  "title": "Template Name",
  "description": "A description of your template",
  "version": "1.0.0",
  "author": "Your Name"
}

Page Files

FilePurpose
index.htmlHomepage (required)
store.htmlProduct listing
product.htmlSingle product page
cart.htmlShopping cart
checkout.htmlCheckout
order-confirmation.htmlOrder confirmation
blog.htmlBlog listing
blog_post.htmlBlog post
privacy.htmlPrivacy policy
terms.htmlTerms of service

Setting Up a Store

1. Create a Product Collection

In Data, create a new data block with fields like:

title       text        required
price       number      required
description textarea
images      gallery
category    text
sku         text
featured    boolean
sale_price  number

2. Enable Sellable

Check "Is Sellable" on the data block and set the cart config:

{
  "price_attribute": "price",
  "discounted_price_attribute": "sale_price",
  "title_attribute": "title",
  "description_attribute": "description",
  "image_attribute": "images",
  "category_attribute": "category",
  "sku_attribute": "sku"
}

3. Create Views

Create views for different displays: products_list, products_detail, featured_products, etc.

4. Store Routes

RouteTemplate
/storestore.html
/product/:idproduct.html
/cartcart.html
/checkoutcheckout.html
/order-confirmation/:orderNumberorder-confirmation.html

Shopping Tags

Product Tags

TagOutput
{{shopping:product:add_to_cart}}Add to cart button
{{shopping:product:quantity}}Quantity selector with +/- buttons
{{shopping:product:price}}Formatted price (with discount if applicable)
{{shopping:products:list}}All products from every sellable block
{{shopping:products:featured}}Products with featured = true
{{shopping:products:sale}}Products with on_sale = true

Cart Tags

TagOutput
{{shopping:cart:items}}Cart items list
{{shopping:cart:summary}}Subtotal, tax, total
{{shopping:cart:count}}Number of items in cart
{{shopping:cart:view}}Link to cart page

Checkout

TagOutput
{{shopping:checkout:form}}Full checkout form

Conditionals

{{if_sellable}}
  <p>Price: {{shopping:product:price}}</p>
  {{shopping:product:add_to_cart}}
{{endif}}

{{if_not_sellable}}
  <p>Contact for pricing</p>
{{endif_not_sellable}}

Template Variables

Global

VariableValue
{{text:site_name}}Site name from settings
{{text:site_description}}Site description
{{text:site_url}}Site URL

Attribute Types

When you define a schema for a data block, each field has a type. Here is how each type renders when used with {{data:attr:fieldname}}:

TypeRendering
textPlain text string
textareaMulti-line text
numberNumeric value
booleanYes / No
imageAn <img> tag
galleryFirst image as <img>; slideshow starts automatically for multiple images
selectSelected option value
urlURL string
dateFormatted date

Cart CSS Classes

Use these classes in your templates for cart functionality. The JS handler binds to them automatically.

Buttons

.cart-add-btn       .cart-remove-btn
.cart-clear-btn     .cart-checkout-btn
.cart-continue-btn

Display

.cart-container     .cart-item
.cart-item-image    .cart-item-title
.cart-item-price    .cart-item-details
.cart-summary       .cart-total
.cart-empty

Quantity

.cart-quantity-input
.cart-quantity-selector
.cart-quantity-decrease
.cart-quantity-increase

Data Attributes

data-block-id      <!-- collection ID -->
data-record-id     <!-- item ID -->
data-cart-item-id  <!-- cart item ID -->