winningsoftware / symfony-base
A base Symfony 7.3 project template with Latte + Vue
Package info
github.com/WinningSoftwareDev/symfony-base
Type:project
pkg:composer/winningsoftware/symfony-base
Requires
- php: >=8.4
- cloudbase/asset-node: ^1.0
- cloudbase/latte-helper: ^1.2.1
- doctrine/dbal: ^4.3
- doctrine/doctrine-bundle: ^3.2
- doctrine/orm: ^3.5
- knpuniversity/oauth2-client-bundle: ^2.0
- league/oauth2-github: ^3.0
- league/oauth2-google: ^4.0
- liip/monitor-bundle: ^2.25
- symfony/asset: ^8.1
- symfony/console: ^8.0
- symfony/dotenv: ^8.0
- symfony/form: ^8.0
- symfony/framework-bundle: ^8.0
- symfony/mailer: ^8.0
- symfony/mime: ^8.0
- symfony/runtime: ^8.0
- symfony/security-bundle: ^8.0
- symfony/validator: ^8.0
- symfony/var-exporter: <8.0
- symfony/yaml: ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.89
- phpstan/phpstan: ^2.1
- phpstan/phpstan-doctrine: ^2.0
README
A highly opinionated, production-ready Symfony 8 starter template designed for rapid application development with a modern frontend stack.
🚀 Features
- Core: Symfony 8 + Doctrine ORM/DBAL.
- Templating: Latte — with custom Vite integration for Instant Live-Reload.
- Frontend: Vue.js 3, Vite, TailwindCSS, TypeScript, and SCSS.
- Auth System: Full "out-of-the-box" flow (Login, Registration, Password Reset, Email Verification, OAuth).
- Email Builder: A database-driven utility for generating templated HTML emails.
- Quality Gates: Pre-configured PHPStan (Max Level), PHP-CS-Fixer, and ESLint.
🛠 Installation
Create your project
composer create-project winningsoftware/symfony-base my-project
This will download the Symfony Base project to a new "my-project" directory in your current working directory.
This also runs the installer as part of the post create project command which creates the required directories, copies
the relevant config files, cleans up unnecessary files and runs composer install - so you don't need to run this
manually.
Configure your environment
Update your .env file to suit your application/development environment. See the "Environment Configuration" section
below.
Install JavaScript dependencies
npm install
Database initialisation
Check the script at data/setup.sql to see what SQL will be executed by the following command:
php bin/console app:database:setup
# Or manually import data/setup.sql
⚙️ Environment Configuration
Before running the app, update your .env file with the following key variables:
| Variable | Default / Example | Description |
|---|---|---|
APP_NAME |
My App |
The name of your application |
DEFAULT_URI |
http://localhost |
Used for generating absolute URLs and OAuth redirect URLs |
DB_HOST |
localhost |
Database host (use mysql if using Docker) |
DB_PORT |
3306 |
Database port |
DB_USER |
root |
Database user |
DB_PASSWORD |
docker |
Database password |
ADMIN_USER |
admin@my-app.com |
Default admin email (created by app:database:setup) |
ADMIN_PASSWORD |
noodlepot |
Default admin password |
MAILER_DSN |
smtp://mailcatcher:1025 |
SMTP connection string |
MAIL_FROM_NAME |
— | Sender name for outgoing emails |
MAIL_FROM_ADDRESS |
info@my-app.com |
Sender address for outgoing emails |
VITE_SERVER_PORT |
3000 |
Vite dev server port |
VITE_LOCAL_PORT |
3000 |
Local port mapped to Vite server (e.g. in Docker) |
USE_HMR |
false |
Set to true to enable Vite Hot Module Replacement |
OAUTH_GITHUB_CLIENT_ID |
— | GitHub OAuth App client ID |
OAUTH_GITHUB_CLIENT_SECRET |
— | GitHub OAuth App client secret |
OAUTH_GOOGLE_CLIENT_ID |
— | Google OAuth 2.0 client ID |
OAUTH_GOOGLE_CLIENT_SECRET |
— | Google OAuth 2.0 client secret |
Note: The OAuth redirect URL is constructed from your
DEFAULT_URIenv var. EnsureDEFAULT_URIuses the correct scheme (httpsin production) so the redirect URL matches what you registered with the provider.
Obtaining OAuth Credentials
GitHub
- Go to Settings > Developer settings > OAuth Apps and click New OAuth App.
- Fill in:
- Application name: Your app name
- Homepage URL: Your app's URL (e.g.
https://my-app.com) - Authorization callback URL:
https://my-app.com/connect/github/check
- Click Register application.
- Copy the Client ID and generate a Client Secret. Set them as
OAUTH_GITHUB_CLIENT_IDandOAUTH_GITHUB_CLIENT_SECRETin your.env.
- Go to the Google Cloud Console, create or select a project.
- Navigate to APIs & Services > Credentials.
- Click Create Credentials > OAuth client ID.
- Set Application type to Web application, add your callback URL under Authorized redirect URIs:
https://my-app.com/connect/google/check. - Click Create. Copy the Client ID and Client Secret. Set them as
OAUTH_GOOGLE_CLIENT_IDandOAUTH_GOOGLE_CLIENT_SECRETin your.env.
💻 Development Workflow
This template supports both local and containerized development. Choose the method that fits your environment.
1. Running the Project (Local)
The simplest way to get started is using PHP's built-in server:
- Terminal A (PHP):
php -S localhost:8000 -t public/ - Terminal B (Vite):
npm run vite:dev - Config: Set
USE_HMR=trueandDEFAULT_URI=http://localhostin your.env.
2. Docker Setup (Recommended)
For a production-like environment, I recommend using Docker. A standard setup should include:
- PHP-FPM (8.4+)
- Server (Nginx/Apache/Caddy etc)
- MySQL 8.0+
- Mailcatcher/Mailtrap (for local email testing)
If using a custom Docker setup with an HTTPS reverse proxy, use the commented-out
serverblock invite.config.tsto map your certificates and enablewssfor HMR. You will need to manually copy the certificate and key from your reverse proxy container into the referenced locations in your PHP container.
3. Hot Module Replacement (HMR)
HMR is configured for both Vue/SCSS assets and Latte templates.
- Local Dev: The default
serverblock invite.config.tsworks out of the box. - Containerized Dev: If running over plain HTTP in Docker, ensure
server.httpsisfalseandserver.hmr.protocolis set tows.
4. Quality Control
Run these commands before committing to maintain high standards:
| Tool | Command | Description |
|---|---|---|
| PHPStan | composer stan |
Static analysis (Level: Max) |
| PHP-CS-Fixer | composer cs |
Check coding standards (dry-run) |
| ESLint | npm run lint |
Lint Vue and TypeScript files |
📂 Project Structure
This template uses a modular, domain-oriented structure. The src/ directory handles PHP logic, while assets/scripts/
organizes Vue components and frontend utilities into feature-based plugins.
src/
├── Administration/ # Module: Admin panel (Vue SPA) — controllers & API
├── Application/ # Domain: Where you build your app logic
├── Authentication/ # Module: Self-contained User & Security logic
├── Core/ # Internal: Base classes and framework extensions
└── Kernel.php
assets/
├── scripts/
│ ├── Core/ # Frontend utilities (ComponentLoader, FlashHandler)
│ ├── Plugin/
│ │ ├── AppCore/ # Homepage UI (IntroCard and sub-components)
│ │ └── AuthCore/ # Authentication UI components
│ └── app.ts # Main JS entry point
└── styles/ # CSS and Tailwind directives
🗄 Database Schema
This project uses a multi-schema approach to maintain strict separation between the Authentication system and other areas of your application.
The php bin/console app:database:setup command executes data/setup.sql, which creates the following:
AuthenticationSchema: ContainstblUser,tblEmailVerificationToken,tblPasswordResetToken,tblRole,tblPermission,tblRolePermission,tblUserRole, andtblUserOauth.CoreSchema: ContainsublEmailTypeandublOauthProvider(look-up tables).
IMPORTANT: Before running the setup command, review
data/setup.sql. If your database user does not haveCREATE SCHEMApermissions, or if you prefer a different database setup, you will need to modify this script and the corresponding Doctrine Entity mappings. You'll need to expose the relevant port (3000 by default) from your PHP container.
📧 Email System
The built-in EmailBuilder utility allows you to generate emails by referencing a "Handle" stored in the Core.ublEmailType table.
Example Usage:
$email = $this->emailBuilder->getEmail( EmailType::VERIFY_EMAIL_ADDRESS, $user->getEmail(), [ 'verificationUrl' => $this->generateUrl('authenticate_verify_email', ['token' => $token]), ] ); $this->mailer->send($email);
🛣 Available Routes
| Namespace | Name | Method | Path |
|---|---|---|---|
| App\Application | app_index |
GET |
/ |
| App\Authentication | authenticate |
GET |
/authenticate |
| App\Authentication | authenticate_request_password_reset |
GET,POST |
/authenticate/password-reset |
| App\Authentication | authenticate_password_reset |
GET,POST |
/authenticate/password-reset/reset |
| App\Authentication | authenticate_login |
GET,POST |
/authenticate/login |
| App\Authentication | authenticate_logout |
GET |
/authenticate/logout |
| App\Authentication | authenticate_get_logged_in_user |
GET |
/authenticate/current-user |
| App\Authentication | authenticate_register |
POST |
/authenticate/register |
| App\Authentication | authenticate_verify_email |
GET |
/authenticate/verify |
| App\Authentication | authenticate_resend_verification_email |
POST |
/authenticate/resend-verification-email |
| App\Authentication | user_account |
GET |
/user/account |
| App\Authentication | connect_oauth_start |
GET |
/connect/{service} |
| App\Authentication | connect_github_check |
GET |
/connect/github/check |
| App\Authentication | connect_google_check |
GET |
/connect/google/check |
| App\Administration | admin_entry |
ANY |
/admin/{vue_routing} |
| Liip Monitor | liip_monitor_health_interface |
ANY |
/monitor/health/ |
Run
php bin/console debug:routerfor the full list of included endpoints.
🔧 Customizing
- Homepage: The main entry point is defined in
src/Application/IndexController.phpwith the template attemplates/application/index.latte. This template renders a singleIntroCardVue component, which acts as a wrapper for various internal components. You can find and modify these inassets/scripts/Plugin/AppCore. - Authentication: All backend logic resides in
src/Authentication. This includes Login, Registration, Password Reset, and Email Verification. - Auth UI: For the frontend side of the built-in system, this project uses Vue components found in the
assets/scripts/Plugin/AuthCoredirectory. - OAuth Providers: To add or remove OAuth sign-in options, update the
Core.ublOauthProviderseed data indata/setup.sql, create aKnpU\OAuth2ClientBundleclient config inconfig/packages/knpu_oauth2_client.yaml, register the callback route inconfig/routes.yaml, and add the provider entry to theOAUTH_PROVIDERSarray inassets/scripts/Plugin/AuthCore/Constant/OauthProvider.ts. - Styles: Global styles, Tailwind directives, and SCSS variables are managed in
assets/styles/app.css.
🐳 Docker & Advanced Setup
The recommended approach for a production-like environment is a containerized setup (PHP, Nginx, MySQL, and Mailcatcher).
If you are using a custom Docker setup, ensure you update the server block in vite.config.ts to use the commented out
section. If you're using plain HTTP inside your containers, remove server.https and set server.hmr.protocol to ws.



