# php-static-site-generator **Repository Path**: wfdaj/php-static-site-generator ## Basic Information - **Project Name**: php-static-site-generator - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-10-09 - **Last Updated**: 2025-10-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # PHPSSG (Personal Home Page Static Site Generator) A **lightweight, PHP-native static site generator** for building **composable templates**. PHPSSG uses **invokable component classes**, **output buffering**, and **plain PHP templates** to provide a clean developer experience — no third-party templating engine required, but you are welcome to use one. --- ## Features - **Plain PHP templates** – no special syntax to learn. - **Invokable components** – use components like `$header()`. - **Centralized render helper** – avoids repeated `ob_start()` / `ob_get_clean()`. - **Nesting & composition** – layouts can include multiple components. - **Slots & data passing** – inject content into templates easily. - **Incremental builds** – files are rewritten only if content changes (MD5 hash comparison). - **Native debugging** – works seamlessly with standard PHP tools. - **PSR-4 compliant** – fully autoloadable via Composer. - **Interfaces** – `Renderable`, `Composable`, `Buildable` help define component APIs. - **IDE-friendly** – docblocks provide autocomplete, type hints, and method signatures. - **Highly portable** – works in any PHP 8.1+ environment. - **Flexible structure** – pages, components, and presenters can each be **Buildable**, **Composable**, or **Renderable** depending on your project. --- ## Requirements - PHP 8.1+ (typed properties & short closures recommended) - Composer (for autoloading) --- ## Installation Install via Composer: ```bash composer require taujor/phpssg ``` Run a local development server: ```bash php -S localhost:8080 public/index.html ``` --- ## Usage In these examples all data comes from trusted developer sources, you. Consider escaping if you bring data in from untrusted sources. In any template you create. ### Layouts Layouts are typically **Renderables**: ```php use Taujor\PHPSSG\Contracts\Renderable; class Base extends Renderable { public function __invoke(string $content): string { return $this->render("layouts/base.php", ["content" => $content]); } } ``` ### Components Components are typically **Renderables** (like layouts) or **Composables** : ```php use Taujor\PHPSSG\Contracts\Composable; class Heading extends Composable { function __construct(private Title $title, private Subtitle $subtitle) {} function __invoke(): string { return ($this->title)() . ($this->subtitle)(); } } ``` `Title` and `Subtitle` are **Renderables** (in this example) they have their own respective template files, however our `Heading` class simply takes these two templates and "composes" them into a new component (via string concatenation in this case). Hence it does not require its own template file and can be invoked just the same as any other presenter. ```php Document ``` - `render()` extracts variables into the template and returns the output as a string. --- ### Pages Pages are typically **Buildables**, like **Composables** they are self-contained, and do not need separate view templates. They gain the ability to use the `compile` and `build` methods which output html files to the `public` directory: ```php use Taujor\PHPSSG\Contracts\Buildable; class Post extends Buildable { public function __construct(private Base $base, private Title $title, private Body $body) {} public function __invoke(object $data): string { return ($this->base)( ($this->title)($data->title) . ($this->body)($data->content) ); } } ``` Pages often combine components and layouts. `$data` is passed to the page during the build process. `$data` is then passed to components via `__invoke()`. Layouts wrap the combined HTML content. ### Utilities Utilities are typically helper classes that provide additional functionality to phpssg. They will become more useful in the near future once hooks are released. ```php \s+<', $html); // Collapse multiple spaces $html = preg_replace('/\s+/', ' ', $html); // Remove comments (except IE conditionals) $html = preg_replace('//', '', $html); return trim($html); } } ``` This utility class can be used to minify html strings, it's currently already in use in the core build & compile methods. Soon I plan to create hooks that allow you to easily write and include your own utilities in the build process. These are my recommendations. However, any **component, page, or presenter** can also extend any of the abstract classes: **Buildable**, **Composable**, **Renderable**. Depending on your specific use case for phpssg or programming style. --- ### Views - Stored in **`src/views/`** (mandatory directory). - Only **Renderables** have view templates. **Composables** and **Buildables** don't require view templates. - Views are plain php templates I recommend their directory structure mirrors that of `presenters/`: ```text src/ └── views/ ├── components/ │ └── title.php └── layouts/ └── base.php ``` - The `render()` method in **Renderable** extracts variables into the template and captures the output. - **No escaping is necessary** — all data comes from trusted sources. --- ### Build scripts This is the entry point of the application often placed in the `scripts` directory at the root of your project. They call on **Buildable** presenters to generate html. For example: ```php 1, 'slug' => 'first-post', 'title' => 'First Post', 'content' => 'Hello' ], (object) [ 'id' => 2, 'slug' => 'second-post', 'title' => 'Second Post', 'content' => 'World' ], ]; Post::build("/posts/post-{{id}}.html", $data); Post::compile("/posts/post-3.html", (object)[ 'id' => 3, 'slug' => 'third-post', 'title' => 'Third Post', 'content' => 'Hello Again' ]); ``` ## Compile and Bulid methods ```php // Compile a single page // 1. target output path relative to the public directory (with optional placeholder syntax) // 2. data to pass to the page, can be an object or associative array based on what your component expects to handle2 Post::compile("/posts/post1.html", (object)[ "id" => 1, "slug" => "first-post", "title" => "First Post", "content" => "Hello" ]); $dataset = [ (object) [ 'id' => 2, 'slug' => 'second-post', 'title' => 'Second Post', 'content' => 'World' ], (object) [ 'id' => 3, 'slug' => 'third-post', 'title' => 'Third Post', 'content' => 'Hello Again' ], ]; // Build multiple pages using placeholder syntax (on the first iteration the path would be `public/posts/first-post.html`) Post::build("/posts/{{slug}}.html", $dataset); ``` - `compile(string $pattern, array|object $data = [])` writes a single file. - `build(string $pattern, iterable $dataset)` writes multiple files iteratively. **Placeholders** use the syntax `{{key}}` in the file path or filename: ```php "/posts/{{slug}}.html" ``` Each `{{key}}` is replaced with the corresponding key from the dataset item (array or object). Incremental builds ensure that files are only rewritten if content changes. Full caching support is in development. --- ### Minimal Required Directories The only **mandatory directories** for a PHPSSG project are: 1. `public/` – the web-facing build directory. 2. `src/views/` – root directory for all templates. 3. `cache/` – application cache directory that is automatically created as needed. Everything else (`scripts/`, `presenters/`, `presenters/components/`, `presenters/layouts/`, `presenters/pages/`, `utilities/`, `views/components`, `views/layouts` etc.) is optional, depending on how you structure your project. --- ### Suggested Project Structure - **`config/`** – bootstrap and environment setup. - **`public/`** – compiled HTML, CSS, JS; web-facing assets. - **`scripts/`** – development/build scripts. - **`presenters/`** – invokable PHP classes for logic (can be Buildable, Composable, or Renderable). - **`presenters/components/`** – reusable UI blocks typically Renderables or Composables. - **`presenters/layouts/`** – reusable page skeletons typically Renderables. - **`presenters/pages/`** – page-level composables or buildables. - **`views/components/`** – templates for Renderable components. - **`views/layout/`** – templates for Renderable layouts. - **`utilities/`** – helpers like `Minify`, `TwigRenderer`, `PrettyPrint`. Make them do anything! This structure ensures: - **Separation of logic vs markup** - **Composable, testable components** - **Safe public directory exposure** - **Maintainability and clarity** --- ## Contributing Contributions are welcome! Philosophy: - **Minimalism First** – lightweight and simple, avoid heavy libraries. - **Developer-Friendly** – components should be easy to understand and compose. - **Consistency** – follow `presenters/`, `views/`, `utilities/` structure. - **Backward Compatibility** – avoid breaking APIs unless clearly beneficial. --- ## Planned Features - [ ] **Packagist Release** - use composer to install phpssg with ease. - [ ] **Caching** – reduce build times for large projects. - [ ] **Hooks** - add extensibility to the build process. - [ ] **Documentation** – phpssg.com for guides and community resources. - [ ] **Templates** – premade templates to start projects quickly. - [ ] **Tutorials** – step-by-step guides on using PHPSSG effectively.