06 — Contributing
Getting Started
Prerequisites
- PHP 8.2+
- Composer
- Node.js 18+ & npm
- SQLite (for local development) or MySQL/PostgreSQL
Local Setup
# Clone the repository
git clone <repo-url> SchemaCraft
cd SchemaCraft
# Install PHP dependencies (includes the package via path repository)
composer install
# Set up environment
cp .env.example .env
php artisan key:generate
# Run migrations (creates the 5 schemacraft_* tables)
php artisan migrate
# Install and build frontend assets
npm install
npm run dev
# Start the dev server
php artisan serve
Visit http://localhost:8000/schemacraft to verify everything works.
Project Structure
Understanding where things live:
SchemaCraft/
├── packages/schemacraft/ <- THE PACKAGE (most work happens here)
│ ├── src/ <- PHP source code
│ │ ├── Http/Livewire/ <- Livewire components (Canvas, TableEditor, etc.)
│ │ ├── Models/ <- Eloquent models
│ │ ├── Enums/ <- ColumnType, RelationshipType
│ │ ├── Generators/ <- Code generation (MigrationGenerator)
│ │ └── Services/ <- Business logic services
│ ├── resources/views/ <- Blade templates + inline Alpine.js
│ ├── config/ <- Package config
│ ├── database/migrations/ <- Package migrations
│ └── routes/ <- Package routes
│
├── app/ <- Host Laravel app (minimal — mostly for SaaS features)
├── docs/ <- Documentation (you're reading it)
└── tests/ <- Test suite
Key principle: Almost all code goes in packages/schemacraft/. The host app is a thin wrapper.
Coding Conventions
PHP
- PHP 8.2+ — use typed properties, enums, match expressions, named arguments
- PSR-12 coding style
- Strict types — add
declare(strict_types=1);to all PHP files - Type hints — all method parameters and return types must be typed
- Models — use
$castsarray, define all relationships explicitly - No abbreviations —
$relationshipnot$rel,$columnnot$col
Livewire Components
- One component per file, matching the view name
- Use
#[Layout('schemacraft::layouts.app')]attribute for layout - Validate all user input before persisting
- Dispatch events for cross-component communication (e.g.,
table-updated) - Use
wire:model.blurinstead ofwire:model.livefor text inputs (reduces server calls)
Alpine.js
- All Alpine code is inline in Blade views (no separate JS files in the package)
- Use
x-data="componentName(...)"pattern with a named function - Keep Alpine state minimal — derive values with getters where possible
- Use
$wirefor Livewire communication,$dispatchfor Alpine-to-Alpine
Blade Views
- Views are namespaced as
schemacraft::(e.g.,schemacraft::livewire.canvas) - Use Tailwind CSS utility classes exclusively — no custom CSS
- Prefer Alpine.js directives over inline JavaScript
Database
- All package tables use
schemacraft_prefix - Use foreign key constraints with
cascadeOnDelete() - JSON columns for flexible/variable-shape data
- Soft deletes only on
projectstable
Naming
| Thing | Convention | Example |
|---|---|---|
| Tables (DB) | snake_case, plural, prefixed | schemacraft_tables |
| Models | PascalCase, singular | Table, Column |
| Livewire components | PascalCase | ProjectManager, TableEditor |
| Views | kebab-case | project-manager.blade.php |
| Config keys | snake_case | route_prefix, default_canvas |
| Enum cases | camelCase | hasMany, belongsToMany |
Git Workflow
Branch Naming
feature/short-description <- New features
fix/short-description <- Bug fixes
docs/short-description <- Documentation changes
refactor/short-description <- Code refactoring
Commit Messages
Use conventional commit format:
feat: add column reordering to table editor
fix: prevent duplicate table names in same project
docs: update architecture diagram
refactor: extract migration generation into service
test: add tests for MigrationGenerator
Pull Request Process
- Create a feature branch from
main - Make your changes in small, focused commits
- Ensure all tests pass:
php artisan test - Ensure code style is correct:
./vendor/bin/pint - Open a PR with:
- Clear description of what changed and why
- Screenshots for UI changes
- Test plan
Testing
Running Tests
# Run all tests
php artisan test
# Run specific test file
php artisan test --filter=MigrationGeneratorTest
# Run with coverage
php artisan test --coverage
Test Organization
tests/
├── Feature/
│ ├── ProjectManagerTest.php
│ ├── CanvasTest.php
│ └── ExportTest.php
└── Unit/
├── MigrationGeneratorTest.php
├── ColumnTypeTest.php
└── Models/
└── ProjectTest.php
What to Test
- Models: Relationships, casts, scopes
- Livewire components: User interactions, validation, state changes
- Generators: Output correctness for all column types and relationships
- Services: Business logic in isolation
Key Documents
If you're new to the project, read these in order:
- Project Overview — What we're building and why
- Architecture — How the system is designed
- Database Design — Data model and schema
- Phase 1 Implementation — Current build plan
- Roadmap — What's coming next
Questions?
If something in the codebase or docs is unclear, open an issue or ask in the team channel. Good documentation benefits everyone — if you figure something out that wasn't documented, please add it.