{"id":51412836,"url":"https://github.com/citomni/app-skeleton","last_synced_at":"2026-07-04T16:01:14.939Z","repository":{"id":363916190,"uuid":"1258702509","full_name":"citomni/app-skeleton","owner":"citomni","description":"Neutral application skeleton for CitOmni. Provides the app container, core wiring points, source-layer structure, runtime folders, and installer tooling without assuming HTTP or CLI mode.","archived":false,"fork":false,"pushed_at":"2026-06-10T22:07:22.000Z","size":26,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-10T23:21:58.834Z","etag":null,"topics":["app-skeleton","application-skeleton","application-template","citomni","citomni-framework","citomni-php","composer","create-project","framework","lightweight-framework","php","php-framework","skeleton"],"latest_commit_sha":null,"homepage":"https://www.citomni.com/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/citomni.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-03T20:48:52.000Z","updated_at":"2026-06-10T22:03:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/citomni/app-skeleton","commit_stats":null,"previous_names":["citomni/app-skeleton"],"tags_count":2,"template":true,"template_full_name":null,"purl":"pkg:github/citomni/app-skeleton","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citomni%2Fapp-skeleton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citomni%2Fapp-skeleton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citomni%2Fapp-skeleton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citomni%2Fapp-skeleton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/citomni","download_url":"https://codeload.github.com/citomni/app-skeleton/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/citomni%2Fapp-skeleton/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35127443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["app-skeleton","application-skeleton","application-template","citomni","citomni-framework","citomni-php","composer","create-project","framework","lightweight-framework","php","php-framework","skeleton"],"created_at":"2026-07-04T16:01:14.116Z","updated_at":"2026-07-04T16:01:14.931Z","avatar_url":"https://github.com/citomni.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# CitOmni App Skeleton\n\nNeutral application skeleton for CitOmni.\n\n`citomni/app-skeleton` is the mode-neutral starting point for CitOmni applications. It provides the application container, app-owned root files, neutral source-layer folders, common config entry points, runtime state folders, defensive `.htaccess` files, and installer lifecycle tooling.\n\nIt does **not** assume that the application is an HTTP app, a CLI app, or both. HTTP and CLI support are added explicitly through `citomni/http` and `citomni/cli`.\n\nLean, deterministic, and pleasantly boring where boring is a feature.\n\n---\n\n## Highlights\n\n- **Mode-neutral application container** for CitOmni projects.\n- **No HTTP assumption** by default: No `public/`, no `templates/`, no HTTP routes, and no web front controller until `citomni/http` is installed.\n- **No CLI assumption** by default: No `bin/citomni` launcher until `citomni/cli` is installed.\n- **Installer-ready lifecycle model** through `citomni/installer`.\n- **App-owned common config entry points** for shared cfg, providers, and local services.\n- **Canonical source-layer folders** for operations, repositories, services, policies, state handlers, support classes, enums, utilities, and exceptions.\n- **Shared-hosting defense-in-depth** through deny rules in internal folders.\n- **Deterministic line endings** through `.gitattributes`.\n\n---\n\n## What this package is\n\n`citomni/app-skeleton` is the neutral application root for CitOmni.\n\nIt exists so new applications can start from a clean, mode-free structure and then explicitly opt into the runtime modes they need.\n\nA new application may become:\n\n- An HTTP application.\n- A CLI application.\n- A combined HTTP and CLI application.\n- A base for a richer DevKit-driven workflow.\n\nThe skeleton itself stays small. Runtime-near scaffold files are owned by the package that needs them.\n\nExamples:\n\n- `public/index.php` is owned by `citomni/http`.\n- `templates/` is owned by `citomni/http`.\n- `bin/citomni` is owned by `citomni/cli`.\n- Scaffold materialization is handled by `citomni/installer`.\n\nThis keeps ownership visible and avoids turning the starter project into a drawer full of maybe-useful files.\n\n---\n\n## What this package provides\n\n`citomni/app-skeleton` provides the app-owned baseline structure.\n\nThat includes:\n\n- Root Composer project metadata.\n- PSR-4 application autoloading.\n- App-owned common configuration files.\n- Shared cfg, provider, and service entry points.\n- Neutral source-layer directories.\n- Language directories.\n- Runtime state directories under `var/`.\n- Defensive `.htaccess` files for internal folders.\n- `.gitattributes` for deterministic line endings.\n- `citomni/installer` as lifecycle tooling.\n\nIt gives the application a safe place to exist before any runtime mode is installed.\n\n---\n\n## What this package does not provide\n\n`citomni/app-skeleton` deliberately does **not** provide:\n\n- HTTP runtime behavior.\n- CLI runtime behavior.\n- HTTP front controller files.\n- CLI launcher files.\n- HTTP routes.\n- CLI commands.\n- HTML templates.\n- Public webroot files.\n- Deployment profiles.\n- Application business logic.\n\nThose belong to runtime packages, provider packages, DevKit, or the application itself.\n\nNo ceremonial `public/` directory for pure CLI apps. No `bin/citomni` launcher for pure HTTP apps. The filesystem should not cosplay as a framework decision.\n\n---\n\n## Requirements\n\n- PHP **8.2+**\n- Composer\n- `citomni/kernel`\n- `citomni/installer`\n\nOPcache is strongly recommended in production once a runtime mode has been installed.\n\n---\n\n## Installation\n\nCreate a new neutral CitOmni application:\n\n```bash\ncomposer create-project citomni/app-skeleton my-app\ncd my-app\n```\n\nAt this point the application is intentionally neutral. It has no HTTP or CLI runtime mode yet.\n\n---\n\n## Add HTTP support\n\nInstall the HTTP runtime package:\n\n```bash\ncomposer require citomni/http\ncomposer citomni:install:http\n```\n\nDirect equivalent, if you do not use Composer scripts:\n\n```bash\nvendor/bin/citomni-installer install --package=citomni/http\n```\n\nThis materializes HTTP-owned scaffold such as:\n\n```text\npublic/index.php\npublic/.htaccess\npublic/assets/.gitkeep\npublic/uploads/.htaccess\nconfig/citomni_http_cfg.php\nconfig/citomni_http_cfg.dev.php\nconfig/citomni_http_cfg.stage.php\nconfig/citomni_http_cfg.prod.php\nconfig/citomni_http_routes.php\nconfig/citomni_http_routes.dev.php\nconfig/citomni_http_routes.stage.php\nconfig/citomni_http_routes.prod.php\nconfig/services_http.php\nsrc/Http/Controller/AppController.php\ntemplates/.htaccess\ntemplates/public/.gitkeep\ntemplates/member/.gitkeep\ntemplates/admin/.gitkeep\n```\n\nAfter this, point your web server document root to:\n\n```text\npublic/\n```\n\nFor local development, you can use PHP's built-in server:\n\n```bash\nphp -S 127.0.0.1:8000 -t public\n```\n\nFor the full scaffold lifecycle manual, see the [CitOmni Installer README](https://github.com/citomni/installer/blob/main/README.md).\n\n---\n\n## Add CLI support\n\nInstall the CLI runtime package:\n\n```bash\ncomposer require citomni/cli\ncomposer citomni:install:cli\n```\n\nDirect equivalent, if you do not use Composer scripts:\n\n```bash\nvendor/bin/citomni-installer install --package=citomni/cli\n```\n\nThis materializes CLI-owned scaffold such as:\n\n```text\nbin/citomni\nconfig/citomni_cli_cfg.php\nconfig/citomni_cli_cfg.dev.php\nconfig/citomni_cli_cfg.stage.php\nconfig/citomni_cli_cfg.prod.php\nconfig/citomni_cli_commands.php\nconfig/citomni_cli_commands.dev.php\nconfig/citomni_cli_commands.stage.php\nconfig/citomni_cli_commands.prod.php\nconfig/services_cli.php\nsrc/Cli/Command/HelloCommand.php\n```\n\nFor the full scaffold lifecycle manual, see the [CitOmni Installer README](https://github.com/citomni/installer/blob/main/README.md).\n\n---\n\n## Add both HTTP and CLI\n\nA combined application can install both modes:\n\n```bash\ncomposer require citomni/http citomni/cli\ncomposer citomni:install:http\ncomposer citomni:install:cli\n```\n\nHTTP and CLI share the same app root, config folder, common cfg, providers, common services, source layers, language files, and runtime state folders.\n\nThe mode-specific adapters stay separate:\n\n```text\nsrc/Http/\nsrc/Cli/\n```\n\nShared application logic should normally live in:\n\n```text\nsrc/Operation/\nsrc/Repository/\nsrc/Service/\nsrc/Policy/\nsrc/State/\nsrc/Support/\nsrc/Enum/\nsrc/Util/\nsrc/Exception/\n```\n\nFor details about installer status checks, repair, sync, conflict handling, manifests, policies, state, and JSON output, see the [CitOmni Installer README](https://github.com/citomni/installer/blob/main/README.md).\n\n---\n\n## Fresh project layout\n\nA fresh `citomni/app-skeleton` project contains only the neutral app structure:\n\n```text\n/app-root\n\t/bin\n\t\t/.htaccess\n\n\t/config\n\t\t/.htaccess\n\t\t/citomni_cfg.php\n\t\t/citomni_cfg.dev.php\n\t\t/citomni_cfg.stage.php\n\t\t/citomni_cfg.prod.php\n\t\t/CONFIGURATION.md\n\t\t/providers.php\n\t\t/services.php\n\n\t/language\n\t\t/da\n\t\t\t/.gitkeep\n\t\t/en\n\t\t\t/.gitkeep\n\t\t/.htaccess\n\n\t/src\n\t\t/Enum\n\t\t\t/.gitkeep\n\t\t/Exception\n\t\t\t/.gitkeep\n\t\t/Operation\n\t\t\t/.gitkeep\n\t\t/Policy\n\t\t\t/.gitkeep\n\t\t/Repository\n\t\t\t/.gitkeep\n\t\t/Service\n\t\t\t/.gitkeep\n\t\t/State\n\t\t\t/.gitkeep\n\t\t/Support\n\t\t\t/.gitkeep\n\t\t/Util\n\t\t\t/.gitkeep\n\t\t/.htaccess\n\n\t/tests\n\t\t/.htaccess\n\n\t/var\n\t\t/backups\n\t\t\t/flags\n\t\t\t\t/.gitkeep\n\t\t\t/.gitkeep\n\t\t/cache\n\t\t\t/.gitkeep\n\t\t/flags\n\t\t\t/.gitkeep\n\t\t/logs\n\t\t\t/.gitkeep\n\t\t/nonces\n\t\t\t/.gitkeep\n\t\t/secrets\n\t\t\t/.gitkeep\n\t\t/state\n\t\t\t/.gitkeep\n\t\t/.htaccess\n\n\t.gitattributes\n\t.gitignore\n\t.htaccess\n\tcomposer.json\n\tLICENSE\n\tNOTICE\n\tREADME.md\n\tTRADEMARKS.md\n```\n\nMode-specific folders such as `public/`, `templates/`, `src/Http/`, and `src/Cli/` are intentionally absent until their owning package is installed and materialized.\n\n---\n\n## Configuration files\n\nThe neutral skeleton provides the common app-level config entry points. Runtime packages may add mode-specific overlays when HTTP or CLI support is installed.\n\nFor the detailed merge contract, see [`config/CONFIGURATION.md`](config/CONFIGURATION.md).\n\n### `config/citomni_cfg.php`\n\nDefines application-owned common configuration shared by HTTP and CLI.\n\n```php\n\u003c?php\ndeclare(strict_types=1);\n\nreturn [\n\t'identity' =\u003e [\n\t\t'app_name' =\u003e 'My App',\n\t],\n];\n```\n\nThis file is the stable app base. It should contain durable values that are not inherently HTTP-specific or CLI-specific.\n\n### `config/citomni_cfg.\u003cenv\u003e.php`\n\nDefines optional common environment overlays, normally `dev`, `stage`, and `prod`.\n\nThese files are loaded after `config/citomni_cfg.php` and before mode-specific environment overlays. They should express narrow environment differences, not duplicate the base file because future you already has enough to review.\n\n### `config/providers.php`\n\nLists provider package registries loaded by the application.\n\n```php\n\u003c?php\ndeclare(strict_types=1);\n\nreturn [\n\t// \\Vendor\\Package\\Boot\\Registry::class,\n];\n```\n\nProvider order matters. Provider cfg is merged in the listed order, while provider service-map precedence is derived from the same order with app service maps still winning above provider and vendor definitions.\n\n### `config/services.php`\n\nDefines app-local service map entries and common overrides.\n\n```php\n\u003c?php\ndeclare(strict_types=1);\n\nreturn [\n\t// 'example' =\u003e \\App\\Service\\ExampleService::class,\n];\n```\n\n`services.php` is shared by HTTP and CLI. A service definition placed here should therefore be safe for both modes, or intentionally override a common service contract.\n\n### Mode-specific cfg files\n\nHTTP mode may add:\n\n```text\nconfig/citomni_http_cfg.php\nconfig/citomni_http_cfg.dev.php\nconfig/citomni_http_cfg.stage.php\nconfig/citomni_http_cfg.prod.php\n```\n\nCLI mode may add:\n\n```text\nconfig/citomni_cli_cfg.php\nconfig/citomni_cli_cfg.dev.php\nconfig/citomni_cli_cfg.stage.php\nconfig/citomni_cli_cfg.prod.php\n```\n\nMode-specific cfg files override common cfg for their mode. Environment overlays override the matching base files.\n\n### Mode-specific service files\n\nHTTP mode may add:\n\n```text\nconfig/services_http.php\n```\n\nCLI mode may add:\n\n```text\nconfig/services_cli.php\n```\n\nService maps use PHP array union semantics. First matching service ID wins. In practice, app mode-specific service maps have the highest precedence, followed by app common services, then provider maps, then the selected vendor mode baseline.\n\n### Dispatch files\n\nHTTP routes remain HTTP-specific:\n\n```text\nconfig/citomni_http_routes.php\nconfig/citomni_http_routes.dev.php\nconfig/citomni_http_routes.stage.php\nconfig/citomni_http_routes.prod.php\n```\n\nCLI commands remain CLI-specific:\n\n```text\nconfig/citomni_cli_commands.php\nconfig/citomni_cli_commands.dev.php\nconfig/citomni_cli_commands.stage.php\nconfig/citomni_cli_commands.prod.php\n```\n\nThere is no common route map and no common command map. Shared orchestration belongs in operations, repositories, services, policies, or other shared source layers, not in shared dispatch files.\n\n## Source-layer model\n\nCitOmni keeps responsibility boundaries explicit.\n\n- `src/Operation/`: Transport-agnostic orchestration and application-level decision logic.\n- `src/Repository/`: Persistence boundary. All SQL and datastore IO belongs here.\n- `src/Service/`: App-aware services registered in the service map.\n- `src/Policy/`: App-aware policy classes for explicit rules and requirements.\n- `src/State/`: Runtime state handlers for state contracts, keys, locks, TTLs, and transitions.\n- `src/Support/`: Focused support classes that may need application context without being singleton services.\n- `src/Enum/`: Bounded value sets such as modes, statuses, purposes, or stable internal flags.\n- `src/Util/`: Pure helpers only. No App, no config reads, no IO, no logging, no SQL.\n- `src/Exception/`: Transport-agnostic application and domain exceptions.\n\nHTTP-specific code should live under `src/Http/` once HTTP mode is installed.\n\nCLI-specific code should live under `src/Cli/` once CLI mode is installed.\n\n---\n\n## Scaffold ownership\n\nCitOmni packages own the scaffold they require.\n\n```text\ncitomni/app-skeleton\n\tOwns the neutral app container.\n\ncitomni/kernel\n\tOwns common config scaffold such as citomni_cfg.php, services.php, and providers.php.\n\ncitomni/http\n\tOwns HTTP runtime and HTTP scaffold.\n\ncitomni/cli\n\tOwns CLI runtime and CLI scaffold.\n\ncitomni/installer\n\tMaterializes package-owned scaffold into the app.\n```\n\nThe details of scaffold discovery, rendering, checksums, managed files, create-only files, `.new` files, repair, and sync belong in the [CitOmni Installer README](https://github.com/citomni/installer/blob/main/README.md).\n\n---\n\n## Security notes\n\nThis skeleton includes defensive `.htaccess` files in internal folders.\n\nExamples:\n\n```text\nbin/.htaccess\nconfig/.htaccess\nlanguage/.htaccess\nsrc/.htaccess\ntests/.htaccess\nvar/.htaccess\n```\n\nThese files are defense-in-depth for shared hosting or misconfigured web roots. A correct HTTP deployment should still point the web server document root to `public/` after HTTP mode is installed.\n\nDo not rely on `.htaccess` as the only security boundary. The correct public webroot is still the real fix. The `.htaccess` files are the airbag, not the steering wheel.\n\nSecrets should not be committed.\n\nRuntime secrets belong under:\n\n```text\nvar/secrets/\n```\n\nor should be provided by environment, deployment tooling, or a dedicated secret mechanism.\n\n---\n\n## Runtime state\n\nThe `var/` folder is the application runtime write area.\n\nTypical subfolders:\n\n```text\nvar/backups/\nvar/cache/\nvar/flags/\nvar/logs/\nvar/nonces/\nvar/secrets/\nvar/state/\n```\n\nProduction deployments should generally make application code read-only and allow writes only where the application deliberately needs runtime state.\n\n---\n\n## Autoloading and performance\n\nThe skeleton uses PSR-4 autoloading:\n\n```json\n{\n\t\"autoload\": {\n\t\t\"psr-4\": {\n\t\t\t\"App\\\\\": \"src/\"\n\t\t}\n\t}\n}\n```\n\nFor development, avoid `classmap-authoritative` as a default unless you are comfortable running autoload dumps whenever classes are added or moved.\n\nFor production, use optimized Composer autoloading:\n\n```bash\ncomposer install --no-dev --optimize-autoloader --classmap-authoritative\n```\n\nor:\n\n```bash\ncomposer dump-autoload -a\n```\n\nOPcache is strongly recommended in production.\n\n---\n\n## Line endings\n\nThe skeleton ships with `.gitattributes` to keep text files normalized.\n\nThis reduces false diffs, makes scaffold checksums more predictable, and keeps Windows development from turning line endings into a tiny procedural crime scene.\n\n---\n\n## Testing\n\nThe skeleton is ready for PHPUnit if you add it:\n\n```bash\ncomposer require --dev phpunit/phpunit:^10.5\n```\n\nTests should live under:\n\n```text\ntests/\n```\n\nwith namespace:\n\n```text\nApp\\Tests\\\n```\n\n---\n\n## Troubleshooting\n\n### `vendor/bin/citomni-installer` is missing\n\nRun Composer install:\n\n```bash\ncomposer install\n```\n\nConfirm that `citomni/installer` is required in `composer.json`.\n\n### HTTP install did not create `public/`\n\nConfirm that `citomni/http` is installed, then materialize the HTTP scaffold:\n\n```bash\ncomposer show citomni/http\ncomposer citomni:install:http\n```\n\n### CLI install did not create `bin/citomni`\n\nConfirm that `citomni/cli` is installed, then materialize the CLI scaffold:\n\n```bash\ncomposer show citomni/cli\ncomposer citomni:install:cli\n```\n\n### New PHP class is not found\n\nRun:\n\n```bash\ncomposer dump-autoload\n```\n\nIf using authoritative classmaps, run:\n\n```bash\ncomposer dump-autoload -a\n```\n\n### Web server shows internal files\n\nPoint the web server document root to:\n\n```text\npublic/\n```\n\nIf `public/` does not exist, HTTP mode has not been installed yet.\n\n---\n\n## Coding and documentation conventions\n\nAll CitOmni projects follow the shared conventions documented here:\n\n[CitOmni Coding and Documentation Conventions](https://github.com/citomni/docs/blob/main/contribute/CONVENTIONS.md)\n\nCore conventions:\n\n- PHP **8.2+**\n- PSR-1 and PSR-4\n- PascalCase classes\n- camelCase methods and variables\n- UPPER_SNAKE_CASE constants\n- K\u0026R brace style\n- Tabs for indentation\n- PHPDoc and inline comments in English\n- Explicit wiring over discovery\n- Deterministic behavior over magic\n\n---\n\n## License\n\n**CitOmni App Skeleton** is open-source under the **MIT License**.\n\nSee [LICENSE](LICENSE).\n\n**Trademark notice:** \"CitOmni\" and the CitOmni logo are trademarks of **Lars Grove Mortensen**. Usage of the name or logo must follow the policy in [NOTICE](NOTICE). Do not imply endorsement or affiliation without prior written permission.\n\n---\n\n## Trademarks\n\n\"CitOmni\" and the CitOmni logo are trademarks of **Lars Grove Mortensen**.\n\nYou may make factual references to \"CitOmni\", but do not modify the marks, create confusingly similar logos, or imply sponsorship, endorsement, or affiliation without prior written permission.\n\nDo not register or use \"citomni\" or confusingly similar terms in company names, domains, social handles, or top-level vendor/package names.\n\nFor details, see [NOTICE](NOTICE).\n\n---\n\n## Author\n\nDeveloped by Lars Grove Mortensen © 2012-present.\n\n---\n\nCitOmni - low overhead, high performance, ready for anything.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitomni%2Fapp-skeleton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcitomni%2Fapp-skeleton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcitomni%2Fapp-skeleton/lists"}