adaiasmagdiel/erlenmeyer-starter

Starter template for web applications with Erlenmeyer and related packages

Maintainers

Package info

github.com/AdaiasMagdiel/erlenmeyer-starter

Type:project

pkg:composer/adaiasmagdiel/erlenmeyer-starter

Transparency log

Statistics

Installs: 10

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v2.1.1 2026-08-27 15:26 UTC

This package is auto-updated.

Last update: 2026-08-27 15:27:45 UTC


README

A starter template for adaiasmagdiel/erlenmeyer with batteries included: Vue 3, Tailwind CSS, Sonner.js, FullCrawl migrations, and phpdotenv.

Stack

Layer Tech
Framework Erlenmeyer v6
Migrations FullCrawl v1.2
Env vars vlucas/phpdotenv v5
Frontend Vue 3 (CDN)
Styling Tailwind CSS v3 (CDN)
Toasts Sonner.js (CDN)

Requirements

  • PHP ^8.2 with json and mbstring extensions
  • Composer
  • Apache with mod_rewrite enabled
  • MySQL / MariaDB (or PostgreSQL / SQLite)

Getting Started

Erlenmeyer Starter is published on Packagist, so the fastest way to start a new project is composer create-project:

# 1. Scaffold a new project
composer create-project adaiasmagdiel/erlenmeyer-starter my-app
cd my-app
# .env is created automatically from .env.example — edit it with your database credentials

# 2. Run migrations (if any)
php fullcrawl.php

# 3. Serve
php -S localhost:8000

Alternatively, clone the repo directly:

git clone https://github.com/adaiasmagdiel/erlenmeyer-starter.git my-app
cd my-app
composer install
cp .env.example .env
# Edit .env with your database credentials
php fullcrawl.php
php -S localhost:8000

For production, point your Apache virtual host to the project root. mod_rewrite must be enabled — all requests are routed through index.php.

Project Structure

erlenmeyer-starter/
├── app/
│   ├── Controllers/
│   │   └── Site.php        # Example controller
│   ├── Database.php        # Lazy PDO singleton registry
│   └── helpers.php         # t(), e(), isDev(), env()
├── templates/
│   ├── layouts/
│   │   └── dashboard.php   # Main HTML layout
│   ├── dashboard/
│   │   └── index.php       # Example page with Vue component
│   ├── site/
│   │   └── index.php       # Welcome page
│   ├── 404.php
│   └── 500.php
├── routes/
│   ├── index.php           # Route definitions
│   └── error_handler.php   # 404 / exception handlers
├── bootstrap.php            # Env & DB initialization
├── index.php                # Entry point: boots App, loads routes, runs it
├── fullcrawl.php            # Migration config
├── .env.example
└── .htaccess

Adding Routes

index.php only boots the App and delegates to routes/index.php, which registers the 404/exception handlers (routes/error_handler.php) and every route:

$app->get('/', [Site::class, 'index']);
$app->post('/users', [Users::class, 'store']);

Group related routes under a shared prefix (and, optionally, middlewares) with group() -- see the /api example already in routes/index.php:

$app->group('/api', function () use ($app) {
    $app->get('/health', fn($req, $res) => $res->withJson(['status' => 'ok']));
}, [$authMiddleware]); // middlewares array is optional

Creating Pages

Pages use output buffering to separate body and script from the layout:

<?php ob_start(); ?>
<template id="tpl-page">
    <main>
        <p>Hello, {{ store.user.name }}</p>
    </main>
</template>
<?php $body = ob_get_clean(); ?>

<?php ob_start(); ?>
<script>
    window.__APP.component('page', {
        template: '#tpl-page',
        setup() {
            const store = Vue.inject('store');
            return { store };
        }
    });
</script>
<?php $script = ob_get_clean(); ?>

<?php
$page = ['body' => $body, 'script' => $script, 'info' => ['title' => 'My Page']];
include t('layouts/dashboard');

Global State

A reactive Vue store is available via inject('store') in any component:

// provided in layouts/dashboard.php
const store = Vue.reactive({
    user: { name: '...', role: '...' }
});
__APP.provide('store', store);

Helpers

Helper Description
t(string $path) Resolves a template path to absolute path
e(?string $value) HTML-escapes a string (XSS prevention)
isDev(): bool Returns true when ENV=development
env(string $key, mixed $default = null) Gets an environment variable — checks $_ENV first, then falls back to getenv()

Database

Database is a lazy singleton registry for PDO connections. Register a connection's config once (typically in bootstrap.php) and it only actually connects the first time it's used:

Database::configure('default', 'mysql', [
    'host' => env('DB_HOST'),
    'port' => env('DB_PORT'),
    'username' => env('DB_USERNAME'),
    'password' => env('DB_PASSWORD'),
    'database' => env('DB_DATABASE'),
]);

// ... later, wherever you need it — connects on first call, reused after that:
$pdo = Database::getConn(); // key defaults to 'default'

Supports MySQL, MariaDB, PostgreSQL, and SQLite, and multiple named connections (Database::configure('reporting', ...), Database::getConn('reporting')) side by side.

License

GPL v3 — see LICENSE for details.