<?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: Raddito</title>
    <description>The latest articles on DEV Community by Raddito (@radditollc).</description>
    <link>https://dev.to/radditollc</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4234828%2F89fe5061-6590-41b9-9246-428da781edba.png</url>
      <title>DEV Community: Raddito</title>
      <link>https://dev.to/radditollc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/radditollc"/>
    <language>en</language>
    <item>
      <title>How to Customize a Tailwind CSS Website Template for a Client Project</title>
      <dc:creator>Raddito</dc:creator>
      <pubDate>Mon, 09 Nov 2026 11:12:45 +0000</pubDate>
      <link>https://dev.to/radditollc/how-to-customize-a-tailwind-css-website-template-for-a-client-project-dj4</link>
      <guid>https://dev.to/radditollc/how-to-customize-a-tailwind-css-website-template-for-a-client-project-dj4</guid>
      <description>&lt;p&gt;Building a website for a client doesn't always mean starting from a blank HTML file.&lt;/p&gt;

&lt;p&gt;Sometimes, the smarter approach is to start with a well-structured template and spend your time on what makes the client's website unique: branding, content, usability, and performance.&lt;/p&gt;

&lt;p&gt;But downloading a template is the easy part.&lt;/p&gt;

&lt;p&gt;The real challenge is turning that template into a finished website that doesn't &lt;em&gt;look&lt;/em&gt; like a template.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll walk through how to customize a Tailwind CSS website template for a client project, from choosing a starter to deploying the finished site.&lt;/p&gt;

&lt;p&gt;We'll use &lt;strong&gt;Studio&lt;/strong&gt;, a free HTML, Tailwind CSS, and Vite website template from Raddito, as our example.&lt;/p&gt;

&lt;p&gt;By the end, you'll know how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose a suitable starter template.&lt;/li&gt;
&lt;li&gt;Customize colors and typography.&lt;/li&gt;
&lt;li&gt;Replace demo content, images, and links.&lt;/li&gt;
&lt;li&gt;Configure and build a project with Vite.&lt;/li&gt;
&lt;li&gt;Test responsive layouts.&lt;/li&gt;
&lt;li&gt;Deploy a production-ready static website.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Choose the right starter template
&lt;/h2&gt;

&lt;p&gt;Before touching any code, choose a template that matches the project's requirements.&lt;/p&gt;

&lt;p&gt;A good starter template should already have the major sections your client needs.&lt;/p&gt;

&lt;p&gt;For example, if you're creating a website for a digital agency, look for a design with a strong hero, services, project portfolio, and clear calls to action.&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll use &lt;strong&gt;Studio by Raddito&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hfdrbasbjxyhyq4olql.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hfdrbasbjxyhyq4olql.webp" alt="Official Studio template preview showing the dark navy hero, violet headline, team photograph, and Selected Projects section" width="650" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Official Studio preview: the original hero and selected-projects layouts.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template details:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Studio&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Technology&lt;/td&gt;
&lt;td&gt;HTML, Tailwind CSS 3, Vite 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design&lt;/td&gt;
&lt;td&gt;Dark, modern agency landing page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sections&lt;/td&gt;
&lt;td&gt;Hero, statistics, services, portfolio, articles, CTA, footer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsive&lt;/td&gt;
&lt;td&gt;Desktop, tablet, and mobile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can explore the &lt;a href="https://studio-farm.netlify.app/" rel="noopener noreferrer"&gt;live Studio demo&lt;/a&gt; to see how the original layout behaves.&lt;/p&gt;

&lt;p&gt;For our example, imagine we're customizing Studio for a fictional creative business called &lt;strong&gt;Northstar Studio&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Our client wants a modern portfolio website with a different color palette, updated typography, real project information, and a clear contact action.&lt;/p&gt;

&lt;p&gt;We'll keep the useful layout and replace the branding.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Before using any template in a paid client project, check its license and any restrictions on assets, attribution, or redistribution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Download the template and inspect the files
&lt;/h2&gt;

&lt;p&gt;After downloading and extracting the template, open the project directory in your code editor.&lt;/p&gt;

&lt;p&gt;Studio includes the main HTML page, Tailwind configuration, custom CSS, assets, and the Vite project setup.&lt;/p&gt;

&lt;p&gt;The important files to look for are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;studio/
├── index.html
├── tailwind.config.js
├── package.json
├── style.css
├── assets/
└── README
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a simplified overview; check the downloaded version for its exact filenames and asset locations.&lt;/p&gt;

&lt;p&gt;Here's what matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;index.html&lt;/code&gt; contains the landing-page structure and content.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tailwind.config.js&lt;/code&gt; defines Tailwind customization.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;style.css&lt;/code&gt; contains the template's additional styles.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;package.json&lt;/code&gt; contains the project's dependencies and scripts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;assets/&lt;/code&gt; contains images, icons, and other visual resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before making any changes, save a copy or initialize Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial Studio template"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you an easy way to compare your changes with the original starter.&lt;/p&gt;

&lt;p&gt;Next, install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite will print a local development URL in your terminal, commonly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5173/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open that URL in your browser.&lt;/p&gt;

&lt;p&gt;Make sure the original template works before changing anything. Fixing setup issues now is easier than debugging them after a full redesign.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Customize the brand colors
&lt;/h2&gt;

&lt;p&gt;One of Tailwind CSS's biggest advantages is that you can build a consistent design system using reusable utility classes.&lt;/p&gt;

&lt;p&gt;Studio's original color palette includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Midnight navy: &lt;code&gt;#0B0A1F&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Violet: &lt;code&gt;#4F3DFE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;White: &lt;code&gt;#FFFFFF&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's say Northstar Studio uses a dark slate background with teal accents.&lt;/p&gt;

&lt;p&gt;Our new colors will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Example client brand colors */&lt;/span&gt;

&lt;span class="nt"&gt;--brand-background&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#0&lt;/span&gt;&lt;span class="nt"&gt;F172A&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;--brand-primary&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;#14&lt;/span&gt;&lt;span class="nt"&gt;B8A6&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;--brand-text&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;#F8FAFC&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update the Tailwind configuration
&lt;/h3&gt;

&lt;p&gt;Because this version of Studio uses Tailwind CSS 3, we can define custom colors in &lt;code&gt;tailwind.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('tailwindcss').Config} */&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{html,js}&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="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brand-bg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#0F172A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brand-primary&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#14B8A6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brand-text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#F8FAFC&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="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&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;This is an example configuration, not a verbatim copy of Studio's original file. Merge these color entries into your existing configuration rather than deleting template-specific settings.&lt;/p&gt;

&lt;p&gt;Now you can use the new colors directly in HTML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-brand-bg text-brand-text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-4xl font-bold"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Design that moves your business forward.
  &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#contact"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inline-block rounded-lg
           bg-brand-primary px-6 py-3
           font-semibold text-slate-950"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Start a Project
  &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice these classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bg-brand-bg&lt;/code&gt; applies the custom background.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;text-brand-text&lt;/code&gt; applies the primary text color.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bg-brand-primary&lt;/code&gt; applies the new accent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll also need to replace existing color utilities throughout the template, including buttons, navigation links, icons, and hover states.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Updating the config doesn't automatically replace every hardcoded color in the HTML or &lt;code&gt;style.css&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Search for the original violet and navy values, and review any gradients or decorative elements that use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Change the typography
&lt;/h2&gt;

&lt;p&gt;Typography can completely change how a website feels.&lt;/p&gt;

&lt;p&gt;Studio originally uses Clash Display for its expressive headlines and Roboto for body text.&lt;/p&gt;

&lt;p&gt;For our fictional Northstar Studio project, we'll use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manrope&lt;/strong&gt; for headings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inter&lt;/strong&gt; for paragraphs, navigation, and buttons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Load the fonts
&lt;/h3&gt;

&lt;p&gt;In &lt;code&gt;index.html&lt;/code&gt;, add the following to the document's &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.gstatic.com"&lt;/span&gt;
  &lt;span class="na"&gt;crossorigin&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&amp;amp;family=Manrope:wght@600;700;800&amp;amp;display=swap"&lt;/span&gt;
  &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For privacy-sensitive projects, consider self-hosting the appropriate font files instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure Tailwind font families
&lt;/h3&gt;

&lt;p&gt;Add the font families to the existing &lt;code&gt;theme.extend&lt;/code&gt; configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fontFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Manrope&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sans-serif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Inter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sans-serif&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then apply them to your content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-display text-4xl font-bold
         leading-tight md:text-6xl"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Websites built for ambitious brands.
&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-6 max-w-xl font-body
         text-base leading-7
         text-slate-300 md:text-lg"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  We create clear, responsive digital
  experiences that help businesses grow.
&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've also added responsive text sizes.&lt;/p&gt;

&lt;p&gt;The heading starts at &lt;code&gt;text-4xl&lt;/code&gt; and increases to &lt;code&gt;text-6xl&lt;/code&gt; on medium-sized screens and above.&lt;/p&gt;

&lt;p&gt;This gives the page a stronger hierarchy without making the mobile layout overwhelming.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Replace the placeholder content
&lt;/h2&gt;

&lt;p&gt;This is the step that often takes more attention than expected.&lt;/p&gt;

&lt;p&gt;A template can look polished while still containing irrelevant content, sample projects, outdated dates, or links that lead nowhere.&lt;/p&gt;

&lt;p&gt;For Studio, check the hero, animated statistics, services, selected projects, article cards, contact links, and footer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customize the hero
&lt;/h3&gt;

&lt;p&gt;Studio's original hero says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Design-driven development of your web product&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For Northstar Studio, we might replace that with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Websites built for ambitious brands.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's an example of a customized hero content block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-brand-bg px-6 py-16
         text-brand-text md:py-24"&lt;/span&gt;
&lt;span class="nt"&gt;&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;"mx-auto max-w-6xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-body text-sm font-semibold
             uppercase tracking-widest
             text-brand-primary"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Northstar Studio
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-5 max-w-3xl font-display
             text-4xl font-bold leading-tight
             md:text-6xl lg:text-7xl"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Websites built for
      &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-brand-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ambitious brands.
      &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-6 max-w-xl font-body
             text-base leading-7
             text-slate-300 md:text-lg"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      We design and develop thoughtful
      digital experiences for growing
      businesses.
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#contact"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-8 inline-block rounded-lg
             bg-brand-primary px-6 py-3
             font-semibold text-slate-950
             transition hover:opacity-90"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Discuss Your Project
    &lt;span class="nt"&gt;&amp;lt;/a&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;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can adapt this markup within Studio's existing hero rather than replacing the entire section and losing its wave effects or other design details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Replace the images
&lt;/h3&gt;

&lt;p&gt;Don't leave demo images in your client's final website.&lt;/p&gt;

&lt;p&gt;Use approved photos, portfolio screenshots, and brand assets.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
  &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/northstar-project.webp"&lt;/span&gt;
  &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Northstar Studio branding project displayed on a desktop screen"&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-auto w-full rounded-2xl object-cover"&lt;/span&gt;
  &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the path to match the actual asset directory.&lt;/p&gt;

&lt;p&gt;Use descriptive filenames, relevant alternative text, and appropriately compressed images.&lt;/p&gt;

&lt;p&gt;Keep the hero image eager-loaded if it's essential to the initial viewport; lazy loading is better suited to images further down the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update portfolio cards
&lt;/h3&gt;

&lt;p&gt;Studio features a Selected Projects section, making it useful for agency and freelancer websites.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hfdrbasbjxyhyq4olql.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9hfdrbasbjxyhyq4olql.webp" alt="Studio's official design preview includes a Selected Projects showcase with large imagery, a project title, and a category label" width="650" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Studio's original project-showcase design. Replace the example imagery and captions with the client's approved work.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For a client site, replace the demonstration projects with real examples.&lt;/p&gt;

&lt;p&gt;A project card could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;article&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"overflow-hidden rounded-2xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt;
    &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"./assets/client-project.webp"&lt;/span&gt;
    &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Preview of a completed client website"&lt;/span&gt;
    &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-auto w-full object-cover"&lt;/span&gt;
    &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt;
  &lt;span class="nt"&gt;/&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;"mt-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-sm text-brand-primary"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Website Design
    &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;h3&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2 font-display text-2xl font-bold"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Client Project Name
    &lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/projects/client-project.html"&lt;/span&gt;
      &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-3 inline-block underline
             underline-offset-4"&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      View Case Study
    &lt;span class="nt"&gt;&amp;lt;/a&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;/article&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only use the case-study URL if that page exists. Otherwise, replace it with a working project link or remove the action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client-project tip:&lt;/strong&gt; Never publish placeholder testimonials, fabricated performance statistics, or portfolio work that the client doesn't have permission to display.&lt;/p&gt;

&lt;p&gt;If Studio's animated statistics are retained, update their numeric targets and labels too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make contact buttons functional
&lt;/h3&gt;

&lt;p&gt;Studio's contact buttons are links, not a working contact-form backend.&lt;/p&gt;

&lt;p&gt;For a simple site, a mail link can be enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt;
  &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"mailto:hello@your-client-domain.com"&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"inline-flex items-center rounded-lg
         bg-brand-primary px-6 py-3
         font-semibold text-slate-950"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Email Us
&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace that example address with the client's real address.&lt;/p&gt;

&lt;p&gt;If you need a contact form, connect it to a tested form endpoint or backend. An HTML form without submission handling doesn't automatically send messages.&lt;/p&gt;

&lt;p&gt;Also update:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The page title and meta description.&lt;/li&gt;
&lt;li&gt;Logo and favicon.&lt;/li&gt;
&lt;li&gt;Social media URLs.&lt;/li&gt;
&lt;li&gt;Navigation anchors.&lt;/li&gt;
&lt;li&gt;Footer copyright and attribution.&lt;/li&gt;
&lt;li&gt;Video links and embedded media.&lt;/li&gt;
&lt;li&gt;Article links and publication dates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Configure Vite for development and deployment
&lt;/h2&gt;

&lt;p&gt;Studio already uses Vite, so there's no need to create a new Vite project.&lt;/p&gt;

&lt;p&gt;Check the scripts in &lt;code&gt;package.json&lt;/code&gt;. A typical Vite setup includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"preview"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vite preview"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Preserve any additional scripts or dependencies that come with your downloaded template.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development mode
&lt;/h3&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite starts a local server and updates the page as you edit supported project files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production build
&lt;/h3&gt;

&lt;p&gt;When the site is ready, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite normally creates a &lt;code&gt;dist/&lt;/code&gt; directory containing the production-ready files.&lt;/p&gt;

&lt;p&gt;To test that build locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run preview
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a preview server, not the server you should use for production hosting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do you need to change vite.config.js?
&lt;/h3&gt;

&lt;p&gt;For a website deployed at the root of a domain, Vite's default &lt;code&gt;base&lt;/code&gt; setting is usually sufficient.&lt;/p&gt;

&lt;p&gt;If you want an explicit config, you could use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dist&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a project hosted at a subpath such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://example.com/client-site/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;you would instead set:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/client-site/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The base path matters because it affects how built assets are referenced.&lt;/p&gt;

&lt;p&gt;Don't change this setting unnecessarily, and test any hardcoded asset URLs when deploying under a subdirectory.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Test the website on different screen sizes
&lt;/h2&gt;

&lt;p&gt;Tailwind CSS makes responsive design easier, but responsive utility classes don't guarantee a flawless layout.&lt;/p&gt;

&lt;p&gt;After updating the content, test the website at different viewport widths.&lt;/p&gt;

&lt;p&gt;A quick starting point:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Example viewport width&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Small mobile&lt;/td&gt;
&lt;td&gt;375px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tablet&lt;/td&gt;
&lt;td&gt;768px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop&lt;/td&gt;
&lt;td&gt;1280px&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large desktop&lt;/td&gt;
&lt;td&gt;1440px&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Open Chrome DevTools, enable Device Toolbar, and resize the viewport.&lt;/p&gt;

&lt;p&gt;Pay attention to navigation, large headlines, portfolio images, button widths, and content spacing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make your layouts responsive
&lt;/h3&gt;

&lt;p&gt;Suppose you have a two-column services section.&lt;/p&gt;

&lt;p&gt;Instead of forcing two columns on every screen:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&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;"grid grid-cols-2 gap-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a responsive grid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&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;"grid grid-cols-1
         gap-6 md:grid-cols-2
         lg:gap-8"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the layout uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One column on small screens.&lt;/li&gt;
&lt;li&gt;Two columns from the &lt;code&gt;md&lt;/code&gt; breakpoint onward.&lt;/li&gt;
&lt;li&gt;More spacing on large screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similarly, responsive headings can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt;
  &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"font-display text-3xl
         font-bold leading-tight
         sm:text-4xl lg:text-5xl"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  Our Selected Projects
&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids oversized headings on small devices.&lt;/p&gt;

&lt;h3&gt;
  
  
  A simple overflow check
&lt;/h3&gt;

&lt;p&gt;While testing, this JavaScript can help detect horizontal overflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overflowing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollWidth&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Horizontal overflow:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;overflowing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it in the browser console on the page you're testing.&lt;/p&gt;

&lt;p&gt;If it returns &lt;code&gt;true&lt;/code&gt;, inspect the layout for oversized fixed-width elements, images, long text, or unwanted margins.&lt;/p&gt;

&lt;p&gt;Also test keyboard navigation, visible focus states, link destinations, and mobile menus.&lt;/p&gt;

&lt;p&gt;A mobile navigation control must be operable, not simply visible.&lt;/p&gt;

&lt;p&gt;For a more realistic review, open the &lt;a href="https://studio-farm.netlify.app/" rel="noopener noreferrer"&gt;Studio live preview&lt;/a&gt; in your browser alongside the customized local site. Compare how the hero, portfolio, and footer behave at narrow widths.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Check performance and accessibility
&lt;/h2&gt;

&lt;p&gt;Before deploying, do a final quality check.&lt;/p&gt;

&lt;p&gt;For performance, pay attention to large images, unnecessary scripts, font loading, and layout shifts.&lt;/p&gt;

&lt;p&gt;Studio also uses external animation and smooth-scrolling libraries. Keep the effects that genuinely improve the experience, but test whether they remain usable on mobile and for visitors who prefer reduced motion.&lt;/p&gt;

&lt;p&gt;For accessibility, check that headings follow a logical order, interactive elements are keyboard-accessible, and text has enough contrast against its background.&lt;/p&gt;

&lt;p&gt;You can also use Lighthouse in Chrome DevTools to inspect performance, accessibility, and other quality signals.&lt;/p&gt;

&lt;p&gt;For example, a simple SEO update in &lt;code&gt;index.html&lt;/code&gt; might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;
  Northstar Studio | Website Design &lt;span class="err"&gt;&amp;amp;&lt;/span&gt; Development
&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt;
  &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;
  &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Northstar Studio creates responsive websites and thoughtful digital experiences for growing brands."&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember that Lighthouse is an audit tool, not a guarantee of real-world performance. Test the deployed site as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Deploy the finished website
&lt;/h2&gt;

&lt;p&gt;Once you've checked the content, layout, and functionality, it's time to publish.&lt;/p&gt;

&lt;p&gt;Because Studio is a static HTML project, you can deploy the production build to a static hosting service.&lt;/p&gt;

&lt;p&gt;We'll use Netlify as an example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A: Manual deployment
&lt;/h3&gt;

&lt;p&gt;First, build the site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to Netlify.&lt;/li&gt;
&lt;li&gt;Create a new site using the manual deployment option.&lt;/li&gt;
&lt;li&gt;Upload the generated &lt;code&gt;dist/&lt;/code&gt; directory.&lt;/li&gt;
&lt;li&gt;Open the deployment URL and test the site.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Make sure you upload the built website, not just the unprocessed source files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B: Deploy from Git
&lt;/h3&gt;

&lt;p&gt;For a client website that will receive updates, connecting a Git repository is often more convenient.&lt;/p&gt;

&lt;p&gt;Push your project to your Git provider, then configure your hosting platform with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Build command:
npm run build

Publish directory:
dist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The hosting service can rebuild your website when you push new changes to the connected branch.&lt;/p&gt;

&lt;p&gt;After deployment, configure the client's custom domain and HTTPS.&lt;/p&gt;

&lt;p&gt;Finally, test the public URL.&lt;/p&gt;

&lt;p&gt;Check that CSS, images, navigation, videos, forms or email links, and any additional pages still work.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Final pre-launch checklist
&lt;/h2&gt;

&lt;p&gt;Before handing the website to the client, confirm the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Brand colors and typography match the approved design.&lt;/li&gt;
&lt;li&gt;[ ] Demo content, images, and sample projects are replaced.&lt;/li&gt;
&lt;li&gt;[ ] All buttons and navigation links work.&lt;/li&gt;
&lt;li&gt;[ ] Project information and statistics are accurate.&lt;/li&gt;
&lt;li&gt;[ ] No placeholder testimonials remain.&lt;/li&gt;
&lt;li&gt;[ ] The website works on mobile, tablet, and desktop.&lt;/li&gt;
&lt;li&gt;[ ] Images have appropriate alternative text.&lt;/li&gt;
&lt;li&gt;[ ] Keyboard navigation and contrast are checked.&lt;/li&gt;
&lt;li&gt;[ ] Page titles, meta descriptions, and favicon are updated.&lt;/li&gt;
&lt;li&gt;[ ] The production build completes successfully.&lt;/li&gt;
&lt;li&gt;[ ] The deployed website has been tested.&lt;/li&gt;
&lt;li&gt;[ ] Licensing, credits, and client handover requirements are satisfied.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A final client review is also valuable before the site goes live.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Customizing a Tailwind CSS template isn't just about changing a few colors and replacing the logo.&lt;/p&gt;

&lt;p&gt;The goal is to turn a reusable layout into a website that feels purposeful, represents the client's business, and works reliably across devices.&lt;/p&gt;

&lt;p&gt;A well-chosen starter can save development time. Tailwind makes visual changes manageable, while Vite provides a straightforward development and build workflow.&lt;/p&gt;

&lt;p&gt;The important part is putting that time back into the things that matter: content, accessibility, usability, and attention to detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have you customized a Tailwind CSS template for a client before?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What took the most time: branding, responsive layouts, content, or deployment?&lt;/p&gt;

&lt;p&gt;Share your experience in the comments!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tutorial by Raddito, a web design and development team creating website templates and client-focused web experiences.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example template: &lt;a href="https://raddito.net/shop/business-services/studio-digital-marketing-html-template-with-tailwind-css-vite/" rel="noopener noreferrer"&gt;Studio — Free HTML, Tailwind CSS &amp;amp; Vite Template&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Further reading: &lt;a href="https://tailwindcss.com/docs" rel="noopener noreferrer"&gt;Tailwind CSS documentation&lt;/a&gt; · &lt;a href="https://vite.dev/guide/static-deploy" rel="noopener noreferrer"&gt;Vite deployment guide&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>vite</category>
    </item>
    <item>
      <title>Build Your First WordPress Plugin: Add Reading Time Without Dependencies</title>
      <dc:creator>Raddito</dc:creator>
      <pubDate>Mon, 09 Nov 2026 10:50:31 +0000</pubDate>
      <link>https://dev.to/radditollc/build-your-first-wordpress-plugin-add-reading-time-without-dependencies-2pjo</link>
      <guid>https://dev.to/radditollc/build-your-first-wordpress-plugin-add-reading-time-without-dependencies-2pjo</guid>
      <description>&lt;p&gt;Ever wanted to add a small feature to a WordPress website without installing another plugin?&lt;/p&gt;

&lt;p&gt;Maybe it's a reading-time indicator, a custom notice, or something specific to your client's project.&lt;/p&gt;

&lt;p&gt;The good news? You don't need a complicated framework to get started.&lt;/p&gt;

&lt;p&gt;WordPress has a powerful system of hooks that lets you extend its functionality with just a few lines of PHP.&lt;/p&gt;

&lt;p&gt;In this tutorial, we'll build a tiny plugin that automatically displays an estimated reading time above blog posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you'll learn:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How WordPress plugins work&lt;/li&gt;
&lt;li&gt;How to create a plugin from scratch&lt;/li&gt;
&lt;li&gt;How to use the &lt;code&gt;the_content&lt;/code&gt; filter&lt;/li&gt;
&lt;li&gt;How to calculate reading time with PHP&lt;/li&gt;
&lt;li&gt;How to safely display custom content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the best part? We won't need any third-party dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, a quick hello! 👋
&lt;/h2&gt;

&lt;p&gt;We're &lt;strong&gt;Raddito&lt;/strong&gt;, a web design and development team specializing in WordPress, WooCommerce, and modern website-building workflows.&lt;/p&gt;

&lt;p&gt;This is our first post on DEV Community!&lt;/p&gt;

&lt;p&gt;We're here to share practical development tutorials, lessons from building websites, and solutions to common WordPress challenges.&lt;/p&gt;

&lt;p&gt;Let's start by building something useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Understand how WordPress plugins work
&lt;/h2&gt;

&lt;p&gt;A WordPress plugin is essentially PHP code that extends the behavior of a WordPress website.&lt;/p&gt;

&lt;p&gt;Instead of modifying WordPress core files, you connect your code to WordPress using hooks.&lt;/p&gt;

&lt;p&gt;There are two main types:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Actions:&lt;/strong&gt; Run your code when something happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Filters:&lt;/strong&gt; Allow you to modify data before WordPress uses or displays it.&lt;/p&gt;

&lt;p&gt;For our reading-time feature, we'll use a filter called &lt;code&gt;the_content&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This filter gives us access to post content before WordPress displays it.&lt;/p&gt;

&lt;p&gt;That means we can add our reading-time indicator without editing individual blog posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create your plugin folder
&lt;/h2&gt;

&lt;p&gt;Open your WordPress installation and navigate to:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;wp-content/plugins/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create a new folder named:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;raddito-reading-time&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inside that folder, create a PHP file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;raddito-reading-time.php&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your directory structure should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wp-content/
└── plugins/
    └── raddito-reading-time/
        └── raddito-reading-time.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple, right?&lt;/p&gt;

&lt;p&gt;Now let's make WordPress recognize it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Add the plugin header
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;raddito-reading-time.php&lt;/code&gt; and add:&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="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="cd"&gt;/**
 * Plugin Name: Raddito Reading Time
 * Description: Shows an estimated reading time on single blog posts.
 * Version: 1.0.0
 * Author: Raddito
 * Text Domain: raddito-reading-time
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This header tells WordPress that the PHP file is a plugin.&lt;/p&gt;

&lt;p&gt;Next, add a small security check:&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'ABSPATH'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;exit&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;This prevents the plugin file from being executed directly outside WordPress.&lt;/p&gt;

&lt;p&gt;Now go to your WordPress dashboard:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plugins → Installed Plugins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should see &lt;strong&gt;Raddito Reading Time&lt;/strong&gt; in the list.&lt;/p&gt;

&lt;p&gt;Don't activate it just yet. We still need to add the actual functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Calculate reading time
&lt;/h2&gt;

&lt;p&gt;Reading time is usually estimated by dividing the number of words by an average reading speed.&lt;/p&gt;

&lt;p&gt;For this example, we'll use 200 words per minute.&lt;/p&gt;

&lt;p&gt;The formula is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reading time = Total words / 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So a 600-word article would have an estimated reading time of 3 minutes.&lt;/p&gt;

&lt;p&gt;Let's add a function below our existing code:&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="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;raddito_add_reading_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'post'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;in_the_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_main_query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$post_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_the_ID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nv"&gt;$post_id&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nv"&gt;$raw_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_post_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s1"&gt;'post_content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nv"&gt;$post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'raw'&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$plain_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_strip_all_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;strip_shortcodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$raw_content&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$word_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_word_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$plain_text&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word_count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="cm"&gt;/* translators: %d: estimated reading time in minutes. */&lt;/span&gt;
        &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'%d min read'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'raddito-reading-time'&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nv"&gt;$minutes&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;p class="raddito-reading-time"&amp;gt;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="nf"&gt;esc_html&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$label&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="s1"&gt;'&amp;lt;/p&amp;gt;'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt;
        &lt;span class="nv"&gt;$content&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;Let's break down what's happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Check the page context&lt;/strong&gt;&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_singular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'post'&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;in_the_loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nf"&gt;is_main_query&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$content&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;We only want the reading-time indicator to appear within the main content of individual blog posts.&lt;/p&gt;

&lt;p&gt;This helps prevent it from appearing in unrelated content areas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Get the original post content&lt;/strong&gt;&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;$raw_content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_post_field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'post_content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;$post_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'raw'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the original content rather than the filtered content to avoid counting HTML generated by other plugins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Remove unnecessary markup&lt;/strong&gt;&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;$plain_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;wp_strip_all_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;strip_shortcodes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$raw_content&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;We remove HTML and registered shortcodes so they don't distort our estimate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Calculate the reading time&lt;/strong&gt;&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;$word_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_word_count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$plain_text&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$word_count&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;200&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;The &lt;code&gt;ceil()&lt;/code&gt; function rounds up, while &lt;code&gt;max()&lt;/code&gt; ensures that even very short posts show at least one minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Prepare the output safely&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We use WordPress translation and escaping functions to create the final label.&lt;/p&gt;

&lt;p&gt;This is an important habit when writing WordPress plugins: escape dynamic content when outputting it into HTML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Connect the function to WordPress
&lt;/h2&gt;

&lt;p&gt;We have our function, but WordPress doesn't know when to run it.&lt;/p&gt;

&lt;p&gt;Add this line at the bottom of your plugin:&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_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'the_content'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'raddito_add_reading_time'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;Whenever WordPress processes post content through this filter, our function can add the reading-time label.&lt;/p&gt;

&lt;p&gt;Now activate your plugin and open a published blog post.&lt;/p&gt;

&lt;p&gt;You should see something like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 min read&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Followed by your normal article content.&lt;/p&gt;

&lt;p&gt;No extra dependencies. No page builder required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Make the reading-time label look better
&lt;/h2&gt;

&lt;p&gt;Our plugin works, but a little CSS can improve the appearance.&lt;/p&gt;

&lt;p&gt;Add the following CSS through your theme's custom CSS area or stylesheet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.raddito-reading-time&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;inline-block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.35rem&lt;/span&gt; &lt;span class="m"&gt;0.75rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#f1f5f9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;#334155&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.875rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.5&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;Now the reading-time label will look more like a small badge.&lt;/p&gt;

&lt;p&gt;You can adjust the colors, spacing, and typography to match your website's design system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Test your plugin
&lt;/h2&gt;

&lt;p&gt;Before using custom functionality on a production website, test it.&lt;/p&gt;

&lt;p&gt;Here are a few things worth checking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a short article and confirm it displays at least &lt;code&gt;1 min read&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open a longer article and verify that the estimate changes.&lt;/li&gt;
&lt;li&gt;Visit a standard WordPress page and confirm the label doesn't appear.&lt;/li&gt;
&lt;li&gt;Check your blog archive and make sure excerpts are unaffected.&lt;/li&gt;
&lt;li&gt;Disable the plugin and confirm the label disappears.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, keep in mind that &lt;code&gt;str_word_count()&lt;/code&gt; is most appropriate for English-language content. Sites using languages without conventional space-separated words will need a different counting strategy.&lt;/p&gt;

&lt;p&gt;Our estimate also doesn't include words generated dynamically by shortcodes or blocks.&lt;/p&gt;

&lt;p&gt;For a simple English-language blog, though, this is a useful starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  What did we actually learn?
&lt;/h2&gt;

&lt;p&gt;We built a working WordPress plugin using one PHP file and a WordPress filter.&lt;/p&gt;

&lt;p&gt;Along the way, we explored a few important development concepts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separation of concerns:&lt;/strong&gt; We added functionality without modifying the theme or WordPress core.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks:&lt;/strong&gt; We learned how to extend WordPress behavior through filters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Context-aware logic:&lt;/strong&gt; We limited the feature to the content where it belongs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safe output:&lt;/strong&gt; We used WordPress escaping functions before displaying generated text.&lt;/p&gt;

&lt;p&gt;These principles become even more valuable as you work on larger WordPress projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where could we take this next?
&lt;/h2&gt;

&lt;p&gt;Once you're comfortable with this basic plugin, you could extend it further.&lt;/p&gt;

&lt;p&gt;For example, you could add an admin setting to change the words-per-minute value, support custom post types, or create a Gutenberg block for displaying the reading time wherever you want.&lt;/p&gt;

&lt;p&gt;You could also make the word-counting logic more suitable for multilingual websites.&lt;/p&gt;

&lt;p&gt;Small projects like this are a great way to become familiar with WordPress development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;At Raddito, we work with WordPress regularly, and one lesson keeps coming up: &lt;strong&gt;the best solution isn't always the one with the most features.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, a small piece of well-structured code is exactly what a project needs.&lt;/p&gt;

&lt;p&gt;This was our first tutorial here on DEV, and we're looking forward to sharing more practical lessons about WordPress, development workflows, website performance, and building better experiences for users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now we're curious:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What's one small WordPress feature you've built yourself instead of installing a plugin?&lt;/p&gt;

&lt;p&gt;Share it in the comments. We'd love to hear about it!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;About Raddito&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We're a WordPress web design and development team helping businesses build fast, functional, and easy-to-manage websites.&lt;/p&gt;

&lt;p&gt;Explore our work: &lt;a href="https://raddito.agency/" rel="noopener noreferrer"&gt;Raddito.agency&lt;/a&gt;&lt;br&gt;
Explore our web templates: &lt;a href="https://raddito.net/" rel="noopener noreferrer"&gt;Raddito.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Useful documentation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.wordpress.org/plugins/" rel="noopener noreferrer"&gt;WordPress Plugin Developer Handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.wordpress.org/reference/hooks/the_content/" rel="noopener noreferrer"&gt;WordPress the_content Filter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.wordpress.org/plugins/plugin-basics/header-requirements/" rel="noopener noreferrer"&gt;WordPress Plugin Header Requirements&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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