Marketing Site (PHP)
The marketing site is a standalone plain PHP application with zero dependencies. No Composer, no Node.js, no build step.
Directory Structure
marketing/
├── public/ # Web root (point server here)
│ ├── index.php # Front controller
│ ├── router.php # PHP dev server router
│ ├── .htaccess # Apache URL rewriting
│ ├── css/style.css # All styles
│ ├── js/
│ │ ├── app.js # Dropdowns, theme, accordion
│ │ └── lucide.min.js # Icons (self-hosted)
│ ├── images/ # Screenshots, og-image
│ ├── robots.txt
│ └── sitemap.xml
├── config.php # URLs, plans, locales
├── routes.php # URI → template mapping
├── lang/
│ ├── en.json # English (200+ keys)
│ └── pt.json # Portuguese
├── src/
│ └── helpers.php # i18n, showcase, breadcrumb, markdown
└── templates/
├── layouts/main.php # HTML shell, SEO, structured data
├── partials/
│ ├── header.php # Nav, theme toggle, lang switcher
│ └── footer.php
└── pages/
├── home.php # Landing page
├── features.php # Feature showcases
├── pricing.php # Plans, FAQ, comparison
├── docs.php # Docs index
├── docs-page.php # Docs layout (sidebar + content)
├── 404.php
└── docs/ # Doc content pages
├── installation/
├── project-structure/
├── authentication/
└── ...
How Routing Works
All requests go through public/index.php (via .htaccess rewrite or Nginx try_files).
- Parse the URI and detect locale prefix (
/pt/pricing→ locale=pt, uri=/pricing) - Match against
routes.phpfor marketing pages - Match against
/docs/{section}/{page}pattern for documentation - Render the template through
layouts/main.php
i18n System
Translations live in lang/*.json files. The t('key') helper looks up strings:
// In a template:
<h1><?= t('home.title') ?></h1>
// With placeholders:
<p><?= t('greeting', ['name' => 'John']) ?></p>
URL routing adds a locale prefix for non-default languages: /pricing (English) vs /pt/pricing (Portuguese).
Adding a Language
- Copy
lang/en.jsontolang/es.json - Translate the values
- Add to
config.php:'es' => 'Español'in thelocalesarray
Theme System
Dark/light/system theme toggle stored in localStorage. CSS uses [data-theme="dark"] and [data-theme="light"] selectors with CSS variables for all colors.
Performance
- CSS inlined in
<head>(zero render-blocking stylesheets) - No external fonts (system font stack)
- JS deferred (
app.js) or async (lucide.min.js) - Icons self-hosted (no CDN round trips)
- Gzip + cache headers via
.htaccess