update template defaults

This commit is contained in:
Snider 2026-01-26 20:39:56 +00:00
parent 735153a804
commit f066becf0a
19 changed files with 798 additions and 10 deletions

24
.editorconfig Normal file
View file

@ -0,0 +1,24 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[*.{js,jsx,ts,tsx,vue}]
indent_size = 2
[*.json]
indent_size = 2
[docker-compose.yml]
indent_size = 2

12
.gemini/settings.json Normal file
View file

@ -0,0 +1,12 @@
{
"$schema": "https://schema.gemini.google.dev/settings.json",
"codeAssist": {
"enabled": true,
"contextFiles": [
"GEMINI.md",
"CLAUDE.md",
"composer.json",
"config/core.php"
]
}
}

4
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,4 @@
# GitHub Sponsors configuration
# Support Trees for the Future through our fundraiser
custom: ["https://donate.trees.org/-/NPMMSVUP?member=SWZTDDWH"]

83
.github/copilot-instructions.md vendored Normal file
View file

@ -0,0 +1,83 @@
# GitHub Copilot Instructions
## Project Overview
This is a Laravel application using the Core PHP Framework - a modular monolith architecture with event-driven module registration.
## Architecture
### Module System
- Modules live in `app/Mod/{ModuleName}/`
- Each module has a `Boot.php` class with event listeners
- Events: `WebRoutesRegistering`, `ApiRoutesRegistering`, `AdminPanelBooting`
### Example Boot.php
```php
<?php
namespace App\Mod\Blog;
use Core\Events\WebRoutesRegistering;
use Core\Events\ApiRoutesRegistering;
class Boot
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
ApiRoutesRegistering::class => 'onApiRoutes',
];
public function onWebRoutes(WebRoutesRegistering $event): void
{
$event->routes(fn() => require __DIR__.'/Routes/web.php');
$event->views('blog', __DIR__.'/Views');
}
}
```
## Coding Standards
### Language
- Use UK English (colour, organisation, centre, behaviour)
- No American spellings (color, organization, center, behavior)
### PHP Style
- PSR-12 with Laravel conventions
- Strict types: `declare(strict_types=1);`
- Type hints on all parameters and return types
- Final classes by default unless inheritance is intended
### Naming
- Models: singular PascalCase (`Post`, `Comment`)
- Tables: plural snake_case (`posts`, `comments`)
- Controllers: `{Model}Controller`
- Livewire: `{Feature}Page`, `{Feature}Modal`
### Testing
- Use Pest, not PHPUnit directly
- Feature tests for HTTP/Livewire
- Unit tests for services/utilities
## UI Framework
- **Livewire 3** for reactive components
- **Flux Pro** for UI components (not vanilla Alpine)
- **Tailwind CSS** for styling
- **Font Awesome Pro** for icons (not Heroicons)
## Key Packages
| Package | Purpose |
|---------|---------|
| `host-uk/core` | Core framework, events, modules |
| `host-uk/core-admin` | Admin panel, modals |
| `host-uk/core-api` | REST API, rate limiting |
| `host-uk/core-mcp` | AI agent tools (MCP) |
## Don't
- Don't use Heroicons (use Font Awesome Pro)
- Don't use vanilla Alpine components (use Flux Pro)
- Don't create controllers for Livewire pages
- Don't use American English spellings
- Don't add unnecessary abstractions

29
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,29 @@
version: 2
updates:
- package-ecosystem: composer
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
- php
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
labels:
- dependencies
- javascript
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
open-pull-requests-limit: 3
labels:
- dependencies
- ci

62
.github/package-workflows/README.md vendored Normal file
View file

@ -0,0 +1,62 @@
# Package Workflows
These workflow templates are for **library packages** (host-uk/core, host-uk/core-api, etc.), not application projects.
## README Badges
Add these badges to your package README (replace `{package}` with your package name):
```markdown
[![CI](https://github.com/host-uk/{package}/actions/workflows/ci.yml/badge.svg)](https://github.com/host-uk/{package}/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/host-uk/{package}/graph/badge.svg)](https://codecov.io/gh/host-uk/{package})
[![Latest Version](https://img.shields.io/packagist/v/host-uk/{package})](https://packagist.org/packages/host-uk/{package})
[![PHP Version](https://img.shields.io/packagist/php-v/host-uk/{package})](https://packagist.org/packages/host-uk/{package})
[![License](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE)
```
## Usage
Copy the relevant workflows to your library's `.github/workflows/` directory:
```bash
# In your library repo
mkdir -p .github/workflows
cp path/to/core-template/.github/package-workflows/ci.yml .github/workflows/
cp path/to/core-template/.github/package-workflows/release.yml .github/workflows/
```
## Workflows
### ci.yml
- Runs on push/PR to main
- Tests against PHP 8.2, 8.3, 8.4
- Tests against Laravel 11 and 12
- Runs Pint linting
- Runs Pest tests
### release.yml
- Triggers on version tags (v*)
- Generates changelog using git-cliff
- Creates GitHub release
## Requirements
For these workflows to work, your package needs:
1. **cliff.toml** - Copy from core-template root
2. **Pest configured** - `composer require pestphp/pest --dev`
3. **Pint configured** - `composer require laravel/pint --dev`
4. **CODECOV_TOKEN** - Add to repo secrets for coverage uploads
5. **FUNDING.yml** - Copy `.github/FUNDING.yml` for sponsor button
## Recommended composer.json scripts
```json
{
"scripts": {
"lint": "pint",
"test": "pest",
"test:coverage": "pest --coverage"
}
}
```

55
.github/package-workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,55 @@
# CI workflow for library packages (host-uk/core-*, etc.)
# Copy this to .github/workflows/ci.yml in library repos
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: [8.2, 8.3, 8.4]
laravel: [11.*, 12.*]
exclude:
- php: 8.2
laravel: 12.*
name: PHP ${{ matrix.php }} / Laravel ${{ matrix.laravel }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite
coverage: pcov
- name: Install dependencies
run: |
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer update --prefer-dist --no-interaction --no-progress
- name: Run Pint
run: vendor/bin/pint --test
- name: Run tests
run: vendor/bin/pest --ci --coverage --coverage-clover coverage.xml
- name: Upload coverage to Codecov
if: matrix.php == '8.3' && matrix.laravel == '12.*'
uses: codecov/codecov-action@v4
with:
files: coverage.xml
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}

40
.github/package-workflows/release.yml vendored Normal file
View file

@ -0,0 +1,40 @@
# Release workflow for library packages
# Copy this to .github/workflows/release.yml in library repos
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
name: Create Release
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
uses: orhun/git-cliff-action@v3
with:
config: cliff.toml
args: --latest --strip header
env:
OUTPUT: CHANGELOG.md
- name: Create release
uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

66
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,66 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
tests:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: [8.2, 8.3, 8.4]
name: PHP ${{ matrix.php }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite
coverage: pcov
- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-progress
- name: Run Pint
run: vendor/bin/pint --test
- name: Run tests
run: vendor/bin/pest --ci --coverage --coverage-clover coverage.xml
- name: Upload coverage to Codecov
if: matrix.php == '8.3'
uses: codecov/codecov-action@v4
with:
files: coverage.xml
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
assets:
runs-on: ubuntu-latest
name: Assets
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Build assets
run: npm run build

37
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,37 @@
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
name: Create Release
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
id: changelog
uses: orhun/git-cliff-action@v3
with:
config: cliff.toml
args: --latest --strip header
env:
OUTPUT: CHANGELOG.md
- name: Create release
uses: softprops/action-gh-release@v2
with:
body_path: CHANGELOG.md
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.DS_Store
/.phpunit.cache
/node_modules
/public/build

124
AGENTS.md Normal file
View file

@ -0,0 +1,124 @@
# AI Agent Instructions
> For Jules, Devin, and other autonomous coding agents.
## Quick Start
1. This is a Laravel 12 + Livewire 3 application
2. Modules go in `app/Mod/{Name}/Boot.php`
3. Use UK English (colour, not color)
4. Run `vendor/bin/pint --dirty` before committing
5. Run `vendor/bin/pest` to test
## Architecture
**Modular monolith** - Features are self-contained modules that register via events.
### Creating a Module
```bash
php artisan make:mod {Name} --all
```
Or manually create `app/Mod/{Name}/Boot.php`:
```php
<?php
declare(strict_types=1);
namespace App\Mod\{Name};
use Core\Events\WebRoutesRegistering;
class Boot
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
];
public function onWebRoutes(WebRoutesRegistering $event): void
{
$event->routes(fn() => require __DIR__.'/Routes/web.php');
$event->views('{name}', __DIR__.'/Views');
}
}
```
## Task Checklist
When implementing features:
- [ ] Create module in `app/Mod/{Name}/`
- [ ] Add `Boot.php` with event listeners
- [ ] Create routes in `Routes/web.php` or `Routes/api.php`
- [ ] Create Livewire components in `Livewire/`
- [ ] Create Blade views in `Views/`
- [ ] Add migrations in `Migrations/`
- [ ] Write tests in `Tests/`
- [ ] Run `vendor/bin/pint --dirty`
- [ ] Run `vendor/bin/pest`
## File Locations
| What | Where |
|------|-------|
| Models | `app/Mod/{Name}/Models/` |
| Livewire | `app/Mod/{Name}/Livewire/` |
| Views | `app/Mod/{Name}/Views/` |
| Routes | `app/Mod/{Name}/Routes/` |
| Migrations | `app/Mod/{Name}/Migrations/` |
| Tests | `app/Mod/{Name}/Tests/` |
| Services | `app/Mod/{Name}/Services/` |
## Critical Rules
1. **UK English** - colour, organisation, centre (never American spellings)
2. **Strict types** - `declare(strict_types=1);` in every PHP file
3. **Type hints** - All parameters and return types
4. **Flux Pro** - Use Flux components, not vanilla Alpine
5. **Font Awesome** - Use FA icons, not Heroicons
6. **Pest** - Write tests using Pest syntax, not PHPUnit
## Example Livewire Component
```php
<?php
declare(strict_types=1);
namespace App\Mod\Blog\Livewire;
use App\Mod\Blog\Models\Post;
use Illuminate\Contracts\View\View;
use Livewire\Component;
use Livewire\WithPagination;
class PostListPage extends Component
{
use WithPagination;
public function render(): View
{
return view('blog::posts.index', [
'posts' => Post::latest()->paginate(10),
]);
}
}
```
## Testing Example
```php
<?php
use App\Mod\Blog\Models\Post;
it('displays posts on the index page', function () {
$posts = Post::factory()->count(3)->create();
$this->get('/blog')
->assertOk()
->assertSee($posts->first()->title);
});
```

66
CLAUDE.md Normal file
View file

@ -0,0 +1,66 @@
# Core PHP Framework Project
## Architecture
Modular monolith using Core PHP Framework. Modules live in `app/Mod/{Name}/Boot.php`.
**Event-driven registration:**
```php
class Boot
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
ApiRoutesRegistering::class => 'onApiRoutes',
AdminPanelBooting::class => 'onAdminPanel',
];
}
```
## Commands
```bash
composer run dev # Dev server (if configured)
php artisan serve # Laravel dev server
npm run dev # Vite
./vendor/bin/pint --dirty # Format changed files
php artisan test # All tests
php artisan make:mod Blog # Create module
```
## Module Structure
```
app/Mod/Blog/
├── Boot.php # Event listeners
├── Models/ # Eloquent models
├── Routes/
│ ├── web.php # Web routes
│ └── api.php # API routes
├── Views/ # Blade templates
├── Livewire/ # Livewire components
├── Migrations/ # Database migrations
└── Tests/ # Module tests
```
## Packages
| Package | Purpose |
|---------|---------|
| `host-uk/core` | Core framework, events, module discovery |
| `host-uk/core-admin` | Admin panel, Livewire modals |
| `host-uk/core-api` | REST API, scopes, rate limiting, webhooks |
| `host-uk/core-mcp` | Model Context Protocol for AI agents |
## Conventions
- UK English (colour, organisation, centre)
- PSR-12 coding style (Laravel Pint)
- Pest for testing
- Livewire + Flux Pro for UI
## License
- `Core\` namespace and vendor packages: EUPL-1.2 (copyleft)
- `app/Mod/*`, `app/Website/*`: Your choice (no copyleft)
See LICENSE for full details.

122
GEMINI.md Normal file
View file

@ -0,0 +1,122 @@
# Core PHP Framework - AI Assistant Context
> For Gemini Code Assist, Jules, and other Google AI tools.
## Project Type
Laravel 12 application using Core PHP Framework - a modular monolith with event-driven architecture.
## Directory Structure
```
app/
├── Mod/ # Feature modules (your code)
│ └── {Name}/
│ ├── Boot.php # Event listeners
│ ├── Models/
│ ├── Routes/
│ ├── Views/
│ └── Livewire/
├── Core/ # Local framework overrides (EUPL-1.2)
└── Providers/
config/core.php # Framework configuration
```
## Module Pattern
Every module has a `Boot.php` with static `$listens` array:
```php
<?php
declare(strict_types=1);
namespace App\Mod\Shop;
use Core\Events\WebRoutesRegistering;
use Core\Events\ApiRoutesRegistering;
use Core\Events\AdminPanelBooting;
class Boot
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
ApiRoutesRegistering::class => 'onApiRoutes',
AdminPanelBooting::class => 'onAdminPanel',
];
public function onWebRoutes(WebRoutesRegistering $event): void
{
$event->routes(fn() => require __DIR__.'/Routes/web.php');
$event->views('shop', __DIR__.'/Views');
}
public function onApiRoutes(ApiRoutesRegistering $event): void
{
$event->routes(fn() => require __DIR__.'/Routes/api.php');
}
public function onAdminPanel(AdminPanelBooting $event): void
{
$event->navigation('Shop', 'shop.admin.index', 'shopping-cart');
}
}
```
## Code Style Requirements
### Language: UK English
- colour (not color)
- organisation (not organization)
- centre (not center)
- behaviour (not behavior)
- licence (noun), license (verb)
### PHP Standards
- `declare(strict_types=1);` in all files
- Full type hints (parameters + return types)
- PSR-12 formatting (use Laravel Pint)
- Pest for testing
### Naming Conventions
| Type | Convention | Example |
|------|------------|---------|
| Model | Singular PascalCase | `Product` |
| Table | Plural snake_case | `products` |
| Controller | `{Model}Controller` | `ProductController` |
| Livewire Page | `{Feature}Page` | `ProductListPage` |
| Livewire Modal | `{Feature}Modal` | `EditProductModal` |
## UI Stack
- **Livewire 3** - Server-side reactivity
- **Flux Pro** - UI component library (NOT vanilla Alpine)
- **Tailwind CSS** - Utility-first styling
- **Font Awesome Pro** - Icons (NOT Heroicons)
## Common Commands
```bash
php artisan make:mod Blog --all # Create module with all features
php artisan serve # Development server
vendor/bin/pint --dirty # Format changed files
vendor/bin/pest # Run tests
```
## Packages
| Package | Namespace | Purpose |
|---------|-----------|---------|
| host-uk/core | `Core\` | Framework core |
| host-uk/core-admin | `Core\Admin\` | Admin panel |
| host-uk/core-api | `Core\Api\` | REST API |
| host-uk/core-mcp | `Core\Mcp\` | AI agent tools |
## Avoid
- American English spellings
- Heroicons (use Font Awesome)
- Vanilla Alpine components (use Flux)
- Over-engineering / premature abstraction
- PHPUnit syntax (use Pest)

View file

@ -102,7 +102,7 @@ DEALINGS IN THE SOFTWARE.
6. QUESTIONS
------------
If you have questions about licensing, contact: [your contact info]
If you have questions about licensing, contact: hello@host.uk.com
For the full EUPL-1.2 text, see:
https://github.com/host-uk/core-php/blob/main/LICENSE

View file

@ -1,5 +1,11 @@
# Core PHP Framework Project
[![CI](https://github.com/host-uk/core-template/actions/workflows/ci.yml/badge.svg)](https://github.com/host-uk/core-template/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/host-uk/core-template/graph/badge.svg)](https://codecov.io/gh/host-uk/core-template)
[![PHP Version](https://img.shields.io/packagist/php-v/host-uk/core-template)](https://packagist.org/packages/host-uk/core-template)
[![Laravel](https://img.shields.io/badge/Laravel-12.x-FF2D20?logo=laravel)](https://laravel.com)
[![License](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](LICENSE)
A modular monolith Laravel application built with Core PHP Framework.
## Features

View file

@ -6,8 +6,11 @@ use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withProviders([
// Core PHP Framework Packages
\Core\CoreServiceProvider::class,
// Core PHP Framework
\Core\LifecycleEventProvider::class,
\Core\Website\Boot::class,
\Core\Front\Boot::class,
\Core\Mod\Boot::class,
])
->withRouting(
web: __DIR__.'/../routes/web.php',
@ -16,7 +19,7 @@ return Application::configure(basePath: dirname(__DIR__))
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
\Core\Front\Boot::middleware($middleware);
})
->withExceptions(function (Exceptions $exceptions) {
//

48
cliff.toml Normal file
View file

@ -0,0 +1,48 @@
# git-cliff configuration
# https://git-cliff.org
[changelog]
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [Unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}**{{ commit.scope }}:** {% endif %}\
{{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
commit_parsers = [
{ message = "^feat", group = "Features" },
{ message = "^fix", group = "Bug Fixes" },
{ message = "^doc", group = "Documentation" },
{ message = "^perf", group = "Performance" },
{ message = "^refactor", group = "Refactor" },
{ message = "^style", group = "Styling" },
{ message = "^test", group = "Testing" },
{ message = "^chore\\(release\\)", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore|^ci", group = "Miscellaneous" },
{ body = ".*security", group = "Security" },
]
protect_breaking_commits = false
filter_commits = false
topo_order = false
sort_commits = "oldest"

View file

@ -10,10 +10,10 @@
"laravel/tinker": "^2.10",
"livewire/flux": "^2.0",
"livewire/livewire": "^3.0",
"host-uk/core": "^1.0",
"host-uk/core-admin": "^1.0",
"host-uk/core-api": "^1.0",
"host-uk/core-mcp": "^1.0"
"host-uk/core": "dev-main",
"host-uk/core-admin": "dev-main",
"host-uk/core-api": "dev-main",
"host-uk/core-mcp": "dev-main"
},
"require-dev": {
"fakerphp/faker": "^1.23",
@ -22,7 +22,8 @@
"laravel/sail": "^1.41",
"mockery/mockery": "^1.6",
"nunomaduro/collision": "^8.6",
"phpunit/phpunit": "^11.5"
"pestphp/pest": "^3.0",
"pestphp/pest-plugin-laravel": "^3.0"
},
"autoload": {
"psr-4": {
@ -36,7 +37,12 @@
"Tests\\": "tests/"
}
},
"repositories": [],
"repositories": [
{
"type": "vcs",
"url": "https://github.com/host-uk/core-php.git"
}
],
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",