Project: OutAfBox Growth Ecosystem
Technology Stack: Astro 5.x, Tailwind CSS v4, TinaCMS (Local Mode), TypeScript
Repository: git@github.com:adevwithpurpose/outafbox.git
Output Mode: static (pre-rendered HTML — no Node.js server required)
Hosted On: cPanel via Git Version Control → .cpanel.yml deployment
⚠️ CRITICAL: This project uses TinaCMS in local mode. The dev server must be running before you run a production build. Skipping this step will cause afetch failederror and crash the build. See Building for Production.
- Overview
- Project Structure
- Technology Stack
- Content Architecture
- Component System
- Design System
- Development Workflow
- Available Pages
OutAfBox is a performance-driven growth ecosystem for DTC brands scaling from $1M to $50M. The site uses a block-based architecture powered by TinaCMS for content editing, allowing non-technical users to build and modify pages visually.
- High-volume UGC creative production
- Scientific media buying
- Destination optimization (high-converting landing pages)
- Performance-based pricing model
outafbox/
├── .astro/ # Astro build cache
├── .git/ # Git repository
├── business_knowledge/ # Business documentation
│ └── legacy_site_content.md # Legacy content archive
├── content/ # Markdown content source files
│ ├── pages/ # Page content (home.md, about.md, etc.)
│ ├── course/ # Legacy course MDX files (TinaCMS managed)
│ └── velocity_copy.md # Additional copy resources
├── output/ # LMS data pipeline output (DO NOT EDIT MANUALLY)
│ ├── modules.json # Module index (generated by build_content.js)
│ ├── courses.json # Course details (generated by build_content.js)
│ └── [module-slug]/ # Per-module MDX lesson files
├── dist/ # Production build output
├── node_modules/ # Dependencies
├── public/ # Static assets
│ ├── admin/ # TinaCMS admin config
│ └── favicon.ico/svg # Favicon files
├── src/ # Source code
│ ├── assets/ # Images and static assets
│ ├── components/ # Reusable Astro components
│ │ ├── blocks/ # Page building blocks (20+ block types)
│ │ ├── brand/ # Brand elements (Logo.astro)
│ │ ├── landing/ # Landing-specific components
│ │ └── layout/ # Layout components (Header, Footer, Ticker)
│ ├── layouts/ # Page layouts (Layout.astro)
│ ├── pages/ # Route definitions
│ └── styles/ # Global styles (global.css)
├── tina/ # TinaCMS configuration
│ ├── __generated__/ # Auto-generated Tina files
│ ├── config.ts # Tina schema configuration
│ └── tina-lock.json # Schema lock file
├── .cpanel.yml # cPanel deployment config
├── .gitignore # Git ignore rules
├── astro.config.mjs # Astro/Vite configuration
├── package.json # Dependencies and scripts
└── tsconfig.json # TypeScript configuration
| Technology | Version | Purpose |
|---|---|---|
| Astro | 5.x | Static Site Generator (output: "static") |
| Tailwind CSS | 4.x | Utility-first CSS framework |
| TinaCMS | 3.x | Headless Git-based CMS (local mode) |
| TypeScript | Latest | Type-safe development |
| Vite | Latest | Build tool (via Astro) |
ℹ️ No Node.js adapter. The project uses
output: "static"inastro.config.mjs. The@astrojs/nodeadapter was removed. All pages useprerender = true+getStaticPaths()and are served as flat HTML files from cPanel.
{
"dependencies": {
"@astrojs/mdx": "^4.x",
"@tailwindcss/vite": "^4.x",
"@tinacms/cli": "^2.x",
"astro": "^5.x",
"tailwindcss": "^4.x",
"tinacms": "^3.x"
}
}npm run dev # Start dev server with TinaCMS
npm run build # Build production site
npm run preview # Preview production build
npm run astro # Astro CLI commandsPages are composed of reusable "blocks" defined in Markdown files:
Content Source: content/pages/*.md
Example home.md block structure:
---
title: Home
blocks:
- headline: "Scale Your DTC Brand Past the Revenue Ceiling."
subhead: "The all-in-one Growth Ecosystem..."
ctaText: Get Your Free Growth Audit
_template: hero
- label: "Trusted by brands scaling from $1M to $5M/mo"
_template: trustBar
- headline: Why You Are Hitting the Ceiling
id: problem
items:
- title: Creative Burnout
icon: 📉
_template: features
# ... more blocks
---| TinaCMS Typename | Component File |
|---|---|
| PageBlocksHero | HeroBlock.astro |
| PageBlocksFeatures | FeatureGridBlock.astro |
| PageBlocksTestimonials | TestimonialsBlock.astro |
| PageBlocksTrustBar | TrustBarBlock.astro |
| PageBlocksAuditForm | AuditFormBlock.astro |
| PageBlocksCreatorForm | CreatorFormBlock.astro |
| PageBlocksFaq | FAQBlock.astro |
| PageBlocksVsl | VSLBlock.astro |
| PageBlocksComparison | ComparisonBlock.astro |
| PageBlocksFounder | FounderBlock.astro |
| PageBlocksResultsTeaser | ResultsTeaserBlock.astro |
| PageBlocksGuarantee | GuaranteeBlock.astro |
| PageBlocksRoiSimulator | ROISimulatorBlock.astro |
| PageBlocksTeam | TeamGridBlock.astro |
| PageBlocksJobs | JobsListBlock.astro |
Header.astro
- Fixed glass-panel navigation bar
- Mobile hamburger menu with dropdown
- Logo component integration
- CTA button for "Get Audit"
Footer.astro
- Multi-column link structure
- Pre-footer CTA section with animated effects
- Social media links (LinkedIn, Instagram)
- Ecosystem, Intelligence, and Frameworks navigation
GrowthTicker.astro
- Animated ticker showing social proof/metrics
Each block component receives data prop from the page's block definition:
- HeroBlock - Hero section with headline, subhead, CTAs
- FeatureGridBlock - 3-column feature grid with icons
- TestimonialsBlock - Client success stories
- TrustBarBlock - "Trusted by" brand logos
- AuditFormBlock - Lead capture form
- CreatorFormBlock - Creator application form
- FAQBlock - Accordion-style FAQ
- VSLBlock - Video Sales Letter embed
- ComparisonBlock - Before/after comparison
- FounderBlock - Founder's note/message
- ResultsTeaserBlock - Results highlight section
- GuaranteeBlock - Performance guarantee
- ROISimulatorBlock - Interactive ROI calculator
Logo.astro - OutAfBox logo component with scalable classes
--color-brand-purple: #7c3aed /* Primary accent */
--color-brand-blue: #2563eb /* Secondary accent */
--color-brand-pink: #db2777 /* Tertiary accent */
--color-brand-gold: #fbbf24 /* Gold highlight */
--color-brand-green: #10b981 /* Success/operational status */
/* Backgrounds */
background-color: #0a0a0a /* Dark theme base */- Body Font: Inter (Google Fonts)
- Display Font: Saira (Google Fonts) for headings
Glass Panel
.glass-panel {
backdrop-blur-xl;
bg-white/5;
border border-white/10;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
}Glow Effects
.glow-purple- Purple glow for CTAs.glow-blue- Blue glow for accents
Gradient Text
.text-gradient-main- Blue→Purple→Pink gradient
fadeIn- Fade in with slide up- Hover scale effects on buttons and links
- Animated background blurs in footer
cd outafbox
npm install
npm run devThis starts TinaCMS dev mode alongside the Astro dev server:
- Local Site:
http://localhost:3000 - TinaCMS Admin:
http://localhost:3000/admin/index.html
🚨 MANDATORY PROCESS — Do not skip any step.
TinaCMS runs a local GraphQL API that index.astro and [...slug].astro query at build time. If that API is not running, the build will crash with fetch failed.
Open a terminal and start the dev server. Keep this running the entire time.
npm run devWait until you see:
✅ 🦙 TinaCMS Dev Server is active
astro vX.X.X ready in XXXX ms
Open a second, separate terminal and run:
npx astro buildSuccess looks like:
[build] 462 page(s) built in 9.08s
[build] Complete!
⚠️ Common mistake: Runningnpm run devandnpm run buildin the same terminal sequentially will NOT work. The dev server must be actively running in a background terminal while the build runs.
🚨 The
dist/folder is force-added to git because cPanel reads it directly. Never skipgit add dist -f.
# Step 1: Stage all source changes
git add .
# Step 2: Force-add the compiled dist/ folder
git add dist -f
# Step 3: Commit
git commit -m "Deploy: [brief description of changes]"
# Step 4: Push to remote
git push origin main- Log into cPanel
- Navigate to Git™ Version Control
- Click Manage next to the project
- Go to the Pull or Deploy tab
- Click Update from Remote
- Click Deploy HEAD Commit
Before any significant structural changes, create a backup branch:
# Create and push a backup branch (naming convention: backup/description-YYYY-MM-DD)
git checkout -b backup/pre-my-change-2026-03-02
git push origin backup/pre-my-change-2026-03-02
# Return to main
git checkout main| Error | Cause | Fix |
|---|---|---|
fetch failed |
TinaCMS dev server not running | Start npm run dev in Terminal 1 first |
Cannot use server-rendered pages without an adapter |
A page has prerender = false in static mode |
Find the page and convert to getStaticPaths() or remove the flag |
EADDRINUSE :::3000 |
Port 3000 already in use | Run Stop-Process -Name node -Force and retry |
Expected } but found ... |
Syntax error in an Astro/MDX file | Check the line number in the error log |
| Site didn't update on cPanel | dist/ was not committed |
Re-run git add dist -f before committing |
- Create markdown file in
content/pages/(e.g.,new-page.md) - Define blocks with
_templateproperty matching block types - Pages are automatically picked up by
[...slug].astroviagetStaticPaths() - Run the Two-Terminal build and push
- Create component in
src/components/blocks/BlockName.astro - Add to
PageBuilder.astroswitch statement with the new typename - Define schema in
tina/config.ts - Run the Two-Terminal build and push
| Page | Route | Content File | Type |
|---|---|---|---|
| Home | / |
content/pages/home.md |
TinaCMS block-builder |
| About | /about |
src/pages/about.astro |
Static Astro |
| Audit | /audit |
content/pages/audit.md |
TinaCMS block-builder |
| Careers | /careers |
content/pages/careers.md |
TinaCMS block-builder |
| Creators | /creators |
content/pages/creators.md |
TinaCMS block-builder |
| Case Studies | /case-studies |
src/pages/case-studies.astro |
Static Astro |
| Ecosystem | /ecosystem |
src/pages/ecosystem.astro |
Static Astro |
| Privacy | /privacy |
src/pages/privacy.astro |
Static Astro |
| Terms | /terms |
src/pages/terms.astro |
Static Astro |
| Training Library | /courses |
src/pages/courses/index.astro |
LMS — Static (prerendered) |
| Module Page | /courses/[module] |
src/pages/courses/[module].astro |
LMS — Static (prerendered) |
| Lesson Player | /courses/[module]/[lesson] |
src/pages/courses/[module]/[lesson].astro |
LMS — Static (prerendered) |
The site includes a comprehensive video course system accessible at /courses/* routes, using a high-performance SSG (Static Site Generation) architecture:
- Routing Architecture:
/courses: Main index with client-side search./courses/[module]: Module index page featuring sequential lesson numbering (01, 02...) and horizontal layout./courses/[module]/[lesson]: Advanced lesson player with persistent sidebar navigation and MDX content rendering.
- Content Synchronization:
- MDX Integration: Lessons are rendered using MDX, combining frontmatter metadata with rich text and video components.
- Drive Sync: Supplemental text content is synced from Google Drive via
rcloneand programmatically merged into MDX files. - Frontmatter Sanitization: Automated scripts ensure YAML compliance for special characters in titles.
- Player Features:
- Hybrid Layout: Video player is positioned directly below the header for immediate access, followed by MDX content.
- Sidebar Navigation: Real-time progress indicators and quick access to all lessons within the module.
- Action Buttons: Integrated "View in Drive" and "Download Lesson" buttons for all videos.
- Data Pipeline:
- Source:
mega_course_database.csvserves as the master source of truth. - Build Script:
build_content.jstransforms the CSV into optimized JSON files (output/courses.jsonandoutput/modules.json).
- Source:
- UI & Performance:
- SSG Core: Pages are pre-rendered (
prerender = true) for sub-second load times. - Tailwind v4: Modern utility-first styling with custom CSS for MDX content containment.
- Accessibility: ARIA labels and semantic structure for sidebar and navigation.
- SSG Core: Pages are pre-rendered (
Remote URL: git@github.com:adevwithpurpose/outafbox.git
Main Branch: main
Backup Convention: backup/description-YYYY-MM-DD
See Pushing to Git above for the full, correct deployment sequence. Do not use a simple
git add . && git commit && git push— thedist/folder must be force-added.
The project previously used output: "server" with @astrojs/node adapter. This was changed to output: "static" because:
- cPanel cannot run a Node.js server process via simple file copy (
.cpanel.ymlusescp -R dist/* $DEPLOYPATH) - All LMS pages (
/courses/*) useprerender = true+getStaticPaths()and work perfectly as static HTML - TinaCMS pages are fetched at build time (not runtime) via the local GraphQL server
TinaCMS local mode starts a GraphQL API on a separate port. Pages like src/pages/index.astro and src/pages/[...slug].astro query this API during the build with await client.queries.page(...). If the API server is not running, those fetches throw fetch failed and crash the build.
Running npm run dev in Terminal 1 keeps the TinaCMS API alive so Terminal 2 can successfully run npx astro build.
Document last updated: 2026-03-02