kreta/core
kreta/core is the foundational package for the Kreta Laravel ecosystem, providing shared contracts, service providers, configuration, and utilities that other Kreta modules build on. It offers a consistent base for integrating and extending Kreta-based applications.
kreta/core is a Laravel foundation package, not a feature package. You will not get controllers, routes, or a UI from it. What you get on composer require kreta/core is a service provider (auto-discovered, assuming standard Laravel package conventions), a set of shared contracts and base classes intended for sibling Kreta modules, and a publishable config file. Install into a Laravel application at the same major version you intend to support, then immediately verify the provider registered:
composer require kreta/core
php artisan vendor:publish --provider="Kreta\\Core\\KretaCoreServiceProvider" --tag=config
php artisan about # confirm the provider shows in the loaded list
Look at these first, in this order. Do not start by reading the README, because there isn't meaningful one. Start in the source tree:
composer.json — the require block tells you which Laravel and PHP majors this actually targets. This is your single most important compatibility signal.src/*ServiceProvider.php) — everything the package registers at boot lives here. If it binds singletons, registers middleware, publishes config, or merges config defaults, this is where you find out. Read register() and boot() line by line.src/Contracts/ — the interfaces you will type-hint against. These are the real public API.src/ base classes and config/ — what you inherit from and what you can override.Your first use case. The canonical day-one pattern for a core package like this is: publish the config, bind your own implementations of the shared contracts in a small application-level service provider, and build one thin feature on top. Concretely — define an app-level AppServiceProvider::register() that rebinds any core contract to your concrete implementation, then extend a core base class for your first domain model. This exercises the two things you actually need to work: config merging/publishing, and interface resolution from the container. If both work, the package is bootstrapping correctly and you can start layering modules. If the container cannot resolve a core contract, you have found the "it's a partial install" failure early, which is exactly the point of the spike.
Treat it as a kernel, not a library. The intended shape of a Kreta-style package is core + feature modules, where the core owns shared abstractions and each feature package depends on core, never the other way around. In practice:
app/
Providers/AppServiceProvider.php # binds core contracts to app implementations
packages/
kreta-core/ # vendored if you fork
kreta-students/ # feature module, depends on core
kreta-enrollment/ # feature module, depends on core
Feature modules require kreta/core in their own composer.json. Keep application-specific overrides (custom repositories, custom role logic) in AppServiceProvider or a dedicated DomainServiceProvider, never by editing the vendor tree.
Contract-first implementation. The most reliable day-to-day pattern is: type-hint against the core contract in your constructors, resolve from the container, provide the concrete class via a binding. This keeps your code testable and keeps the core replaceable — important given the maintenance risk on this package.
// app/Providers/DomainServiceProvider.php
public function register(): void
{
$this->app->bind(
\Kreta\Core\Contracts\SomeContract::class,
\App\Domain\MyImplementation::class
);
}
Extending base abstractions instead of composing. Core packages usually ship base models, base providers, or trait bundles intended for inheritance. Use them where they match your domain, but be deliberate: a single class extending a core base class is one vendor upgrade away from a break. If a base class exposes too much, prefer wrapping it with composition so a replacement is local rather than spread across the codebase.
Module registration through the core provider. If the core provider is the registration point for feature modules (a common Kreta-shape pattern), register each module provider in config/app.php or auto-discovery, and keep module bootstrapping declarative. Do not do work in module boot() methods that depends on another module being booted — provider boot order is not a contract.
Config as the integration seam. Publish the config once, commit it, and change it in your application. Do not rely on runtime overrides of core config values from inside feature modules. If you need environment-driven variation, add your own config key that reads env() and pass that into core services at construction.
Workflow for a new feature module:
DomainServiceProvider.Auto-discovery fails silently when namespaces drift. Laravel's package discovery relies on the extra.laravel block in composer.json. If the package's declared provider does not match its actual namespace, discovery registers nothing and you see no error. Symptom: container cannot resolve a core contract, "class not found" only in code paths you hit at runtime. Fix: register the provider manually in config/app.php and confirm with php artisan about.
Check Laravel major compatibility before anything else. A core package pins illuminate/* constraints that drift every 12 months. If composer.json targets an older major, do not downgrade your platform for an unproven dependency — the compatibility question answers the adoption question, and often in the negative.
Config publishing is a one-time copy, not a live link. Once published, edits go to config/kreta.php in your app. If the vendor package ships new config keys in an upgrade, vendor:publish --force will overwrite your changes. Diff the vendor config against yours on every package upgrade rather than blindly republishing.
config:cache will happily freeze a broken binding. Because config is merged from the provider, run php artisan config:clear and config:cache as part of your deploy and test the cached path. A merge that works in dev can behave differently after caching, particularly if a module's config is loaded conditionally.
Provider boot order is not guaranteed across packages. Never assume another feature module's provider has booted when yours does. If your module depends on a core service, resolve it lazily from the container inside methods, not in boot().
Prefer constructor injection over facades. Core packages sometimes ship facades for convenience. Facades hide which contract you depend on and make swapping the implementation harder, which matters because you may have to fork this package. Inject the interface.
Build a smoke test that pins the core contract. One test — boot the app, resolve each core contract, assert an instance is returned — catches the largest class of breakage on upgrade (renamed classes, changed constructors, dropped bindings) in a few lines.
Assume you may own this code. Given the ecosystem signals, a fork-ready posture is prudent. Keep kreta/core at arm's length: don't spread references to its concrete classes around the app, keep usage behind contracts and a single binding provider, and keep an eye on what would break if you replaced the package with a few hundred lines of in-house code. That boundary is the difference between a fork being a weekend and a quarter.
Debugging path, in order. (1) composer show kreta/core to see the installed version and its requires. (2) php artisan about --only=providers to confirm the provider is loaded. (3) php artisan tinker, then app()->make(\Kreta\Core\Contracts\X::class) — if that throws, it's a binding problem, not a downstream logic problem. (4) Check the source provider for the exact string it binds — often the mismatch is a concrete class bound where you expected a contract.
Extension points beat edits. Anything you customise in vendor code will be lost on the next composer update. If the package does not expose a hook for what you need, add a small adapter class in your app rather than patching the package — the adapter survives upgrades, the patch does not.
How can I help you explore Laravel packages today?