A lightweight, single-file PHP content management system built for performance, SEO, and developer sanity.
Your site is live. Set your branding, build your first page, launch.
Structured content types with custom fields, templates, and taxonomy.
Build layouts with HTML and double-curly-brace tokens. No PHP required.
Built-in SEO intelligence with keyword research, position tracking, and AI recommendations.
LiteFrame CMS is a PHP/MySQL content management system designed for agencies and developers who need fast, maintainable sites without the overhead of WordPress. The entire admin panel lives in a single PHP file architecture with no plugin dependencies, no composer packages, and no build pipeline.
Performance first. Every page renders as clean HTML/CSS. No JavaScript frameworks on the front end. PageSpeed scores stay in the 90s without optimization plugins.
Single-file admin. The admin panel is self-contained. Each feature (editor, collections, SEO, forms) is a PHP include file. Deploy by uploading files.
Collections as first-class content. Not just pages and posts. Collections give you custom content types with entry fields, categories, tags, index pages, entry pages, and card templates, all configurable from the admin UI.
Developer-friendly. Templates use HTML with {{token}} syntax. No template language to learn. Write the HTML you want, drop in tokens where data goes.
LiteFrame is a hosted platform. We handle the server, the database, the SSL, the updates. You build your site, we keep it running. If you ever want to leave, you can export your entire site as a static HTML package and take it anywhere.
What makes LiteFrame different.
Every page LiteFrame serves is clean HTML and CSS. No JavaScript frameworks on the front end, no render-blocking scripts, no layout shift. This is why PageSpeed scores stay in the 90s without optimization plugins or CDN tricks.
The entire admin is one interface. Pages, collections, SEO, forms, media, AI tools, and settings all live in one place. No plugin ecosystem, no compatibility matrix, no update anxiety.
All content lives in a unified system. Standard pages, blog posts, landing pages, and collection entries are all managed the same way. Collection field data is stored as structured JSON, which means your content is portable and queryable.
Layouts use HTML with {{token}} syntax. You write the HTML you want, drop in tokens where data goes. No PHP, no template language, no build step. If you can write HTML, you can build templates.
LiteFrame supports multiple site modes for different use cases:
| Mode | Description |
|---|---|
hosted_direct | Standard mode. Full HTML editing, template access, code editor. |
hosted_secure | Templates locked. Users edit through schema fields only. For client-managed sites where the developer controls the design. |
hybrid | Some pages use secure templates, others use direct editing. |
headless | Content-only. Front end is a separate application consuming the API. |
Your site is yours. Export at any time as a complete static HTML package. Your content, your templates, your images, fully self-contained and deployable to any web server.
Your site is ready. Here's how to make it yours.
Log in at yourdomain.com/admin with the credentials from your welcome email. You'll land on the Dashboard, which shows your content stats, PageSpeed score, SEO readiness, and recent activity.
1. Set your site name and branding. Head to Settings and configure your site name, logo, and favicon. These appear in the admin sidebar and can be used in your site templates.
2. Build your first page. Click + Page from the Dashboard quick actions. Give it a title, write some content, and hit Publish. Visit your site to see it live.
3. Set up collections. If your site needs structured content (team members, services, resources, locations), create a Collection from Content > Manage Content. Add your entry fields, design your cards, and start adding entries.
4. Configure SEO. SearchLab will score every page you publish and give you actionable recommendations. Connect Google Search Console in SearchLab > Settings to unlock CTR gap analysis and position tracking.
The orange button in the top-right corner of the admin opens the Toolbox panel. It has three tabs:
If you're migrating from WordPress, use the built-in importer at Content > Import. It handles WP XML exports and automatically maps post types to collections, preserving field keys and taxonomy. Multiple content types can be mapped and imported in a single pass.
LiteFrame is yours. If you ever want to leave, export your entire site as a static HTML package from Settings > Export. You get clean HTML, CSS, and images that work on any hosting provider.
Standard content pages, blog posts, and landing pages.
| Mode | Purpose | URL Pattern |
|---|---|---|
standard | Regular site pages | /page-slug |
blog | Blog posts | /blog/post-slug |
landing | Landing pages (no nav/footer) | /page-slug |
seo | SEO location pages | /page-slug |
| collection slug | Collection entries | /prefix/entry-slug |
Each page can use one of these templates, configured in Code > Templates:
Owners can lock individual pages to prevent editor-role users from modifying them. The lock toggle appears in the editor controls bar. Locked pages show a padlock icon for editors and reject save attempts at the server level.
The visual editor is a diff-based overlay that loads the live page in an iframe. Click any editable element (headings, paragraphs, images, links, buttons) to edit it in place. Changes are tracked and applied back to the source HTML on save without serializing the iframe DOM, so shortcodes, scripts, and whitespace are preserved. Template regions and shortcode blocks are greyed out and non-editable.
Content is edited in the admin editor and saved via AJAX. HTML content is base64 encoded before transmission (ModSecurity compliance), then decoded and stored in the pages.content column.
Structured content types with custom fields, templates, and taxonomy.
Collections are custom content types. A "Resources" collection might have fields for category, read time, and a body. A "Team Members" collection might have fields for job title, photo, and bio. Each collection gets its own index page, entry pages, category/tag taxonomy, and card templates.
Navigate to Content > Manage Content and click + New Collection. Give it a name, slug, and URL prefix. The slug determines the page_mode value for entries and the URL prefix determines the public URL path.
Each collection has the following tabs:
The Features tab controls what panels appear in the entry editor and what functionality is available:
Categories and tags are managed in the Taxonomy tab. Each category/tag gets a slug used for archive URLs (/prefix/?cat=slug). Entries can be assigned categories and tags in the entry editor.
Each collection has its own API mode, configurable in the Features tab. Four modes are available:
| Mode | Description | Best For |
|---|---|---|
| Off | API disabled for this collection | - |
| Data Only | Raw JSON with field values, categories, and metadata | React, Next.js, mobile apps |
| Rendered HTML | Pre-rendered HTML fragments using your card and entry templates | Embedding content into other sites |
| Data + Design Tokens | Raw JSON plus your style settings as a separate object | Design system sync, Figma-to-code |
Define the data structure for your collection entries.
Entry fields are the first sub-tab inside Content Templates. Each field you define becomes an input in the entry editor and a {{token}} available in your card, index, and entry page templates. Fields are stored as JSON in engine_collections.fields_json.
| Type | Description | Token Output |
|---|---|---|
text | Single-line text input | Plain text, HTML-escaped |
textarea | Multi-line text | Text with line breaks preserved |
html | Raw HTML content | Unescaped HTML |
wysiwyg | Visual rich text editor (TipTap) | Unescaped HTML |
image | Image URL (opens media picker) | URL string |
gallery | Multiple image URLs | JSON array of URLs |
select | Dropdown with predefined options | Selected value |
checkbox | Boolean toggle | 1 or empty |
number | Numeric input | Number |
url | URL input | URL string |
email | Email address | Email string |
phone | Phone number | Phone string |
date | Date picker | Date string |
color | Color picker | Hex color |
group | Repeater group with sub-fields | Loop syntax required |
reference | Link to another collection entry | Referenced entry data |
Each field has these configurable properties:
{{key}} token and JSON storageselect type: comma-separated list of choicesThe special _section type adds a visual heading divider in the entry editor. It creates no token and stores no data. Use it to organize long field lists into logical groups.
The group type creates a repeater: users can add multiple rows of sub-fields. Each sub-field has its own key and type. In templates, use the loop syntax:
HTML{{#team_members}}
<div class="member">
<h3>{{name}}</h3>
<p>{{role}}</p>
<img src="{{photo}}" alt="{{name}}">
</div>
{{/team_members}}
Fields are stored as a JSON array. Each field object follows this structure:
JSON{
"label": "Job Title",
"key": "job_title",
"type": "text",
"required": false,
"placeholder": "e.g. Senior Developer",
"options": "",
"fields": []
}
For group type fields, the fields array contains sub-field objects with the same structure (minus nested groups).
These tokens are always available regardless of your field schema:
{{title}}Entry title{{url}}Full URL path{{slug}}URL slug{{id}}Entry ID{{featured_image}}Featured image URL{{excerpt}}Excerpt text{{content}}Body content (HTML){{body}}Alias for content{{author}}Author name{{date}}Published date{{categories}}Comma-separated names{{category_links}}Linked category names{{read_time}}Estimated read timeHow each entry looks in listings.
Three built-in presets are available to get started quickly. Each provides a complete card design with image, title, excerpt, date, and hover effects:
| Preset | Description |
|---|---|
| Shadowed | White card with subtle shadow, rounded corners, image on top |
| Minimal | No border or shadow; clean typography-first layout |
| Bordered | Light border with no shadow; structured, editorial feel |
New collections default to the Shadowed preset. Existing collections with no saved template get a runtime fallback using the same Shadowed layout.
Select "Custom" to write your own card template using HTML, CSS, and tokens. The card template renders once per entry in any listing context (index page, shortcode embeds, category archives).
HTML<a href="{{url}}" class="my-card">
<img src="{{featured_image}}" alt="{{title}}">
<div class="my-card-body">
<span class="my-card-cat">{{categories}}</span>
<h3>{{title}}</h3>
<p>{{excerpt}}</p>
</div>
</a>
An optional second card template used when embedding a collection via shortcode with card="embed". If empty, the main card template is used everywhere. This lets you have a full card on the index page and a compact card when embedded on other pages.
All built-in tokens ({{title}}, {{url}}, {{featured_image}}, {{excerpt}}, {{date}}, {{author}}, {{categories}}, {{category_links}}, {{read_time}}) plus any custom entry field keys are available in card templates.
The listing page showing all entries in a collection.
The Index Page is the third sub-tab inside Content Templates. It controls the main listing page at /prefix/ showing all entries in a configurable grid. Category and tag filtered pages (/prefix/?cat=slug) inherit these settings.
Three controls define the entry grid:
The grid section wraps the entry cards. Controls include vertical/horizontal padding and background color. These apply to the section container that holds the grid.
An optional header above the grid. Two modes:
When enabled, filter buttons appear above the grid. Only renders if categories exist for the collection. Fully stylable:
The full page view for individual collection entries.
The entry page is built from two zones. The Hero section always spans the full width of the container and contains the featured image, title, and metadata (date, author, categories). The Content section sits below it and holds the body text with an optional sidebar.
Choose between two approaches:
Five hero configurations are available:
| Layout | Description |
|---|---|
| Full Width Image | Image spans the container above the title and metadata |
| Image Left | Image on the left, title and metadata on the right |
| Image Right | Title and metadata on the left, image on the right |
| Title Overlay | Title and metadata overlaid on the featured image |
| No Image | Title and metadata only, no featured image |
Hero spacing is fully configurable: padding top/bottom, margin top/bottom, image max height, image border radius, and column gap (for split layouts).
The content section supports three layout options:
The sidebar aligns with the body text, not the hero. It sits below the hero zone.
Fine-grained control over visual appearance:
When a sidebar layout is selected, toggle these auto-generated widgets:
Sidebar width is adjustable (200-480px).
Switch to Custom Template mode for full HTML/CSS/JS control. All entry tokens are available. The custom template replaces both the hero and content zones entirely.
single_template_html render a proper default layout with title, date/author metadata, category links, featured image, and body content. The default template respects which features are enabled for the collection.Embed collections and content anywhere.
The main shortcode for embedding collection entries. Both and are accepted for backward compatibility.
Shortcode
| Attribute | Description | Default |
|---|---|---|
slug | Collection slug (required) | - |
limit | Max entries to show | All |
columns | Grid columns (1-6) | 3 |
layout | grid to force grid wrapper | - |
category | Filter by category slug | - |
tag | Filter by tag slug | - |
filters | true to show category filter buttons | false |
style | links, compact, or bullets | - |
card | embed to use embed card template | - |
show_date | false to hide dates | true |
show_image | false to hide images | true |
show_excerpt | false to hide excerpts | true |
show_button | true to add CTA button | false |
button_text | Button label | Learn More |
icon_field | Field key to use as icon | - |
| Style | Description |
|---|---|
links | Title + date list, no images. Good for sidebar navigation. |
compact | Tiny thumbnail + title. Good for related content widgets. |
bullets | Bullet-point linked titles only. Good for simple lists. |
Embed a gallery created in the Media Library:
Shortcode
Supports layout (grid, masonry, justified, slider), columns, gap, and per_page attribute overrides.
Embed a form:
Shortcode
Build layouts with HTML and token syntax.
Tokens use double curly braces: {{token_name}}. They are replaced with real data at render time. No PHP, no template engine.
HTML<h1>{{title}}</h1>
<img src="{{featured_image}}" alt="{{title}}">
HTML{{#team_members}}
<div class="member">
<h3>{{name}}</h3>
<p>{{role}}</p>
</div>
{{/team_members}}
Render content only when a field has a value:
HTML{{?subtitle}}
<p class="subtitle">{{subtitle}}</p>
{{/subtitle}}
{{title}}Entry title{{url}}Full URL path{{slug}}URL slug{{id}}Entry ID{{featured_image}}Featured image URL{{excerpt}}Excerpt text{{content}}Body content (HTML){{body}}Alias for content{{author}}Author name{{date}}Published date{{categories}}Comma-separated names{{category_links}}Linked category names{{read_time}}Estimated read timeAny custom field key is automatically available as a token. If you have a field with key job_title, use {{job_title}} in your template.
These work in the Custom layout template for index pages:
{{items}}All entries through card template{{filters}}Category filter buttons{{featured:N}}First N entries through hero template{{items_after:N}}Entries after position N{{collection_name}}Collection display nameGlobal values configured in Settings. Use the token. prefix:
HTML<p>Call us at </p>
<a href="">Book Now</a>
Change the value once in Settings and it updates everywhere the token appears.
Manage images, files, and image galleries.
Upload images, documents, and files through the Media Library. Supported formats: JPG, PNG, WebP, GIF, SVG, PDF, MP4, and MP3. Multiple file upload is supported via drag-and-drop or the file picker. Files are searchable by name.
On upload, images are automatically processed based on your Settings:
media_quality setting.Click any image in the library to open it in the preview panel. From there you can:
Bulk delete is available by selecting multiple files and clicking Delete Selected.
The media picker modal appears wherever an image field is used (page editor, collection fields, settings). It offers four tabs:
The Galleries tab lets you create named image galleries. Each gallery has a name, slug, layout, and a sortable list of images with optional captions.
| Layout | Description |
|---|---|
grid | CSS Grid with configurable columns and gap |
masonry | CSS columns-based masonry layout |
justified | Flexbox rows with images stretched to fill width |
slider | Horizontal scroll with snap points, touch-friendly |
Galleries are embedded via shortcode: . Shortcode attributes override the saved gallery settings. Galleries support pagination with a configurable per-page count.
Within a gallery, images can be reordered via drag-and-drop. Add images from the Media Library or by URL. Each image can have a caption.
Built-in SEO intelligence suite.
The SearchLab dashboard provides a site-wide overview: aggregate SEO scores, keyword chart, and actionable summaries highlighting pages that need attention.
Site Health scores every published page on SEO readiness with a checklist of actionable recommendations. Rank Readiness provides a site-wide average score and per-page breakdown.
Powered by DataForSEO:
Track keywords per page with color-coded ranking display. Positions are automatically checked on every GSC sync using SERP cache (12-hour TTL). Position history accumulates over time for trend analysis.
Identifies pages ranking on page 1 of Google with below-average click-through rates. These are your highest-leverage optimization opportunities.
The AI recommendation engine analyzes each page using all available data: SEO score, failed checks, GSC queries, tracked keyword positions, SERP features, cached competitor data, PAA questions, recent change history, and content preview. Generates 5 prioritized recommendations with data-backed reasoning. Recommendations are cached for 48 hours and appear in the page editor.
Every page save snapshots SEO-relevant fields. Changes are auto-classified (keyword change, meta update, content update, schema update). The impact measurement system compares 14-day windows before and after changes to show impressions, clicks, position, and CTR deltas.
Configure in SearchLab > Settings:
Tracks how AI platforms (ChatGPT, Perplexity, Gemini, etc.) reference your content. Monitors LLM mentions and citation patterns.
AI-powered content and development assistant.
BuildLab is an AI assistant built into the admin panel, powered by the Anthropic API. It includes multiple tools:
Token usage is tracked per-site and visible in the BuildLab interface.
Build and manage contact forms.
The form builder uses a visual layout with a dark icon rail on the left, field configuration in the middle, and a live preview canvas on the right. Drag fields to reorder, click to configure.
Forms are embedded via shortcode:
Shortcode
Submissions go to the Forms > Entries tab and can be emailed to configured recipients.
Locked-down editing for client-managed sites.
When a site runs in hosted_secure mode, the template HTML is locked. Users cannot access the code editor or modify template markup. Instead, they edit through a schema-driven field UI. The developer controls the design; the client controls the content.
The system has three layers:
data/templates/ as plain HTML files with {{token}} syntaxsecure_templates database table as JSON, defining what fields the user seespages.content, with each key matching a field from the schemaWhen a page is rendered, the template file is loaded, the field data is queried, and tokens are replaced. Output is cached with ETag support for efficient delivery.
Accessed at /admin/templates (owner-only). Create templates with a slug, label, and description. Each template gets an HTML file and a field schema.
Write your HTML layout with tokens for every editable region:
HTML<section class="hero">
<div class="container">
<h1>{{headline}}</h1>
{{?subheadline}}
<p class="sub">{{subheadline}}</p>
{{/subheadline}}
<img src="{{hero_image}}" alt="{{headline}}">
</div>
</section>
{{#features}}
<div class="feature">
<h3>{{title}}</h3>
<p>{{description}}</p>
</div>
{{/features}}
| Syntax | Purpose |
|---|---|
{{field_key}} | Simple replacement. Text fields are HTML-escaped; HTML/WYSIWYG fields are not. |
{{#repeater}}...{{/repeater}} | Repeater loop. Iterates over each row in a group field. |
{{?field_key}}...{{/field_key}} | Conditional. Block is rendered only if the field has a non-empty value. |
{{title}}, {{slug}}, etc. | Built-in page tokens. Always available regardless of schema. |
Define what fields users see in the editor. Uses the same field types as collection entry fields (text, textarea, html, wysiwyg, image, select, checkbox, number, date, group). The schema is edited as JSON in the template manager.
Rendered pages are cached in the secure_cache table. Cache is invalidated when a page is published or when the template itself is saved. ETag headers enable browser-side caching with 304 responses.
Templates can be locked to prevent accidental edits. Locked templates show a lock icon in the list and require an explicit unlock before editing.
REST API for external integrations.
LiteFrame exposes a REST API through api.php. Collection entries can be accessed when an API mode is enabled for the collection (in Features > API / Headless).
HTTPGET /api.php?collection=resources&limit=10
GET /api.php?collection=resources&category=guides
GET /api.php?collection=resources&id=42
| Mode | Response Content |
|---|---|
json | Raw JSON: field values, categories, metadata. No HTML rendering. |
rendered | Pre-rendered HTML fragments using your card and entry templates. Drop into any page with fetch. |
design | JSON data plus your style settings (card_styles, page_styles, template_css) as a separate design object. |
All responses are JSON. Entry data includes all custom fields, built-in fields (title, slug, excerpt, featured_image), taxonomy assignments, and metadata (dates, author, status).