| name | unopim-connector-quickstart |
| description | Day-1 checklist and step-by-step guide to build a complete Unopim third-party connector (WooCommerce, Shopify, Shopware, module, or any REST API) within one working day. Use this skill when starting a new Unopim integration, planning a connector from scratch, or needing the full ordered sequence of steps to create a production-ready connector module. Covers all required files, patterns, and critical checkpoints verified against the WooCommerce connector reference implementation.
|
| version | 2.0.0 |
| tags | ["unopim","connector","integration","quickstart","scaffold","woocommerce","shopify","shopware"] |
Unopim Connector Quickstart: Day-1 Guide
Reference Implementation
All patterns in this guide are verified against the production WooCommerce
connector: packages/Webkul/WooCommerce/. When in doubt, refer to that
package's source code.
Prerequisites (15 min)
Admin UI Rule (CRITICAL)
For all admin Blade forms in connector modules, use UnoPim Blade components first.
- Use
x-admin::form.control-group wrappers.
- Use
x-admin::form.control-group.label and x-admin::form.control-group.error.
- Use
x-admin::form.control-group.control for inputs/selects/textareas.
- Do not generate raw
<select>, <input>, <textarea>, or <label> markup when component equivalents are available.
- Use translations for all labels/placeholders/messages.
For select fields, use component select (type="select") with :options="json_encode(...)", track-by, label-by, and Vue @input binding.
Before coding:
- Confirm the external API authentication type (Basic Auth / Bearer Token / OAuth)
- Note the API base URL pattern (e.g.
/wp-json/wc/v3/, /api/v1/, etc.)
- Decide what entities to sync: Products, Categories, Attributes, Customers, Orders
- List which direction: export only / import only / bidirectional
Phase 1 ā Scaffolding (1ā2 hours)
Step 1: Create directory structure
packages/Webkul/{ModuleName}/
āāā Config/
āāā Routes/
āāā Database/
ā āāā Migration/ ā NOT "Migrations" (singular)
ā āāā Factories/
āāā Resources/
ā āāā lang/en/
ā āāā views/
āāā src/
āāā Providers/
āāā Models/
āāā Contracts/
āāā Repositories/
āāā Http/
ā āāā Controllers/
ā āāā Requests/
ā āāā Client/
āāā DataGrids/
ā āāā Credential/
āāā Services/
āāā Helpers/
ā āāā Exporters/
ā ā āāā Product/
ā ā āāā Category/
ā ā āāā Attribute/
ā āāā Importers/
ā āāā Product/
āāā Validators/
ā āāā JobInstances/
ā āāā Export/
ā āāā Import/
āāā Presenters/
Step 2: composer.json
{
"name": "webkul/{module-name}",
"type": "library",
"autoload": {
"psr-4": { "Webkul\\{ModuleName}\\": "src/" }
},
"extra": {
"laravel": {
"providers": ["Webkul\\{ModuleName}\\Providers\\{ModuleName}ServiceProvider"]
}
}
}
Step 3: {ModuleName}ServiceProvider
Critical rules:
- Routes:
Route::middleware('web')->group(...) ā NOT $this->loadRoutesFrom()
- Event:
unopim.admin.layout.head.before ā NOT without .before
- Register
ModuleServiceProvider inside register()
public function boot(): void
{
Route::middleware('web')->group(__DIR__ . '/../../Routes/{module-name}-routes.php');
$this->loadViewsFrom(...);
$this->loadTranslationsFrom(...);
$this->loadMigrationsFrom(__DIR__ . '/../../Database/Migration');
Event::listen('unopim.admin.layout.head.before', function ($viewRenderEventManager) {
$viewRenderEventManager->addTemplate('{module-name}::layouts.head');
});
}
public function register(): void
{
$this->app->register(ModuleServiceProvider::class);
$this->registerConfig();
}
protected function registerConfig(): void
{
$this->mergeConfigFrom(..., 'acl');
$this->mergeConfigFrom(..., 'menu');
$this->mergeConfigFrom(..., 'exporters');
$this->mergeConfigFrom(..., 'quick_exporters');
$this->mergeConfigFrom(..., 'importers');
}
Step 4: ModuleServiceProvider
class ModuleServiceProvider extends CoreModuleServiceProvider
{
protected $models = [
\Webkul\{ModuleName}\Models\Credential::class,
];
}
Phase 2 ā Database & Model (1 hour)
Step 5: Migration
- File in:
Database/Migration/ (NOT Database/Migrations/)
- Table name:
{module}_credentials (DB_PREFIX added automatically by Laravel)
- Column names: camelCase matching model
$fillable (e.g. apiUrl, consumerKey)
- Include
extras JSON column for flexible extra config
Schema::create('{module}_credentials', function (Blueprint $table) {
$table->id();
$table->string('label');
$table->string('apiUrl');
$table->string('consumerKey');
$table->string('consumerSecret');
$table->json('extras')->nullable();
$table->boolean('status')->default(true);
$table->timestamps();
});
Step 6: Contract Interface
src/Contracts/Credential.php ā interface Credential {}
Step 7: Credential Model
class Credential extends Model implements CredentialContract, PresentableHistoryInterface
{
use HasFactory, HistoryTrait;
protected $table = '{module}_credentials';
protected $casts = ['extras' => 'array', 'status' => 'boolean'];
protected $auditExclude = ['consumerSecret'];
}
Step 8: CredentialRepository
class CredentialRepository extends Repository
{
public function model(): string { return Credential::class; }
}
Phase 3 ā HTTP Client (30 min)
Step 9: cURL-based ApiClient
Unopim connectors use native cURL ā NOT Guzzle, NOT Laravel HTTP facade.
src/Http/Client/
āāā ApiClient.php ā curl_init / curl_exec / curl_close
āāā BasicAuth.php ā curl_setopt(CURLOPT_HTTPAUTH)
Key methods: configure(), buildApiUrl(), get(), post(), put(), delete()
Step 10: Service class wraps all API calls
src/Services/{ModuleName}Service.php
Controllers inject {ModuleName}Service, never ApiClient directly.
Phase 4 ā CRUD Controller & Routes (1 hour)
Step 11: FormRequest
src/Http/Requests/CredentialForm.php
Never use inline $request->validate() in controllers.
Step 12: CredentialController
- Returns
JsonResponse with redirect_url for store/update/delete
- Inject
CredentialRepository and {ModuleName}Service
testConnection() method for API connectivity check
Step 13: Routes
Route::group(['middleware' => ['admin'], 'prefix' => config('app.admin_url')], function () {
});
Phase 5 ā Admin UI (1 hour)
Step 14: ACL (flat array ā no nested children)
return [
['key' => '{module-slug}', 'name' => '...', 'route' => '...', 'sort' => 1],
['key' => '{module-slug}.credentials', ...],
['key' => '{module-slug}.credentials.create', ...],
['key' => '{module-slug}.credentials.edit', ...],
['key' => '{module-slug}.credentials.delete', ...],
];
Step 15: DataGrid
src/DataGrids/Credential/CredentialDataGrid.php
Rules:
DB::table('{module}_credentials') in prepareQueryBuilder()
- Methods have PHPDoc
@return only (no PHP type hints)
- Column
closure uses fn ($row) => (arrow function)
- Action
url uses function ($row) { return route(...); } (regular function)
- Status badges:
label-active / label-info text-gray-600 dark:text-gray-300
Step 16: Blade views
views/credentials/index.blade.php ā <x-admin::datagrid :src="route(...)" />
views/credentials/create.blade.php
views/credentials/edit.blade.php
Phase 6 ā Export/Import Workflow (2 hours)
Step 17: exporters.php (every select field MUST have these 4 keys)
[
'name' => 'credential',
'type' => 'select',
'async' => true, ā required
'track_by' => 'id', ā required
'label_by' => 'label', ā required
'list_route' => '{module-slug}.credentials.get', ā required
]
Step 18: quick_exporters.php (one-click from product listing)
'{ModuleName}QuickExport' => [
'title' => '...',
'route' => '{module-slug}.quick_export',
'exporter' => ...,
'source' => \Webkul\Product\Repositories\ProductRepository::class,
];
Step 19: importers.php (same filter field structure as exporters)
Step 20: Exporter & Importer classes
src/Helpers/Exporters/{Entity}/Exporter.php ā extends AbstractExporter
src/Helpers/Importers/{Entity}/Importer.php ā extends AbstractImporter
Each exporter needs: BATCH_SIZE, UNOPIM_ENTITY_NAME, ACTION_ADD, ACTION_UPDATE, CODE_ALREADY_EXIST, CODE_NOT_EXIST
Step 21: Validator classes
src/Validators/JobInstances/Export/ProductsValidator.php
src/Validators/JobInstances/Import/ProductsValidator.php
Phase 7 ā Lang & Final Polish (30 min)
Step 22: Translation file
return [
'credentials' => [
'create-success' => 'Credential created successfully.',
'update-success' => 'Credential updated successfully.',
'delete-success' => 'Credential deleted successfully.',
'test-success' => 'Connection successful.',
'test-failed' => 'Connection failed. Check credentials.',
],
];
Step 23: Register provider
Add to bootstrap/providers.php:
\Webkul\{ModuleName}\Providers\{ModuleName}ServiceProvider::class,
Complete Checklist (in order)
Scaffolding
Database
Model
Routes & Controller
HTTP Client
DataGrid
Export/Import
ACL
Skill Cross-Reference
| Topic | Skill to use |
|---|
| Full module scaffold | unopim-package |
| Credential CRUD + model | unopim-credential-management |
| cURL HTTP client | unopim-http-client |
| Export/import jobs | unopim-export-workflow |
| DataGrid listing | unopim-datagrid |
| module mapping | unopim-connector-export-mapping |