preflow / skeleton
Preflow project skeleton
Requires
- php: >=8.4
- nyholm/psr7: ^1.8
- nyholm/psr7-server: ^1.1
- preflow/auth: ^0.1 || @dev
- preflow/components: dev-main
- preflow/core: dev-main
- preflow/data: dev-main
- preflow/htmx: dev-main
- preflow/i18n: dev-main
- preflow/routing: dev-main
- preflow/twig: dev-main
- preflow/view: dev-main
Requires (Dev)
- preflow/devtools: dev-main
- preflow/testing: dev-main
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-main
- v0.34.0
- v0.33.0
- v0.32.0
- v0.31.0
- v0.30.0
- v0.29.0
- v0.28.0
- v0.27.1
- v0.27.0
- v0.26.0
- v0.25.1
- v0.25.0
- v0.24.1
- v0.24.0
- v0.23.0
- v0.22.1
- v0.22.0
- v0.21.0
- v0.20.0
- v0.19.2
- v0.19.1
- v0.19.0
- v0.18.1
- v0.18.0
- v0.17.2
- v0.17.1
- v0.17.0
- v0.16.2
- v0.16.1
- v0.16.0
- v0.15.0
- v0.14.2
- v0.14.1
- v0.14.0
- v0.13.1
- v0.13.0
- v0.12.0
- v0.11.4
- v0.11.3
- v0.11.2
- v0.11.1
- v0.11.0
- v0.10.4
- v0.10.3
- v0.10.2
- v0.10.1
- v0.10.0
- v0.9.1
- v0.9.0
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.0
- v0.4.1
- v0.4.0
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.1
- v0.1.0
This package is auto-updated.
Last update: 2026-10-25 19:30:07 UTC
README
Starter template for Preflow applications.
Quick Start
composer create-project preflow/skeleton myapp
cd myapp
php preflow serve
Open http://localhost:8080. That's it — the installer handles .env, database, and demo content automatically.
Project Structure
app/
├── Components/ Reusable UI components (PHP + template + CSS/JS)
├── Controllers/ API and form controllers (#[Route] attributes)
├── Models/ Data models (#[Entity] attributes)
├── Providers/ Service providers
├── Seeds/ Demo data seeders
└── pages/ File-based routes (Twig templates)
config/ Framework configuration
lang/ Translation files (en/, de/)
migrations/ Database schema
public/ Web root (index.php, .htaccess)
storage/ SQLite database, cache, logs
tests/ PHPUnit tests
What's Included
Routing
File-based routes in app/pages/ map to URLs by directory structure. Dynamic segments use brackets: blog/[slug].twig matches /blog/hello-world.
Controllers use PHP attributes:
#[Route('/api')] final class HealthController { #[Get('/health')] public function health(ServerRequestInterface $request): ResponseInterface { return new Response(200, ['Content-Type' => 'application/json'], json_encode(['status' => 'ok'])); } }
Components
A component is a PHP class + Twig template + inline CSS/JS in one directory. Drop it in app/Components/, it auto-discovers.
final class ExampleCard extends Component { public string $title = ''; public int $count = 0; public function __construct(private readonly SessionInterface $session) {} public function resolveState(): void { $this->title = $this->props['title'] ?? 'Hello'; $this->count = (int) $this->session->get('example_counter', 0); } public function actions(): array { return ['increment']; } public function actionIncrement(array $params = []): void { $this->count = (int) $this->session->get('example_counter', 0) + 1; $this->session->set('example_counter', $this->count); } }
Use in templates: {{ component('ExampleCard', { title: 'Hello' }) }}
Authentication
Login, registration, and logout are included. Protect routes with middleware:
#[Route('/dashboard')] #[Middleware(AuthMiddleware::class)] final class DashboardController { /* ... */ }
Templates can check auth status:
{% if auth_check() %}
Welcome, {{ auth_user().email }}
{% endif %}
Blog Admin
The skeleton includes a full blog admin at /admin (requires login). Create, edit, and delete posts through a form-based interface.
Default admin credentials:
- Email: admin@preflow.dev
- Password: password
The admin demonstrates the hybrid pattern: PostForm component handles form UI with co-located CSS, BlogAdminController handles CRUD logic with redirects and flash messages.
Internationalization
Translations live in lang/{locale}/{group}.php. Switch languages with the locale switcher in the header, or visit /de/... for German.
{{ t('blog.title') }}
{{ t('blog.published', { date: '2026-01-01' }) }}
{{ t('blog.post_count', {}, 5) }}
Data Layer
Models use PHP attributes for storage mapping:
#[Entity(table: 'posts', storage: 'default')] final class Post extends Model { #[Id] public string $uuid = ''; #[Field(searchable: true)] public string $title = ''; #[Field] public string $status = 'draft'; }
Query with the DataManager:
$posts = $dm->query(Post::class) ->where('status', 'published') ->orderBy('uuid', SortDirection::Desc) ->get();
HTMX
Components can define actions that handle HTMX requests. The ExampleCard counter persists in the session across page reloads — no JavaScript needed.
Asset helpers
AppServiceProvider registers asset_url() and img_url() template functions. Both resolve paths relative to the public/ directory.
<link rel="stylesheet" href="{{ asset_url('css/app.css') }}"> <img src="{{ img_url('logo.png') }}" alt="Logo">
img_url() is a convenience wrapper that prepends images/ automatically. Both functions are commented-out examples in AppServiceProvider — uncomment and adjust the base path for your deployment.
Configuration
| File | Purpose |
|---|---|
config/app.php |
App name, debug level, timezone, locale, template engine |
config/auth.php |
Guards, user providers, session settings |
config/data.php |
Storage drivers (SQLite, JSON, MySQL) |
config/i18n.php |
Available locales, fallback, URL strategy |
config/providers.php |
Service provider registration |
.env |
Environment-specific overrides |
CLI Commands
php preflow serve # Start dev server (localhost:8080) php preflow migrate # Run pending migrations php preflow db:seed # Seed demo data php preflow key:generate # Generate APP_KEY php preflow routes:list # List all routes php preflow cache:list # List registered caches php preflow cache:clear --all # Clear every registered cache
Web Server
Development: php preflow serve — no configuration needed.
Apache: Point your document root to the public/ directory. The included .htaccess handles URL rewriting. Ensure mod_rewrite is enabled.
Nginx:
server { listen 80; server_name myapp.test; root /path/to/myapp/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass unix:/var/run/php/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; include fastcgi_params; } }
Testing
./vendor/bin/phpunit
Tests live in tests/. The skeleton includes example tests for components and routing.