Content Strategy & Architecture¶
Archived record
This page describes the Firebase-era platform or a migration step that has completed. It is kept as history and is not a current runbook. The current platform is described from the home page.
Architecture Decision¶
Decision: Use a Client-Side Data Fetching model with React + Vite and Firestore as the headless CMS.
Why:
- Simplicity: No complex build pipelines or server-side rendering infrastructure to manage.
- Real-time: Content updates are instantly available without rebuilding or revalidating.
- Cost: Leveraging Firebase's generous free tier and low-cost reads.
- Performance: Initial app shell loads instantly from CDN; content fetches are fast via Firestore.
Technical Implementation¶
Component Structure¶
The application uses a Template Pattern where generic page components (BlogTemplate,
FrameworkTemplate) are populated with data fetched based on the URL.
// src/pages/templates/BlogTemplatePage.jsx (simplified)
import { useParams } from 'react-router-dom';
import { useFirestoreDocument } from '@/hooks/useFirestore'; // Custom hook
import { useProviderConfig } from '@/context/ProviderContext';
export default function BlogTemplatePage() {
const { provider, slug } = useParams();
const theme = useProviderConfig();
// Fetch content: /unique_content/{provider}/blog/{slug}
const {
data: post,
loading,
error,
} = useFirestoreDocument(`unique_content/${provider}/blog/${slug}`);
if (loading) return <Loader />;
if (error) return <NotFound />;
return (
<article className="blog-post" style={{ '--primary': theme.color }}>
<header className="blog-header">
<Badge color={theme.color}>{provider.toUpperCase()}</Badge>
<h1>{post.title}</h1>
<Meta author={post.author} date={post.publishedAt} />
</header>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
);
}
Firestore Schema¶
The database schema is designed for efficient read access by the client application.
firestore/
├── providers/{providerId}
│ ├── theme: { ... } (synced with frontend config)
│ └── metadata: { ... }
│
├── unique_content/{providerId}/{contentType} // Collection
│ ├── {slug} // Document ID matches URL slug
│ │ ├── title: "String"
│ │ ├── content: "HTML/Markdown String"
│ │ ├── author: "String"
│ │ ├── publishedAt: Timestamp
│ │ ├── tags: [Array]
│ │ ├── seo: {
│ │ │ title: "String",
│ │ │ description: "String"
│ │ │ }
│ │ └── ...
Content Types & URL Mapping¶
| Content Type | URL Pattern | Collection Path | Template Component |
|---|---|---|---|
| Blog Post | /:provider/blog/:slug |
unique_content/{provider}/blog |
BlogPage |
| Framework | /:provider/framework/:slug |
unique_content/{provider}/framework |
FrameworkPage |
| Architecture | /:provider/architecture/:slug |
unique_content/{provider}/architecture |
ArchitectureDesignsPage |
Content Creation Workflow¶
1. Authoring¶
Content creators write content (Markdown or HTML) and define metadata.
2. Publishing¶
Content is pushed to Firestore. This can be done via:
- Scripts: A Node.js script uploads Markdown files from the local repo.
- Admin UI: (Future) value-add feature for direct editing.
- API: Automated aggregation from RSS feeds (e.g., for
terrafrom/rss).
3. Consumption¶
Users navigate to a URL. The Single Page Application (SPA):
- Loads the application shell (Header, Nav, Footer).
- Identifies the
providerandslugfrom the URL. - Fetches the document from Firestore.
- Renders the content using the provider's theme.
SEO Strategy (SPA)¶
Since the content is rendered client-side, we use React Helmet Async to manage metadata for social sharing and browser tabs.
<Helmet>
<title>{post.seo.title || post.title} | HCW</title>
<meta name="description" content={post.seo.description} />
<meta property="og:title" content={post.title} />
{/* ... other tags */}
</Helmet>
Note: For enhanced search engine indexing, we may explore Pre-rendering solutions or migrate to Server-Side Rendering (SSR) if SEO becomes a critical blocker, but for the MVP, standard Google Crawler execution of JS is sufficient.
Performance Considerations¶
- Caching: Firestore SDK handles offline persistence and caching.
- Code Splitting: Templates are lazy-loaded only when needed.
- Optimistic UI: Use skeletons/loaders while fetching data.
Security¶
- Firestore Rules:
allow read: if true;(Public content)allow write: if request.auth != null && request.auth.token.admin == true;(Admin only)
Version: 2.0 (SPA Architecture) Date: February 10, 2026