<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vivian</title>
    <description>The latest articles on DEV Community by Vivian (@veycaptain).</description>
    <link>https://dev.to/veycaptain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3919785%2Fdc090347-0325-4e5e-a717-127349368f79.png</url>
      <title>DEV Community: Vivian</title>
      <link>https://dev.to/veycaptain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/veycaptain"/>
    <language>en</language>
    <item>
      <title>I Built 7 Interactive Calculators for a Niche Site Using Only PHP Shortcodes — No Plugins</title>
      <dc:creator>Vivian</dc:creator>
      <pubDate>Fri, 08 May 2026 10:08:51 +0000</pubDate>
      <link>https://dev.to/veycaptain/i-built-7-interactive-calculators-for-a-niche-site-using-only-php-shortcodes-no-plugins-1774</link>
      <guid>https://dev.to/veycaptain/i-built-7-interactive-calculators-for-a-niche-site-using-only-php-shortcodes-no-plugins-1774</guid>
      <description>&lt;p&gt;I run a small niche site called &lt;a href="https://pethuts.com" rel="noopener noreferrer"&gt;PetHuts&lt;/a&gt; that provides free tools for people building bioactive terrariums and vivariums. It has 7 interactive calculators, all built as WordPress shortcodes — no page builders, no calculator plugins, no React, no build step.&lt;/p&gt;

&lt;p&gt;Here's how and why I did it this way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Shortcodes Instead of a Plugin?
&lt;/h2&gt;

&lt;p&gt;Most WordPress calculator plugins are bloated. They load their own CSS frameworks, jQuery dependencies, and admin interfaces even on pages that don't use them. For a site where speed matters for SEO (mine went from 8.9s to 3.7s LCP after optimization), every unnecessary script hurts.&lt;/p&gt;

&lt;p&gt;A PHP shortcode is just a function that returns HTML. WordPress calls it when it encounters &lt;code&gt;[your_shortcode]&lt;/code&gt; in a page. The CSS and JS are inline, so nothing loads on pages that don't use the calculator. Zero overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Structure
&lt;/h2&gt;

&lt;p&gt;Each calculator follows the same pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;add_shortcode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pethuts_calc'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'pethuts_calc_render'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;pethuts_calc_render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$atts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shortcode_atts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'substrate'&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$atts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nb"&gt;ob_start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;/* scoped CSS here */&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"calculator-wrapper"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- inputs --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"calculate-btn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Calculate&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- results container --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// calculation logic&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calculate-btn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// math happens here&lt;/span&gt;
            &lt;span class="c1"&gt;// inject results into DOM&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ob_get_clean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One shortcode, one function, everything self-contained. The &lt;code&gt;$atts&lt;/code&gt; parameter lets me use the same shortcode for multiple calculator types: &lt;code&gt;[pethuts_calc type="substrate"]&lt;/code&gt;, &lt;code&gt;[pethuts_calc type="cleanup"]&lt;/code&gt;, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;The 7 calculators on &lt;a href="https://pethuts.com/calculators/" rel="noopener noreferrer"&gt;PetHuts&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ABG Mix Calculator&lt;/strong&gt; — enter tank dimensions, get exact amounts of each substrate ingredient based on the 2:1:1:1:2 ratio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LECA Drainage Layer Calculator&lt;/strong&gt; — how much clay balls for the drainage layer beneath the substrate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tank Size Calculator&lt;/strong&gt; — recommended enclosure size by species&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heat Bulb Wattage Calculator&lt;/strong&gt; — room temp + target temp + distance = recommended wattage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleanup Crew Calculator&lt;/strong&gt; — how many isopods and springtails based on tank size and humidity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe Plant Finder&lt;/strong&gt; — filter non-toxic plants by enclosure type, light, and size&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jumping Spider Care Calculator&lt;/strong&gt; — personalized care plan by species and age&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each one took 1-2 hours to build. The most complex part is usually the data, not the code — researching the correct formulas, species requirements, and plant safety lists takes longer than writing the JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Programmatic SEO Layer
&lt;/h2&gt;

&lt;p&gt;The interesting part: I used the same shortcode approach to generate 20+ landing pages from a data array. One shortcode, one PHP array of tank specifications, and each page auto-generates a full guide with pre-calculated substrate amounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$tanks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'18x18x24'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'18×18×24'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'common'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Standard Tall Terrarium'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'l'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'w'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'h'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'depth'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'species'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'crested geckos, dart frogs...'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// ...more data&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c1"&gt;// ...more tanks&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each entry becomes a page targeting a specific long-tail keyword like "how much substrate for 40 gallon tank." The math is calculated server-side from the dimensions in the array. One code change updates every page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;The site went from 5 pages to 35+ pages in a few weeks. Google Search Console shows impressions climbing week over week, with the programmatic pages picking up long-tail queries that no competitor targets with dedicated pages.&lt;/p&gt;

&lt;p&gt;No React. No build pipeline. No npm. Just PHP, vanilla JS, and a data array.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would I Do It Differently?
&lt;/h2&gt;

&lt;p&gt;For a site this small, shortcodes are perfect. If PetHuts grows to 20+ calculators with shared state between them, I'd probably move to a lightweight frontend framework. But for now, the simplicity is the feature — any WordPress user can paste a shortcode and get a working calculator. No technical setup required.&lt;/p&gt;

&lt;p&gt;If you're building niche tools for a content site, don't overthink the stack. The value is in the tool itself and the content around it, not the framework it's built with.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Check out the live calculators at &lt;a href="https://pethuts.com/calculators/" rel="noopener noreferrer"&gt;pethuts.com/calculators&lt;/a&gt;. All free, no signup.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>php</category>
      <category>seo</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
