Building a Feature Extraction Engine for Laravel
The core engineering challenge in kit isn't building features — it's removing them cleanly. When a buyer selects Billing + Teams but not Notifications, the generated project can't have a single reference to notifications anywhere. No unused imports, no dead routes, no orphaned migrations.
Here's how the extraction system works.
The Annotation Layer
Every piece of code that belongs to a specific module gets annotated with a comment tag:
Annotations work in any file type:
The key insight: annotations mark entire files and individual code blocks within shared files. A route file might have some routes that belong to billing and others that belong to teams.
The Manifest
The features.json manifest is the single source of truth:
Dependencies are important. If billing depends on teams, selecting billing automatically includes teams. Users don't need to figure this out.
The Extraction Process
When extraction runs, it follows these steps:
Step 1: Resolve Dependencies
Given a set of selected features, expand the list to include all dependencies. If the user selected billing, the resolved set becomes billing + teams.
Step 2: Remove Annotated Files
Any file annotated with a feature that isn't in the resolved set gets deleted entirely:
Step 3: Strip Inline Annotations
For shared files that contain code blocks from multiple features, strip the unselected blocks:
Step 4: Clean Up Imports
After removing code blocks, there will be unused imports. The cleanup pass removes them:
Step 5: Remove Annotations
Finally, strip all #feature: comments from the remaining code. The buyer never sees the annotation system.

Validation
The extraction engine includes a validation step that runs after every extraction:
- Are there any dangling references to removed classes?
- Do all remaining routes resolve to existing controllers?
- Are there any orphaned migration files?
- Do the remaining tests pass?
If validation fails, the extraction aborts and reports what went wrong. This catches mistakes when I add new code and forget to annotate it properly.
The Hard Part: Shared Code
The trickiest aspect is code that's used by multiple modules. A User model might have relationships for teams, billing, and notifications. The extraction engine needs to selectively remove relationship methods without breaking the model.
The solution: annotate individual methods, not just files.
This granularity is what makes the system work. It's more work to maintain, but the output is worth it — every generated project looks like it was built from scratch. The CLI installer orchestrates this entire flow, from license validation to project delivery.