7.5 KiB
Framex Engine Documentation
Framex is a small PHP engine for building fast websites with plain PHP views, Markdown pages, reusable templates, and Tailwind CSS 4. It is designed to stay simple: URLs map to files, templates wrap views, and assets live in public.
Project Structure
The important folders are:
app/views/ Page views for URLs
core/ Router, renderer, helpers, and configuration
templates/ Layout templates and partials
templates/partials/ Shared pieces such as top menu and footer
public/ Web root for CSS, JS, images, and index.php
public/css/src/ Tailwind source CSS
public/css/style.css Compiled production CSS
public/js/init.js Theme toggle and menu behavior
The web server should point to public as the document root.
URL Routing
Framex resolves the browser URL to a file inside app/views.
For a request like:
/about
Framex checks these files in order:
app/views/about.php
app/views/about/index.php
app/views/about.md
app/views/about/index.md
The first file that exists is rendered. If none exists, Framex falls back to templates/error404.php.
Examples:
/ -> app/views/index.php
/docs -> app/views/docs/index.md
/about -> app/views/about/index.md
/pricing -> app/views/pricing.php
/blog/hello -> app/views/blog/hello.php or app/views/blog/hello/index.md
Trailing slashes are normalized, so /docs/ and /docs resolve the same way.
PHP Views
Use PHP views when a page needs custom markup, variables, conditionals, loops, forms, or reusable PHP logic.
Create a file:
app/views/pricing.php
Then visit:
/pricing
A PHP view can set page metadata by assigning values to the $data array:
<?php
$data['title'] = 'Pricing - Framex';
$data['metaDescription'] = 'Simple pricing page built with Framex.';
$data['bodyClass'] = 'bg-slate-50 text-slate-950 dark:bg-slate-950 dark:text-slate-100';
?>
<main class="section">
<div class="contain">
<h1 class="text-4xl font-semibold">Pricing</h1>
<p class="mt-4 text-slate-600 dark:text-slate-400">Choose the right plan.</p>
</div>
</main>
The rendered PHP view is injected into the main template through <?= $view ?>.
Markdown Views
Use Markdown views for documentation, simple content pages, articles, and static text-heavy pages.
Create a file:
app/views/guide/index.md
Then visit:
/guide
Markdown files are parsed by Parsedown and automatically wrapped in:
<article class="prose prose-shell">
...
</article>
That means Markdown pages automatically get readable typography, spacing, links, lists, code blocks, tables, blockquotes, images, and light/dark colors.
Example Markdown page:
# My Guide
This page is rendered from Markdown.
## Features
- Clean URLs
- Automatic styling
- Light and dark mode
```php
echo 'Code blocks are styled too';
## Templates
The default layout is:
```text
templates/main.php
It handles:
- HTML document structure
- Meta tags
- CSS include
- Dark-mode bootstrap
- Top menu partial
- Current view output
- Footer partial
- JavaScript include
The main content flow is:
<?= partial('topmenu') ?>
<?= $view ?>
<?= partial('footer') ?>
Partials live in:
templates/partials/
For example:
templates/partials/topmenu.php
templates/partials/footer.php
Load a partial with:
<?= partial('topmenu') ?>
Metadata
PHP views can customize metadata with $data.
Common keys:
$data['title'] = 'Page title';
$data['metaDescription'] = 'Page description for search and sharing.';
$data['metaImage'] = image(1200, 630);
$data['bodyClass'] = 'custom body classes';
$data['template'] = 'main';
If a key is not set, templates/main.php uses sensible defaults.
Markdown views currently use the default metadata unless the renderer is extended to read front matter.
Assets
Public files are served from public.
Examples:
public/css/style.css -> /css/style.css
public/js/init.js -> /js/init.js
public/images/logo.png -> /images/logo.png
Use the asset() helper for cache-busted URLs:
<link rel="stylesheet" href="<?= asset('css/style.css') ?>">
<script src="<?= asset('js/init.js', ['prefix' => 'framex', 'hash' => true]) ?>"></script>
Useful asset options:
asset('css/style.css');
asset('js/init.js', ['hash' => true]);
asset('images/logo.png', ['absolute' => true]);
asset('images/missing.png', ['fallback' => '/images/default.png']);
Tailwind CSS
Framex uses Tailwind CSS 4 through the Tailwind CLI.
Install dependencies:
npm install
Build CSS:
npm run build:css
Watch CSS during development:
npm run watch:css
Source CSS:
public/css/src/style.css
Compiled CSS:
public/css/style.css
Tailwind scans these sources:
@source "../../../templates/**/*.php";
@source "../../../app/**/*.php";
@source "../../../app/**/*.md";
When you add new Tailwind classes in PHP or Markdown files, rebuild the CSS.
Reusable CSS Classes
The project includes reusable classes in public/css/src/style.css.
Layout:
<section class="section">
<div class="contain">...</div>
</section>
Buttons:
<a class="btn btn-primary" href="/docs">Primary</a>
<a class="btn btn-secondary" href="/about">Secondary</a>
<button class="btn btn-ghost">Ghost</button>
Cards:
<article class="card">
<h2>Card title</h2>
<p>Card content.</p>
</article>
Preset backgrounds:
<div class="bg-pre-blue">Blue preset</div>
<div class="bg-pre-emerald">Emerald preset</div>
<div class="bg-pre-amber">Amber preset</div>
<div class="bg-pre-rose">Rose preset</div>
These presets include both light and dark colors.
Light and Dark Mode
Dark mode is controlled by the dark class on the <html> element.
The inline script in templates/main.php runs before the stylesheet loads. It checks:
- The saved
framex-themevalue inlocalStorage. - The browser system preference.
- Light mode as the fallback.
The toggle buttons in templates/partials/topmenu.php use:
data-theme-toggle
The behavior is implemented in:
public/js/init.js
Use Tailwind dark variants anywhere:
<div class="bg-white text-slate-950 dark:bg-slate-900 dark:text-white">
Theme-aware content
</div>
Running Locally
Install dependencies and build CSS:
npm install
npm run build:css
Start PHP's built-in server:
php -S localhost:8000 -t public
Open:
http://localhost:8000/
Useful URLs:
/ Landing page
/docs This documentation
/about Example Markdown page
Adding a New Page
For a PHP page:
app/views/services.php
Visit:
/services
For a Markdown page:
app/views/services/index.md
Visit:
/services
For a nested page:
app/views/blog/hello-world/index.md
Visit:
/blog/hello-world
Recommended Workflow
- Add or edit a PHP or Markdown view in
app/views. - Use
templates/partialsfor shared UI. - Use
.section,.contain,.btn,.card, and preset backgrounds for consistent design. - Run
npm run build:cssafter changing Tailwind classes. - Test the URL in the browser.
Framex works best when pages stay close to the filesystem, shared layout stays in templates, and reusable styling stays in the Tailwind source CSS.