Why we're building Tapix | Tapix                  [ ![Tapix](/img/tapix-logo-light.svg) ![Tapix](/img/tapix-logo-dark.svg) ](https://tapix.dev)   Try Demo  [Pre-order for $59 $99](https://tapix.dev#pricing)

    Try Demo  [Pre-order for $59 $99](https://tapix.dev#pricing)

   ![Tapix](https://tapix.dev/img/tapix-logo-light.svg)

 ProductWhy we're building Tapix
========================

 tapix.dev/blog

  [    Back to blog ](https://tapix.dev/blog) [ Product ](https://tapix.dev/blog/category/product)

Why we're building Tapix
========================

 Manch Minasyan ·  April 17, 2026  · 7 min read

 I spent three weeks building a contact importer for Relaticle CRM. Three weeks. Not because the problem was hard to understand -- read a CSV, validate the rows, insert them into the database. The problem was hard to solve well. Column mapping, inline validation, relationship linking, queue processing, error recovery, multi-tenancy. Each one reasonable on its own. All six together? That is where every import project quietly falls apart.

This is the story of how that experience turned into Tapix.

[\#](#building-relaticle "Permalink")Building Relaticle
-------------------------------------------------------

Relaticle is an open-source CRM built with Laravel and Filament. It has over 1,000 stars on GitHub now, which still surprises me. I started it because I wanted a CRM that developers could actually extend -- not a black box SaaS with a plugin marketplace, but real Laravel code you can read and modify.

The feature requests came quickly once people started using it. Most were predictable: custom fields, pipeline views, contact management. But one request showed up more than any other, from the first month onward: CSV import.

Every CRM user has contacts somewhere else. In a spreadsheet, in another CRM's export, in a vendor's system. The first thing they want to do is bring that data in. I knew I would have to build it eventually. I underestimated how long "eventually" would take.

[\#](#the-import-that-took-three-weeks "Permalink")The import that took three weeks
-----------------------------------------------------------------------------------

The naive version took an afternoon. Read the CSV with `fgetcsv`, loop through rows, create Contact models. It worked for my test file of 50 rows. Then I gave it to a beta tester.

Their CSV had "First Name" as the header, not `first_name`. Their email column had blank cells, entries like "N/A", and one row that just said "see notes". Their company column referenced companies that did not exist yet. Their file was 12,000 rows and the import timed out.

I started solving these problems one at a time. Column mapping meant building a UI where users match their CSV headers to the expected fields, plus auto-detection for common synonyms like "fname", "given name", and "first". Validation meant running rules against every cell and letting users fix errors before import, not after. The company column meant implementing find-or-create logic -- if "Acme Corp" exists, link to it; if not, create it. Scale meant moving to queued jobs with chunked processing. Error recovery meant tracking which rows failed and why, so users could fix and retry without re-uploading.

Each of these is a real engineering problem. Column mapping alone required a matching algorithm, a drag-and-drop UI, and persistent state so the wizard survives page refreshes. Validation required per-column job batches running in parallel. Relationship linking required a configurable match-or-create system that works for BelongsTo, MorphToMany, and other Eloquent relationships.

Three weeks later, Relaticle had a solid contact importer. It handled messy real-world data, scaled to large files, and gave users control over the process. I was proud of it. I was also annoyed that I would have to build it again for every model that needed import -- companies, deals, activities.

[\#](#the-pattern-i-kept-seeing "Permalink")The pattern I kept seeing
---------------------------------------------------------------------

Relaticle was not my first open-source Laravel package. I had already built FlowForge (kanban boards, over 40,000 downloads), Custom Fields (dynamic user-defined fields, over 25,000 downloads), and FilaForms (a visual form builder at filaforms.app). Each package came from the same pattern: I built something for a specific project, realized the problem was universal, and extracted it.

CSV import followed the same arc, but the stakes were higher. Every Laravel project that deals with external data eventually needs an import feature. Agencies rebuild it per client. SaaS products rebuild it per module. Internal tools rebuild it per spreadsheet the operations team sends over.

And every time, the same five problems show up:

**Column mapping.** Every user's CSV is different. Headers vary, column order varies, some columns are missing, some are extra. You cannot hardcode a column-to-field mapping and call it done.

**Validation.** Bad data is the norm, not the exception. Blank cells, wrong formats, values that do not match your constraints. Users need to see and fix these errors before the import runs, not get a stack trace after.

**Relationships.** A CSV is flat. Your database is relational. The "Company" column needs to resolve to a `company_id` foreign key. The "Tags" column needs to create or match multiple records. This is where most DIY importers give up.

**Scale.** A hundred rows works synchronously. Ten thousand rows needs a queue. A hundred thousand rows needs chunked batches with progress tracking and automatic retry. The architecture is fundamentally different.

**User experience.** Developers often build importers for themselves -- upload a file, see a success message. Real users need a wizard: preview their data, correct mappings, fix validation errors, monitor progress, handle failures. That is a full frontend feature, not an afterthought.

[\#](#what-exists-today "Permalink")What exists today
-----------------------------------------------------

The Laravel ecosystem has strong tools, but nothing that covers the full problem.

**Laravel Excel** is the standard. Over 145 million downloads, rock-solid for reading and writing spreadsheets. But it is a library, not a UI. You get programmatic access to file contents. The mapping, validation, wizard, and queue orchestration are still your problem.

**Filament's Import Action** ships with Filament and works well for simple flat-table imports. Define your columns, map them, import. For a table with no relationships, no complex validation, and modest file sizes, it is a reasonable choice. But it is tightly coupled to Filament, has no step-by-step wizard, and relationship handling requires significant custom code.

**Hosted SaaS platforms** -- CSVBox, OneSchema, Flatfile -- solve the UX problem well. Polished wizards, drag-and-drop mapping, client-side validation. But your data leaves your server. For a $19/month tool processing customer PII through a third-party iframe, the tradeoff does not make sense for most Laravel applications. Your data should stay in your infrastructure.

There is a thorough breakdown of all these approaches in our [complete guide to CSV imports in Laravel](/blog/complete-guide-csv-imports-laravel).

[\#](#the-gap "Permalink")The gap
---------------------------------

What does not exist is a self-hosted, full-stack import wizard that works with any Laravel application.

Something you install with `composer require`, configure in five minutes, and have running with three lines of code. Something that gives your users a four-step wizard -- upload, map, review, import -- with smart column matching, inline error correction, and live progress tracking. Something that handles relationships natively, runs imports through Laravel's queue system with chunked batches, and supports multi-tenancy out of the box.

That is Tapix.

It is not a library you build a UI on top of. It is not a Filament-only feature. It is a complete import system -- backend processing, Livewire wizard, Filament integration, and standalone mode -- in one package. Define your fields, configure your relationships, and the wizard handles everything from file upload to database insertion.

The importer definition is intentionally concise. You declare your fields, their types, validation rules, and relationships. Tapix handles the column matching, the validation pipeline, the queue orchestration, and the user-facing wizard. The ContactImporter I originally built for Relaticle in three weeks now takes about 30 lines of configuration.

[\#](#what-is-next "Permalink")What is next
-------------------------------------------

Tapix is in early access now. I have been working on it full-time -- the core engine, the Livewire wizard, the Filament plugin, the queue pipeline, the multi-tenancy layer. The architecture is proven; it powers Relaticle's import system in production today.

Early access customers get up to 40% off launch pricing, access to early builds, and direct input on the feature roadmap. If you have ever spent days building a CSV importer and thought "there has to be a better way" -- there is.

[Get early access to Tapix](/#pricing)

 ### Enjoyed this post?

Get notified when we publish new articles about Laravel imports and data handling.

  Email address   Subscribe

Almost there — confirm your subscription via email.

  [ ![Tapix](/img/tapix-logo-light.svg) ![Tapix](/img/tapix-logo-dark.svg) ](https://tapix.dev)CSV and Excel import wizard for Laravel.

  Product [Pricing](https://tapix.dev#pricing) [Docs](https://docs.tapix.dev) [Blog](https://tapix.dev/blog) [Contact](mailto:hello@tapix.dev)

 Compare [vs Laravel Excel](https://tapix.dev/vs/laravel-excel) [vs Filament Import](https://tapix.dev/vs/filament-import)

 Legal [Privacy](https://tapix.dev/privacy-policy) [Terms](https://tapix.dev/terms-of-service)

© 2026 Tapix. All rights reserved.
