Rebuild SHTML

Code ExamplesText review

Here are the four methods with fully copy-pasteable, production-ready code for your single-page app architecture.


This uses a tiny script to load your HTML fragments right when your app starts. It keeps everything strictly in the browser.

1. Create your component files: Create header.html and footer.html in a folder called components/. (Just put the raw HTML inside them, no <html> or <body> tags needed).

2. Your index.html file:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My App</title>
</head>
<body>

    <!-- Target containers for your includes -->
    <header id="site-header"></header>
    
    <main id="app-content">
        <!-- Your existing JS will load JSON article data here -->
    </main>

    <footer id="site-footer"></footer>

    <!-- The Loader Script -->
    <script>
        async function loadInclude(selector, filePath) {
            const el = document.querySelector(selector);
            if (!el) return;
            try {
                const res = await fetch(filePath);
                if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
                el.innerHTML = await res.text();
            } catch (err) {
                console.error(`Failed to load ${filePath}:`, err);
                el.innerHTML = `<!-- Failed to load ${filePath} -->`;
            }
        }

        // Run as soon as the HTML shell loads
        document.addEventListener('DOMContentLoaded', () => {
            loadInclude('#site-header', 'components/header.html');
            loadInclude('#site-footer', 'components/footer.html');
            
            // ... Call your existing function that fetches the PHP-generated JSON here ...
        });
    </script>
</body>
</html>
  • Pros: 100% decoupling from backend, pure .html.
  • Cons: Cannot test by double-clicking the file locally (requires a local server like VS Code Live Server to bypass CORS).

Method 2: Modern Web Components

This creates custom HTML tags for your header and footer. It does the exact same thing as Method 1, but the code is heavily modular and highly modern.

1. The Component Script (app.js):


// Define a reusable class for external HTML components
class HTMLInclude extends HTMLElement {
    async connectedCallback() {
        const file = this.getAttribute('src');
        if (!file) return;
        
        try {
            const res = await fetch(file);
            if (res.ok) {
                this.innerHTML = await res.text();
            }
        } catch (err) {
            console.error(`Error loading component: ${file}`, err);
        }
    }
}

// Register the custom tag with the browser
customElements.define('html-include', HTMLInclude);

2. Your index.html file:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My App</title>
    <!-- Load your components script first -->
    <script src="app.js"></script>
</head>
<body>

    <!-- Just use your new custom tag! -->
    <html-include src="components/header.html"></html-include>
    
    <main id="app-content"></main>

    <html-include src="components/footer.html"></html-include>

</body>
</html>
  • Pros: Extremely clean HTML syntax; highly scalable if you add more components later.
  • Cons: Same local testing limitation as Method 1.

Method 3: Native PHP Includes

Since you have PHP on your shared host, you can simply change your index.html extension to .php. The server will stitch it together instantly before sending it to the user.

1. Your main file (MUST be renamed to index.php):


  <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My App</title>
</head>
<body>

    <!-- PHP pulls this in instantly on the server -->
    <?php include 'components/header.html'; ?>
    
    <main id="app-content">
        <!-- Your JS injects the article JSON here -->
    </main>

    <!-- PHP pulls this in instantly on the server -->
    <?php include 'components/footer.html'; ?>

    <script src="app.js"></script>
</body>
</html>
  • Pros: Zero Javascript needed for the layout. No FOUC (Flash of Unstyled Content). 100% success rate on shared hosting.
  • Cons: You are no longer using purely .html files. Requires a local PHP environment (like XAMPP or php -S localhost:8000) to test on your computer.

Method 4: Apache .htaccess SSI

This is the true .shtml method, but configured to work on standard .html files.

1. Create a .htaccess file in your main public directory:

# Enable Server Side Includes
Options +Includes
# Tell the server to parse .html files for includes
AddType text/html .html
AddOutputFilter INCLUDES .html

2. Your index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My App</title>
</head>
<body>

    <!-- Apache server will replace this before the browser sees it -->
    <!--#include virtual="components/header.html" -->
    
    <main id="app-content"></main>

    <!--#include virtual="components/footer.html" -->

    <script src="app.js"></script>
</body>
</html>
  • Pros: Keeps the .html extension, acts instantly on the server, no JS required for layout.
  • Cons: ~25% chance your shared host has disabled mod_include for security (if they did, adding the .htaccess file will break your site with a 500 error). Like PHP, you cannot test this locally without running an Apache server.

TEXT Review

Here is a summary of all the methods that fit your exact setup (a single index.html SPA, pure JS/CSS/HTML frontend, on shared hosting), ranked by their ease of use for your specific architecture.

(Note: "% Success Rate" here means the likelihood it will work immediately in both your live shared hosting environment and on your local computer without tricky configuration.)


1. Vanilla JavaScript fetch() (The SPA Standard)

You use a tiny JS script in index.html to fetch header.html and inject it into a <div> or <header> tag when the page loads.

  • Success Rate: 99%

  • How it works: document.querySelector('header').innerHTML = await (await fetch('header.html')).text();

  • Drawbacks:

    • FOUC (Flash of Unstyled Content): Because the HTML loads, then JS runs, then the header fetches, there may be a split-second delay where the header is missing before it pops in.
    • Local Testing limitation: You cannot just double-click index.html on your computer (file:///). Browser security (CORS) blocks fetch() from reading local files. You must use a local server (like VS Code's "Live Server") to test on your machine.

2. Modern JS Web Components (The Cleanest Code)

You register a custom HTML tag using JS (e.g., <site-header></site-header>), and the browser automatically fetches the HTML to fill it whenever it sees that tag.

  • Success Rate: 95%

  • How it works: class SiteHeader extends HTMLElement { ... } customElements.define('site-header', SiteHeader);

  • Drawbacks:

    • Same issues as vanilla fetch(): Has a split-second load delay and requires a local server to test.
    • Browser Support: Works on all modern browsers, but will fail entirely if a user is on an ancient browser (like Internet Explorer).

3. Native PHP Includes (The Easiest Server Method)

Instead of fighting with .html, you simply rename your one page from index.html to index.php. Since you already have PHP on your shared host, this works out of the box.

  • Success Rate: 100% (On your live server)

  • How it works: Put <?php include 'header.html'; ?> directly inside index.php.

  • Drawbacks:

    • Breaks the "Pure HTML" rule: Your main file is now a .php file, not .html.
    • Local Testing: To view your app locally, you now have to run a local PHP server (like XAMPP, MAMP, or php -S) instead of just opening an HTML file.

4. Apache SSI via .htaccess (True .shtml behavior)

You add a .htaccess file to your server telling it to process standard .html files for Server-Side Includes (SSI) before sending them to the browser.

  • Success Rate: ~75% (Depends heavily on your specific web host)

  • How it works: <!--#include virtual="header.html" --> goes right in index.html.

  • Drawbacks:

    • Hosting Restrictions: Many shared hosts disable mod_include (SSI) for security or performance reasons. If they do, adding the .htaccess code will either do nothing, or instantly crash your site with a 500 Internal Server Error.
    • Local Testing: Your local computer does not run Apache by default. If you double-click index.html locally, the <!--#include --> tag will just be ignored as an HTML comment, and your header won't load.

The Verdict for your project:

Since you are building a Single Page Application (SPA) where JavaScript is already doing the heavy lifting (pulling JSON from your PHP bridge and rendering articles), Method 1 (Vanilla JS fetch) is by far the most natural fit.

It keeps your frontend 100% decoupled from the server, maintains the pure .html extension, and fits perfectly into the existing Javascript flow of your app.