gemvc / stcms
A lightweight, static-like PHP website with clean architecture and multi-language support.
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
Language:Twig
Requires
- php: >=8.0
- guzzlehttp/guzzle: ^7.0
- symfony/cache: ^7.0
- symfony/console: ^7.0
- symfony/dotenv: ^7.0
- symfony/filesystem: ^7.0
- twig/twig: ^3.0
Suggests
- ext-apcu: Allows use of APCu for in-memory caching (recommended for best performance)
README
A Composer-installable PHP library for building modern, component-based frontends for GEMVC (or any API backend), using Twig for server-side templates and React (via Vite) for interactive UI components.
Features
- π Hybrid Rendering: Twig for server-side, React for interactive components
- π API Integration: Fetch data from GEMVC or any API using Guzzle
- β‘ Modern Caching: Symfony Cache (APCu/file)
- π οΈ CLI Project Init: Scaffold new projects with
vendor/gemvc/stcms/bin/stcms init
- π¨ Component-based UI: React components in
/assets/js/components/
, bundled with Vite - ποΈ Multi-language Support: Easily add new languages
- π Config via .env: Symfony Dotenv for environment config
- π§© Extensible: Easy for both PHP and frontend devs
- π‘οΈ Security: Apache security headers and file protection
- π¦ Standardized Setup: Consistent project initialization
Quick Start
1. Install via Composer
composer require gemvc/stcms
2. Initialize a New Project
php vendor/gemvc/stcms/bin/stcms init
3. Build Frontend Assets (React via Vite)
npm install npx vite build
4. Configure Environment
Edit .env
for API base URL, cache, etc.
5. Test if CMS successfully installed
php -S localhost:8000
6. Start Developing
- Pages in
/pages/
(real user-facing pages) - Templates in
/templates/
(layouts, partials, reusable Twig blocks) - React components in
/assets/js/components/
- API calls via Guzzle in PHP
Project Structure
/
βββ src/ # PHP library code
β βββ Core/ # Core classes (Application, Router, etc.)
β β βββ Application.php # Main application orchestrator
β β βββ Router.php # URL routing and request handling
β β βββ Request.php # HTTP request encapsulation
β β βββ Response.php # HTTP response handling
β β βββ TemplateEngine.php # Twig template rendering
β β βββ ApiClient.php # HTTP API communication
β βββ Command/ # CLI commands
β βββ setup/ # Template files for project initialization
βββ pages/ # Real user-facing pages (Twig)
βββ templates/ # Twig layouts, partials, and reusable templates
βββ assets/
β βββ js/
β β βββ components/ # React components (JSX)
β β βββ app.jsx # Main React entry
β βββ css/ # CSS (optional, Tailwind via CDN or Vite)
βββ public/
β βββ assets/js/ # Vite build output
βββ .env # Config
βββ .htaccess # Apache configuration with security headers
βββ index.php # Main entry point
βββ vite.config.js # Vite config
βββ package.json # Frontend dependencies
βββ composer.json # Composer config
βββ bin/stcms # CLI entry point
Core PHP Classes
Application.php
Main application orchestrator that manages sessions, JWT authentication, and coordinates all components.
Router.php
URL routing with support for exact matches, dynamic routes (/user/{id}
), and automatic template rendering.
TemplateEngine.php
Twig integration with custom functions:
asset()
- Generate asset URLsroute()
- Generate route URLsjson_encode()
- JSON encoding helperis_authenticated()
- Authentication check
ApiClient.php
HTTP API communication using Guzzle with JWT authentication support.
How It Works
- Twig renders main pages from
/pages/
; React components are mounted where needed - Reusable layouts/partials in
/templates/
- API data fetched via Guzzle (with Symfony Cache)
- Frontend devs build React components in
/assets/js/components/
- Vite bundles JS for use in templates/pages
- Config and cache are environment-driven
Example: Hybrid Rendering
Twig page (in /pages/
):
{% extends 'layout.twig' %} {% block content %} <div id="user-profile-root" data-user="{{ user|json_encode }}" {% if jwt %}data-jwt="{{ jwt }}"{% endif %}></div> {% endblock %} <script src="{{ asset('js/app.js') }}"></script>
React entry (app.jsx):
import React from 'react'; import { createRoot } from 'react-dom/client'; import UserProfile from './components/UserProfile'; const el = document.getElementById('user-profile-root'); if (el) { const user = JSON.parse(el.dataset.user); const jwt = el.dataset.jwt; // Only present if authenticated createRoot(el).render(<UserProfile user={user} jwt={jwt} />); }
Authentication Flow & Security
- JWT is only exposed to React if the user is authenticated (JWT is present in PHP session).
- If not authenticated, no JWT is exposedβReact knows to show login or restrict access.
- React components use the JWT for API requests (e.g., via Axios/fetch, in Authorization header).
- JWT is never generated or verified in the frontendβall JWT logic is handled by the backend (GEMVC API).
- Session management and login/logout handled by PHP backend.
- Best practice: Always validate JWTs on the backend for every API request.
Setup Folder Structure
The src/setup/
folder contains all template files that get copied during project initialization:
src/setup/
βββ .gitignore # Git ignore patterns
βββ .htaccess # Apache configuration with security headers
βββ index.php # Main entry point
βββ env.template # Environment configuration template
βββ vite.config.js # Vite build configuration
βββ package.json # Frontend dependencies
βββ templates/ # Layouts, partials, reusable Twig blocks
β βββ example.twig # Example template
βββ pages/ # Real user-facing pages (Twig)
β βββ index.twig # Example landing page
βββ assets/js/
βββ app.jsx # React entry point
βββ components/
βββ UserProfile.jsx # Example React component
Benefits
- β Clean separation of backend, pages, templates, and frontend components
- β Easy for both PHP and React developers
- β Fast, SEO-friendly, and interactive
- β Works on most hosting (APCu/file cache)
- β Extensible and maintainable
- β Standardized project initialization
- β Security headers and file protection
- β Modern development workflow
For PHP Developers
- Use
/pages/
for real pages,/templates/
for layouts/partials - Fetch API data with Guzzle (and cache it)
- Pass data to React components via JSON in the DOM
- Expose JWT to React only if authenticated
- Use the Router for custom route handling
For React Developers
- Build components in
/assets/js/components/
- Use Vite for fast dev/build
- Mount components anywhere in Twig pages/templates
- Use JWT (if present) for authenticated API requests
- Leverage the asset() function for static file URLs
CLI Commands
Initialize Project
vendor/bin/stcms init
Creates a new project with all necessary files and folder structure.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly
- Submit a pull request
License
MIT
Support
- Documentation:
/en/docs
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Changelog
Version 1.0.0
- Initial release with complete PHP framework
- Core classes: Application, Router, Request, Response, TemplateEngine, ApiClient
- CLI project initialization
- Hybrid Twig/React rendering
- Security headers and file protection
- Standardized setup folder structure
- Beautiful landing page template
- Comprehensive .gitignore patterns
STCMS - Making hybrid PHP/React development simple and powerful! π