From c19612d751a8db9cbb9563f93949f365e669181f Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 26 Jan 2026 18:40:00 +0000 Subject: [PATCH] Initial commit --- .env.example | 76 ++++++++++++++ .gitattributes | 11 ++ .gitignore | 23 +++++ LICENSE | 108 +++++++++++++++++++ README.md | 132 ++++++++++++++++++++++++ app/Http/Controllers/.gitkeep | 0 app/Mod/.gitkeep | 0 app/Models/.gitkeep | 0 app/Providers/AppServiceProvider.php | 24 +++++ artisan | 15 +++ bootstrap/app.php | 23 +++++ bootstrap/cache/.gitignore | 2 + bootstrap/providers.php | 5 + composer.json | 72 +++++++++++++ config/core.php | 24 +++++ database/factories/.gitkeep | 0 database/migrations/.gitkeep | 0 database/seeders/DatabaseSeeder.php | 16 +++ package.json | 16 +++ phpunit.xml | 33 ++++++ postcss.config.js | 6 ++ public/.htaccess | 21 ++++ public/index.php | 17 +++ public/robots.txt | 2 + resources/css/app.css | 3 + resources/js/app.js | 1 + resources/js/bootstrap.js | 3 + resources/views/welcome.blade.php | 65 ++++++++++++ routes/api.php | 5 + routes/console.php | 3 + routes/web.php | 7 ++ storage/app/.gitignore | 3 + storage/app/public/.gitignore | 2 + storage/framework/.gitignore | 9 ++ storage/framework/cache/.gitignore | 3 + storage/framework/cache/data/.gitignore | 2 + storage/framework/sessions/.gitignore | 2 + storage/framework/testing/.gitignore | 2 + storage/framework/views/.gitignore | 2 + storage/logs/.gitignore | 2 + tailwind.config.js | 11 ++ tests/Feature/.gitkeep | 0 tests/TestCase.php | 10 ++ tests/Unit/.gitkeep | 0 vite.config.js | 11 ++ 45 files changed, 772 insertions(+) create mode 100644 .env.example create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 app/Http/Controllers/.gitkeep create mode 100644 app/Mod/.gitkeep create mode 100644 app/Models/.gitkeep create mode 100644 app/Providers/AppServiceProvider.php create mode 100755 artisan create mode 100644 bootstrap/app.php create mode 100644 bootstrap/cache/.gitignore create mode 100644 bootstrap/providers.php create mode 100644 composer.json create mode 100644 config/core.php create mode 100644 database/factories/.gitkeep create mode 100644 database/migrations/.gitkeep create mode 100644 database/seeders/DatabaseSeeder.php create mode 100644 package.json create mode 100644 phpunit.xml create mode 100644 postcss.config.js create mode 100644 public/.htaccess create mode 100644 public/index.php create mode 100644 public/robots.txt create mode 100644 resources/css/app.css create mode 100644 resources/js/app.js create mode 100644 resources/js/bootstrap.js create mode 100644 resources/views/welcome.blade.php create mode 100644 routes/api.php create mode 100644 routes/console.php create mode 100644 routes/web.php create mode 100644 storage/app/.gitignore create mode 100644 storage/app/public/.gitignore create mode 100644 storage/framework/.gitignore create mode 100644 storage/framework/cache/.gitignore create mode 100644 storage/framework/cache/data/.gitignore create mode 100644 storage/framework/sessions/.gitignore create mode 100644 storage/framework/testing/.gitignore create mode 100644 storage/framework/views/.gitignore create mode 100644 storage/logs/.gitignore create mode 100644 tailwind.config.js create mode 100644 tests/Feature/.gitkeep create mode 100644 tests/TestCase.php create mode 100644 tests/Unit/.gitkeep create mode 100644 vite.config.js diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..01b4da4 --- /dev/null +++ b/.env.example @@ -0,0 +1,76 @@ +APP_NAME="Core PHP App" +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_TIMEZONE=UTC +APP_URL=http://localhost + +APP_LOCALE=en_GB +APP_FALLBACK_LOCALE=en_GB +APP_FAKER_LOCALE=en_GB + +APP_MAINTENANCE_DRIVER=file + +BCRYPT_ROUNDS=12 + +LOG_CHANNEL=stack +LOG_STACK=single +LOG_DEPRECATIONS_CHANNEL=null +LOG_LEVEL=debug + +DB_CONNECTION=sqlite +# DB_HOST=127.0.0.1 +# DB_PORT=3306 +# DB_DATABASE=core +# DB_USERNAME=root +# DB_PASSWORD= + +SESSION_DRIVER=database +SESSION_LIFETIME=120 +SESSION_ENCRYPT=false +SESSION_PATH=/ +SESSION_DOMAIN=null + +BROADCAST_CONNECTION=log +FILESYSTEM_DISK=local +QUEUE_CONNECTION=database + +CACHE_STORE=database +CACHE_PREFIX= + +MEMCACHED_HOST=127.0.0.1 + +REDIS_CLIENT=phpredis +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=log +MAIL_HOST=127.0.0.1 +MAIL_PORT=2525 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS="hello@example.com" +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= +AWS_USE_PATH_STYLE_ENDPOINT=false + +VITE_APP_NAME="${APP_NAME}" + +# Core PHP Framework +CORE_CACHE_DISCOVERY=true + +# CDN Configuration (optional) +CDN_ENABLED=false +CDN_DRIVER=bunny +BUNNYCDN_API_KEY= +BUNNYCDN_STORAGE_ZONE= +BUNNYCDN_PULL_ZONE= + +# Flux Pro (optional) +FLUX_LICENSE_KEY= diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..fcb21d3 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto eol=lf + +*.blade.php diff=html +*.css diff=css +*.html diff=html +*.md diff=markdown +*.php diff=php + +/.github export-ignore +CHANGELOG.md export-ignore +.styleci.yml export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bec2973 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +/.phpunit.cache +/node_modules +/public/build +/public/hot +/public/storage +/storage/*.key +/storage/pail +/vendor +.env +.env.backup +.env.production +.phpactor.json +.phpunit.result.cache +Homestead.json +Homestead.yaml +auth.json +npm-debug.log +yarn-error.log +/.fleet +/.idea +/.nova +/.vscode +/.zed diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5709b1a --- /dev/null +++ b/LICENSE @@ -0,0 +1,108 @@ +Core PHP Framework Template +=========================== + +Copyright (c) 2026 Host UK / Snider + +This project uses a dual-licensing approach: + + +1. CORE FRAMEWORK CODE (EUPL-1.2) +--------------------------------- + +The Core PHP Framework packages (host-uk/core, host-uk/core-admin, +host-uk/core-api, host-uk/core-mcp) and any code within the `Core\` +namespace are licensed under the European Union Public Licence v1.2 +(EUPL-1.2). + +The full EUPL-1.2 license text is available at: +https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + +And in the Core PHP Framework repository: +https://github.com/host-uk/core-php/blob/main/LICENSE + + +2. APPLICATION CODE EXCEPTION +----------------------------- + +As the copyright holder, we grant the following additional permission: + +Code you create within the following directories is EXEMPT from the +EUPL-1.2 copyleft requirements and may be licensed under any terms +you choose (including proprietary licenses): + + app/Mod/ - Your feature modules + app/Website/ - Your website/domain modules + app/Service/ - Your service classes + database/ - Your migrations, seeders, factories + resources/ - Your views, assets, translations + routes/ - Your route definitions + tests/ - Your test files + config/ - Your configuration files (except config/core.php) + +This exception applies ONLY to original code you create in these +directories. It does NOT apply to: + + - Modified copies of Core framework code + - Code that extends or overrides the `Core\` namespace + - Derivative works of the Core framework itself + + +3. CORE NAMESPACE MODIFICATIONS +------------------------------- + +If you create local overrides or extensions within the `Core\` namespace +(e.g., in `app/Core/`), those modifications ARE subject to EUPL-1.2 and +its copyleft requirements. + +We encourage you to submit such modifications as pull requests to: +https://github.com/host-uk/core-php + +This requirement constitutes the consideration for the license grant +herein. The Core PHP Framework is not provided without cost; rather, +the license fee is paid in kind through the contribution of improvements +to the community. By using this software, you acknowledge and agree that +modifications to the Core\ namespace shall be made available to the +community under the same terms, ensuring that all users benefit from +collective improvements. This reciprocal obligation is a fundamental +condition of the license grant and not merely a request. + + +4. SUMMARY +---------- + +┌─────────────────────────────────────────────────────────────────────┐ +│ Location │ License │ Copyleft Required? │ +├─────────────────────────────────────────────────────────────────────┤ +│ vendor/host-uk/* │ EUPL-1.2 │ Yes │ +│ app/Core/* │ EUPL-1.2 │ Yes (submit as PR) │ +│ Core\ namespace │ EUPL-1.2 │ Yes │ +├─────────────────────────────────────────────────────────────────────┤ +│ app/Mod/* │ Your choice │ No │ +│ app/Website/* │ Your choice │ No │ +│ app/Service/* │ Your choice │ No │ +│ database/* │ Your choice │ No │ +│ resources/* │ Your choice │ No │ +│ routes/* │ Your choice │ No │ +│ tests/* │ Your choice │ No │ +└─────────────────────────────────────────────────────────────────────┘ + + +5. WARRANTY DISCLAIMER +---------------------- + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. + + +6. QUESTIONS +------------ + +If you have questions about licensing, contact: [your contact info] + +For the full EUPL-1.2 text, see: +https://github.com/host-uk/core-php/blob/main/LICENSE diff --git a/README.md b/README.md new file mode 100644 index 0000000..b82f81c --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +# Core PHP Framework Project + +A modular monolith Laravel application built with Core PHP Framework. + +## Features + +- **Core Framework** - Event-driven module system with lazy loading +- **Admin Panel** - Livewire-powered admin interface with Flux UI +- **REST API** - Scoped API keys, rate limiting, webhooks, OpenAPI docs +- **MCP Tools** - Model Context Protocol for AI agent integration + +## Requirements + +- PHP 8.2+ +- Composer 2.x +- SQLite (default) or MySQL/PostgreSQL +- Node.js 18+ (for frontend assets) + +## Installation + +```bash +# Clone or create from template +git clone https://github.com/host-uk/core-template.git my-project +cd my-project + +# Install dependencies +composer install +npm install + +# Configure environment +cp .env.example .env +php artisan key:generate + +# Set up database +touch database/database.sqlite +php artisan migrate + +# Start development server +php artisan serve +``` + +Visit: http://localhost:8000 + +## Project Structure + +``` +app/ +├── Console/ # Artisan commands +├── Http/ # Controllers & Middleware +├── Models/ # Eloquent models +├── Mod/ # Your custom modules +└── Providers/ # Service providers + +config/ +└── core.php # Core framework configuration + +routes/ +├── web.php # Public web routes +├── api.php # REST API routes +└── console.php # Artisan commands +``` + +## Creating Modules + +```bash +# Create a new module with all features +php artisan make:mod Blog --all + +# Create module with specific features +php artisan make:mod Shop --web --api --admin +``` + +Modules follow the event-driven pattern: + +```php + 'onWebRoutes', + ApiRoutesRegistering::class => 'onApiRoutes', + AdminPanelBooting::class => 'onAdminPanel', + ]; + + public function onWebRoutes(WebRoutesRegistering $event): void + { + $event->routes(fn() => require __DIR__.'/Routes/web.php'); + $event->views('blog', __DIR__.'/Views'); + } +} +``` + +## Core Packages + +| Package | Description | +|---------|-------------| +| `host-uk/core` | Core framework components | +| `host-uk/core-admin` | Admin panel & Livewire modals | +| `host-uk/core-api` | REST API with scopes & webhooks | +| `host-uk/core-mcp` | Model Context Protocol tools | + +## Flux Pro (Optional) + +This template uses the free Flux UI components. If you have a Flux Pro license: + +```bash +# Configure authentication +composer config http-basic.composer.fluxui.dev your-email your-license-key + +# Add the repository +composer config repositories.flux-pro composer https://composer.fluxui.dev + +# Install Flux Pro +composer require livewire/flux-pro +``` + +## Documentation + +- [Core PHP Framework](https://github.com/host-uk/core-php) +- [Getting Started Guide](https://host-uk.github.io/core-php/guide/) +- [Architecture](https://host-uk.github.io/core-php/architecture/) + +## License + +EUPL-1.2 (European Union Public Licence) diff --git a/app/Http/Controllers/.gitkeep b/app/Http/Controllers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/Mod/.gitkeep b/app/Mod/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/Models/.gitkeep b/app/Models/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php new file mode 100644 index 0000000..452e6b6 --- /dev/null +++ b/app/Providers/AppServiceProvider.php @@ -0,0 +1,24 @@ +handleCommand(new ArgvInput); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 0000000..ac5419a --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,23 @@ +withProviders([ + // Core PHP Framework Packages + \Core\CoreServiceProvider::class, + ]) + ->withRouting( + web: __DIR__.'/../routes/web.php', + api: __DIR__.'/../routes/api.php', + commands: __DIR__.'/../routes/console.php', + health: '/up', + ) + ->withMiddleware(function (Middleware $middleware) { + // + }) + ->withExceptions(function (Exceptions $exceptions) { + // + })->create(); diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bootstrap/providers.php b/bootstrap/providers.php new file mode 100644 index 0000000..38b258d --- /dev/null +++ b/bootstrap/providers.php @@ -0,0 +1,5 @@ + [ + app_path('Core'), + app_path('Mod'), + app_path('Website'), + ], + + 'services' => [ + 'cache_discovery' => env('CORE_CACHE_DISCOVERY', true), + ], + + 'cdn' => [ + 'enabled' => env('CDN_ENABLED', false), + 'driver' => env('CDN_DRIVER', 'bunny'), + ], +]; diff --git a/database/factories/.gitkeep b/database/factories/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/database/migrations/.gitkeep b/database/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php new file mode 100644 index 0000000..df6818f --- /dev/null +++ b/database/seeders/DatabaseSeeder.php @@ -0,0 +1,16 @@ + + + + + tests/Unit + + + tests/Feature + + + + + app + + + + + + + + + + + + + + + + diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..49c0612 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..3aec5e2 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,21 @@ + + + Options -MultiViews -Indexes + + + RewriteEngine On + + # Handle Authorization Header + RewriteCond %{HTTP:Authorization} . + RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] + + # Redirect Trailing Slashes If Not A Folder... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_URI} (.+)/$ + RewriteRule ^ %1 [L,R=301] + + # Send Requests To Front Controller... + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..947d989 --- /dev/null +++ b/public/index.php @@ -0,0 +1,17 @@ +handleRequest(Request::capture()); diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/resources/css/app.css b/resources/css/app.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/resources/css/app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/resources/js/app.js b/resources/js/app.js new file mode 100644 index 0000000..e59d6a0 --- /dev/null +++ b/resources/js/app.js @@ -0,0 +1 @@ +import './bootstrap'; diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js new file mode 100644 index 0000000..953d266 --- /dev/null +++ b/resources/js/bootstrap.js @@ -0,0 +1,3 @@ +import axios from 'axios'; +window.axios = axios; +window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php new file mode 100644 index 0000000..88808ac --- /dev/null +++ b/resources/views/welcome.blade.php @@ -0,0 +1,65 @@ + + + + + + Core PHP Framework + + + +
+

Core PHP Framework

+

Laravel {{ Illuminate\Foundation\Application::VERSION }} | PHP {{ PHP_VERSION }}

+ +
+ + diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 0000000..15fbf70 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,5 @@ +