@antinna/blogger-theme: Say Goodbye to Designing Single XML Files for Blogger

mg3994
@antinna/blogger-theme: Say Goodbye to Designing Single XML Files for Blogger

For more than a decade, creating or customizing a Blogger theme has been a frustrating experience. Developers have had to manually write and edit massive, monolithic XML files that combine HTML, CSS, native template loops, conditional tags, and inline scripts in a single unmanageable file. What if you could build modern, production-ready Blogger layouts using clean, modular React components, typed with TypeScript, styled with Tailwind CSS, and compiled automatically with hot-reloading? Introducing @antinna/blogger-theme—an innovative, type-safe development framework that changes Blogger development forever by compiling React and JSX directly into native Blogger-compliant XML templates.

🚀 No More Outdated Type Definitions!

The latest version of @antinna/blogger-theme has undergone major enhancements. It now fully supports native typings out of the box. You no longer need to write complex local .d.ts files to declare Blogger namespaces. The framework directly exports typed layout components (like BSection, BWidget, BLoop, BIf, and BClientScript) that typecheck perfectly with TypeScript automatically!



Step 1 The Problem with Legacy Blogger XML Files

Traditional Blogger layouts are structured inside a single, complex XML document. This monolithic approach forces you to combine server-side layout logic, page configurations, global styles, and client scripts into one file. Development quickly becomes difficult because:

  • No Module Separation: You cannot break your header, sidebar, post layout, or comments section into clean, reusable files.
  • No Type-Safety or Autocomplete: Editors have no understanding of Blogger's proprietary template attributes, resulting in frequent syntax issues and typos.
  • Fragile Script Injections: Adding custom client JavaScript requires either confusing CDATA blocks or writing unreadable, HTML-escaped character strings.

Step 2 Introducing @antinna/blogger-theme: Core Concepts

The @antinna/blogger-theme framework completely changes how you build Blogger themes. It compiles modern, component-driven React JSX templates into the exact XML tags that Blogger's template engine requires. It handles complex operations automatically:

  • Translates JSX components into compliant <b:section>, <b:widget>, and <b:includable> XML blocks.
  • Enforces strict type-safety for conditional constructs (<BIf>) and server loops (<BLoop>).
  • Injects bundled CSS sheets and single-page React apps safely into Blogger's CDATA blocks.

Step 3 Understanding the JSX Compiler and Core Exports

The framework exports a comprehensive suite of typed JSX components that align directly with Blogger's layout tags. This removes the need to write custom TypeScript declarations. Key exports include:

Exported Component Blogger XML Target Key Attributes / Features
BloggerTheme Theme Orchestrator Takes document headers, body layouts, and builds the raw theme string.
BSection <b:section> A layout container representing a sidebar, header, or post grid area.
BWidget <b:widget> Represents specific widget assets (like a Header, Blog, or AdSense block).
BIf <b:if> Enforces conditional structures (e.g. testing if the page is a homepage).
BLoop <b:loop> Loops through data arrays like "data:posts".
BClientScript Script CDATA Injection Compiles and embeds external TypeScript/JavaScript app scripts.

Step 4 Step-by-Step Theme Building with TypeScript

To compile your theme, create a central script file (e.g. theme/src/main.tsx). This script acts as the entry point, defining your layouts and calling the compiler to generate the XML theme file:

📂 theme/src/main.tsx
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from "node:url";
import {
  BloggerTheme,
  BSection,
  BWidget,
  BClientScript,
  BSkin,
  Title,
  BIf,
  BIncludable,
  BInclude,
  BLoop,
  BData,
  BEval,
} from "@antinna/blogger-theme";

// Polyfill __dirname for ES Modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const ROOT_DIR = path.resolve(__dirname, "../../");
const DIST_DIR = path.resolve(ROOT_DIR, "dist");
const OUTPUT_CSS_PATH = path.resolve(DIST_DIR, "output.css");
const REACT_APP_ENTRY = path.resolve(ROOT_DIR, "app/src/index.tsx");

const BlogHeader = () => (
  <header className="header-container">
    <BSection
      id="main-header"
      className="main-header-sec"
      maxwidgets={1}
      showaddelement={true}
    >
      <BWidget
        id="Header1"
        type="Header"
        title="My React Blog Header"
        locked={true}
      />
    </BSection>

    <BIf cond="data:view.isHomepage">
      <div className="homepage-banner">
        <h1 expr:title="data:blog.title">
          Welcome to {new BEval({ expr: "data:blog.title" })}!
        </h1>
        <p>A cutting-edge blog layout engineered entirely in TypeScript.</p>
      </div>
    </BIf>
  </header>
);

const BlogLayout = () => (
  <div className="wrapper-pane">
    <BlogHeader />

    <main className="content-area">
      <BSection id="main-content-sec">
        <BWidget id="Blog1" type="Blog">
          <BIncludable id="main">
            <BLoop values="data:posts" varName="post">
              <div className="post-item-view" expr:id="data:post.id">
                <h2 expr:class="data:post.class">
                  <a expr:href="data:post.url">
                    <BData value="post.title" />
                  </a>
                </h2>
                <div className="post-body">
                  <BData value="post.body" />
                </div>
              </div>

              <BInclude name="postShareButtons" data="post" />
            </BLoop>
          </BIncludable>
        </BWidget>
      </BSection>

      {/* Target element for React SPA mounting */}
      <div id="react-root"></div>

      {/* Embeds your React entry point with hot reloading support */}
      <BClientScript scriptPath={REACT_APP_ENTRY} mode="cdata" />
    </main>
  </div>
);

function buildTheme() {
  if (!fs.existsSync(DIST_DIR)) {
    fs.mkdirSync(DIST_DIR, { recursive: true });
  }

  const theme = new BloggerTheme({
    attributes: {
      "b:responsive": "true",
      "b:defaultwidgetversion": "2",
      "b:layoutsversion": "3",
    },
    head: [
      <Title id="ram">React Blogger Theme Example</Title>,
      <BSkin css={OUTPUT_CSS_PATH} />,
    ],
    body: [<BlogLayout />],
  });

  const xml = theme.generate();
  const outputPath = path.resolve(DIST_DIR, "blogger-theme.xml");
  fs.writeFileSync(outputPath, xml, "utf8");

  console.log(`\n🎉 Success! Blogger XML theme generated at: ${outputPath}`);
}

buildTheme();

Step 5 Integrating an Embedded React App with BClientScript

One of the most powerful features of @antinna/blogger-theme is its ability to bundle a modern React application directly into Blogger's XML output. By utilizing the <BClientScript /> element, you can link to an external React component. The compiler automatically builds, compiles, and embeds this script into CDATA wrappers, allowing you to run a modern, interactive app directly inside Blogger:

📂 app/src/App.tsx
import React, { useState } from "react";

export const App = () => {
  const [count, setCount] = useState(0);

  return (
    <div className="p-6 bg-blue-50 rounded-xl border border-blue-200">
      <h2 className="text-xl font-bold text-blue-900">Embedded React App 🚀</h2>
      <p className="text-blue-700 mt-1">This component is bundled into Blogger CDATA.</p>
      <button
        onClick={() => setCount((c) => c + 1)}
        className="mt-4 px-4 py-2 bg-blue-600 text-white font-medium rounded-lg shadow hover:bg-blue-700 transition-colors cursor-pointer"
      >
        Clicks: {count}
      </button>
    </div>
  );
};

Step 6 Styling with Tailwind CSS and Building the Pipeline

To style your layout elements, write standard CSS inside a source file like style/src/input.css using standard Tailwind CSS classes. When you run the compilation command, the build pipeline processes your classes, compiles the Tailwind bundle into dist/output.css, and embeds it directly into the XML theme output via <BSkin css={OUTPUT_CSS_PATH} />!


Step 7 Quickstart Template Repository and Installation

To help you get started quickly, a pre-configured starter template is available. This template sets up the monorepo structure, Tailwind CSS build scripts, and React configurations automatically.

📂 Open Source Quickstart Template

Avoid manual setup by cloning the official template repository:
👉 Tailwind React Blogger Template: github.com/mg3994/Blogger-Tailwind-React

To run and compile the template locally:

$ git clone https://github.com/mg3994/Blogger-Tailwind-React.git
$ cd Blogger-Tailwind-React && npm install
$ npm run dev

The compiler will watch your React components and stylesheet modifications, compiling them automatically into dist/blogger-theme.xml. Simply copy and paste this compiled XML file directly into Blogger's theme editor!


Step 8 Benefits of this Modern Approach

Moving your theme development to @antinna/blogger-theme brings several major benefits:

  • Fully Component-Driven: Organize your theme using small, self-contained files (e.g. Header.tsx, Sidebar.tsx, Footer.tsx) instead of a single massive file.
  • Robust Type-Safety: All properties, arrays, and Blogger constructs are fully typed, catching potential errors during development.
  • Tailwind & React Integration: Use your favorite frontend libraries and styling tools directly inside Blogger, raising it to the standard of modern CMS systems.

Complete Conclusion & Next Steps

Developing templates for Blogger no longer requires writing rigid, unmanageable XML files. With @antinna/blogger-theme, you can build layouts using component-driven, type-safe React JSX files, styled with Tailwind CSS, and compiled automatically.

🎉 Start Building Today!

Clone the template repository, run npm install, and start customizing your layout using clean JSX components. Your compiled, responsive Blogger theme XML will be ready in seconds!


📄 Contributions & Feedback

We believe this modern development workflow makes building templates for Blogger both elegant and fun. What features are you planning to build with React and TypeScript inside your next Blogger theme? Let us know in the comments below!

Post a Comment