PHPackages                             logicoforms/laravel-forms - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. logicoforms/laravel-forms

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

logicoforms/laravel-forms
=========================

A Typeform-like forms system for Laravel with logic branching and AI builder.

1.1(2mo ago)03MITPHPPHP ^8.2

Since Mar 4Pushed 2mo agoCompare

[ Source](https://github.com/mzainzulifqar/logico-forms-plugin)[ Packagist](https://packagist.org/packages/logicoforms/laravel-forms)[ RSS](/packages/logicoforms-laravel-forms/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (2)Dependencies (4)Versions (3)Used By (0)

Laravel Forms
=============

[](#laravel-forms)

A Typeform-style forms package for Laravel with logic branching, an AI form builder, and a full UI out of the box.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 12+
- GD extension (for OG image generation)
- An AI provider API key (OpenAI, Anthropic, etc.) if using the AI builder

Installation
------------

[](#installation)

```
composer require logicoforms/laravel-forms
```

The service provider is auto-discovered. Publish the config and run migrations:

```
php artisan vendor:publish --tag=forms-config
php artisan migrate
```

If the `laravel/ai` migration doesn't run automatically, run it manually:

```
php artisan migrate --path=vendor/laravel/ai/database/migrations
```

### Local path install (development)

[](#local-path-install-development)

Add the path repository to your app's `composer.json`:

```
{
    "repositories": [
        {
            "type": "path",
            "url": "../packages/laravel-forms"
        }
    ],
    "require": {
        "logicoforms/laravel-forms": "@dev"
    }
}
```

Then run `composer update logicoforms/laravel-forms`.

Environment Variables
---------------------

[](#environment-variables)

Add these to your `.env` file. All are optional — sensible defaults are used when omitted.

```
# ── General ──────────────────────────────────────────────────────
FORMS_OWNER_MODEL="App\Models\User"          # Model that owns forms
FORMS_API_PREFIX=api                          # Prefix for public API routes
FORMS_API_RATE_LIMIT=60,1                     # API throttle (requests,minutes)

# ── URLs ─────────────────────────────────────────────────────────
FORMS_URL_EDIT=/logico/forms/{id}/edit         # Edit URL pattern (used by AI builder)
FORMS_URL_PUBLIC=/f/{slug}                    # Public form URL pattern

# ── Branding ─────────────────────────────────────────────────────
FORMS_BRAND_NAME="My App"                     # Shown in nav & OG images
FORMS_BRAND_DOMAIN=myapp.com                  # Shown in OG images
FORMS_BRAND_TAGLINE="Smart forms for everyone"
FORMS_BRAND_LOGO_URL=/logo.svg                # Logo URL for nav

# ── AI Provider Keys (required for AI builder) ──────────────────
OPENAI_API_KEY=                               # Required if using OpenAI
ANTHROPIC_API_KEY=                            # Required if using Anthropic

# ── AI Builder ───────────────────────────────────────────────────
FORMS_AI_BUILDER_PROVIDER=                    # e.g. openai, anthropic (auto-detected if blank)
FORMS_AI_BUILDER_MODEL=gpt-5.2               # Model for form generation
FORMS_AI_BUILDER_TIMEOUT=120                  # Max seconds per AI request
FORMS_AI_BUILDER_ENFORCE_QUALITY=true         # Reject lazy branching patterns

# ── AI Critic (optional quality reviewer) ────────────────────────
FORMS_AI_CRITIC_ENABLED=true                  # Enable AI quality review
FORMS_AI_CRITIC_MODE=on_pass                  # When to run critic
FORMS_AI_CRITIC_PROVIDER=                     # Provider (defaults to builder provider)
FORMS_AI_CRITIC_MODEL=gpt-4o                  # Critic model
FORMS_AI_CRITIC_TIMEOUT=25                    # Critic timeout in seconds
FORMS_AI_CRITIC_MAX_ATTEMPTS=2                # Max retry attempts
```

> **Note:** The AI builder requires the `laravel/ai` package. Make sure you also configure your AI provider's API key in `laravel/ai`'s config (e.g. `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`).

Setup
-----

[](#setup)

### 1. Implement `FormOwner` on your User model

[](#1-implement-formowner-on-your-user-model)

```
use Logicoforms\Forms\Contracts\FormOwner;
use Logicoforms\Forms\Models\Form;
use Illuminate\Database\Eloquent\Relations\HasMany;

class User extends Authenticatable implements FormOwner
{
    public function forms(): HasMany
    {
        return $this->hasMany(Form::class, 'created_by');
    }
}
```

### 2. Configure (optional)

[](#2-configure-optional)

Edit `config/forms.php` after publishing. Key options:

```
return [
    // The model that owns forms
    'owner_model' => App\Models\User::class,

    // URL patterns used by the AI builder when generating links
    'urls' => [
        'edit'   => '/forms/{id}/edit',
        'public' => '/f/{slug}',
    ],

    // Set to false to define your own web routes
    'register_web_routes' => true,

    // Middleware for authenticated routes
    'auth_middleware' => ['web', 'auth'],

    // Branding shown in nav and OG images
    'brand' => [
        'name'    => 'My App',
        'domain'  => 'myapp.com',
        'tagline' => 'Smart forms for everyone',
    ],

    // Override view partials (or set to null to disable)
    'views' => [
        'nav'       => 'forms::partials.nav', // or your own: 'partials.my-nav'
        'analytics' => null,                   // e.g. 'partials.gtag'
    ],

    // AI builder settings (requires laravel/ai)
    'ai_builder' => [
        'provider' => null, // auto-detected from laravel/ai config
        'model'    => 'gpt-4o',
        'timeout'  => 120,
    ],
];
```

### 3. Implement `FormLimiter` (optional)

[](#3-implement-formlimiter-optional)

By default the package uses `NullFormLimiter` which imposes no limits. To add plan-based restrictions, create your own implementation:

```
use Logicoforms\Forms\Contracts\FormLimiter;

class AppFormLimiter implements FormLimiter
{
    public function maxResponsesPerForm($owner): ?int
    {
        return null; // unlimited
    }

    public function canCreateForm($owner): bool
    {
        return $owner->forms()->count() < 100;
    }

    public function canRemoveBranding($owner): bool
    {
        return false;
    }

    public function canUseCustomThemes($owner): bool
    {
        return true;
    }

    public function canAccessAiBuilder($owner): bool
    {
        return true;
    }

    public function hasAiCredits($owner): bool
    {
        return true;
    }

    public function deductAiCredit($owner): void
    {
        // no-op
    }

    public function getAiCreditBalance($owner): ?int
    {
        return null; // unlimited
    }

    public function formLimitRedirectUrl(): ?string
    {
        return null; // shows generic error
    }
}
```

Register it in your `AppServiceProvider`:

```
use Logicoforms\Forms\Contracts\FormLimiter;

public function register(): void
{
    $this->app->singleton(FormLimiter::class, AppFormLimiter::class);
}
```

What's included
---------------

[](#whats-included)

### Routes

[](#routes)

The package registers both API and web routes automatically.

**Web routes** (configurable via `register_web_routes`):

MethodURIDescriptionGET`/f/{slug}`Public form viewGET`/f/{slug}/og-image.png`OG imageGET`/logico/forms`Forms listGET`/logico/forms/create`Create formGET`/logico/forms/{form}/edit`Form editorGET`/logico/forms/{form}`Responses viewerGET`/logico/forms/{form}/logic-tree`Logic tree visualizerGET`/logico/forms/templates`Template galleryGET`/logico/forms/ai-builder`AI form builder**API routes** (always registered):

MethodURIDescriptionPOST`/api/forms/{form}/sessions`Start a sessionPOST`/api/forms/{form}/sessions/{uuid}/answers`Submit an answerPOST`/api/forms/{form}/sessions/{uuid}/complete`Complete session### Models

[](#models)

- `Form` — title, slug, status, theme, end screen
- `FormQuestion` — type, text, help text, settings, ordering
- `QuestionOption` — label, value, image URL
- `QuestionLogic` — operator, value, next question routing
- `FormSession` — tracks a respondent's progress
- `FormAnswer` — stores individual answers
- `FormThemePreset` — reusable theme configurations

### Question types

[](#question-types)

`text`, `email`, `number`, `select`, `radio`, `checkbox`, `rating`, `picture_choice`, `opinion_scale`

### Logic branching

[](#logic-branching)

Each question can have logic rules that route respondents to different questions based on their answers. Supported operators: `equals`, `not_equals`, `is`, `is_not`, `greater_than`, `less_than`, `contains`, `not_contains`, `begins_with`, `ends_with`, `always`, and more.

### AI builder

[](#ai-builder)

The AI builder creates forms from natural language descriptions. It generates questions, options, and logic rules automatically. Requires `laravel/ai` and an API key for your chosen provider.

Set up the queue worker for AI builder to function:

```
php artisan queue:work
```

### Events

[](#events)

The package dispatches events instead of logging directly, so you can listen to them in your app:

EventPayload`FormCreated``Form $form`, `array $metadata``FormUpdated``Form $form``FormDeleted``int $formId`, `string $formTitle``QuestionChanged``Form $form`, `string $action`, `array $metadata``AiBuilderUsed``array $metadata`### Views

[](#views)

All views are published under the `forms` namespace. Override any view by publishing:

```
php artisan vendor:publish --tag=forms-views
```

This copies views to `resources/views/vendor/forms/` where you can customize them.

Customizing the navigation
--------------------------

[](#customizing-the-navigation)

The dashboard includes a configurable nav partial. Set `forms.views.nav` in config to point to your own Blade partial:

```
'views' => [
    'nav' => 'partials.my-nav', // your app's nav
],
```

Set it to `null` to disable the nav entirely.

Querying Forms &amp; Responses
------------------------------

[](#querying-forms--responses)

All package models are available for direct use. Import from `Logicoforms\Forms\Models\*`.

### Get a user's forms

[](#get-a-users-forms)

```
use Logicoforms\Forms\Models\Form;

$forms = $user->forms;

// Only published
$published = $user->forms()->where('status', 'published')->get();

// With question and session counts
$forms = Form::where('created_by', $user->id)
    ->withCount(['questions', 'sessions'])
    ->latest()
    ->get();
```

### Get form questions with options

[](#get-form-questions-with-options)

```
$form = Form::with('questions.options')->find($formId);

foreach ($form->questions as $question) {
    echo $question->question_text; // "How likely are you to recommend us?"
    echo $question->type;          // radio, text, rating, etc.

    foreach ($question->options as $option) {
        echo $option->label; // "Very likely"
        echo $option->value; // "very_likely"
    }
}
```

### Get completed responses for a form

[](#get-completed-responses-for-a-form)

```
use Logicoforms\Forms\Models\FormSession;

$sessions = FormSession::where('form_id', $formId)
    ->where('is_completed', true)
    ->with('answers.question')
    ->latest()
    ->get();

foreach ($sessions as $session) {
    echo $session->session_uuid;
    echo $session->created_at;

    foreach ($session->answers as $answer) {
        echo $answer->question->question_text;
        echo $answer->answer_value; // string or array (for checkbox)
    }
}
```

### Get answers for a specific question

[](#get-answers-for-a-specific-question)

```
use Logicoforms\Forms\Models\FormAnswer;

$answers = FormAnswer::where('question_id', $questionId)
    ->whereHas('session', fn ($q) => $q->where('is_completed', true))
    ->pluck('answer_value');
```

### Count responses

[](#count-responses)

```
$form = Form::withCount([
    'sessions',
    'sessions as completed_count' => fn ($q) => $q->where('is_completed', true),
])->find($formId);

echo $form->sessions_count;  // total started
echo $form->completed_count; // total completed
```

### Aggregate answers (averages, breakdowns)

[](#aggregate-answers-averages-breakdowns)

```
// Average rating
$avg = FormAnswer::where('question_id', $ratingQuestionId)
    ->whereHas('session', fn ($q) => $q->where('is_completed', true))
    ->get()
    ->avg(fn ($a) => (float) $a->answer_value);

// Option breakdown for radio/select
$breakdown = FormAnswer::where('question_id', $radioQuestionId)
    ->whereHas('session', fn ($q) => $q->where('is_completed', true))
    ->get()
    ->countBy(fn ($a) => $a->answer_value);
// Returns: ['very_likely' => 12, 'not_likely' => 3, ...]
```

### Filter responses by date

[](#filter-responses-by-date)

```
$sessions = FormSession::where('form_id', $formId)
    ->where('is_completed', true)
    ->whereBetween('created_at', [$startDate, $endDate])
    ->with('answers')
    ->get();
```

### Export-friendly: all responses as rows

[](#export-friendly-all-responses-as-rows)

```
$form = Form::with('questions')->find($formId);
$questions = $form->questions;

$rows = FormSession::where('form_id', $formId)
    ->where('is_completed', true)
    ->with('answers')
    ->get()
    ->map(function ($session) use ($questions) {
        $row = [
            'uuid' => $session->session_uuid,
            'completed_at' => $session->updated_at,
        ];
        foreach ($questions as $q) {
            $answer = $session->answers->firstWhere('question_id', $q->id);
            $val = $answer?->answer_value;
            $row[$q->question_text] = is_array($val) ? implode(', ', $val) : $val;
        }
        return $row;
    });
```

Claude Code Skill
-----------------

[](#claude-code-skill)

The package ships with a [Claude Code](https://claude.com/claude-code) skill that lets you create forms, add logic, review quality, export responses, and debug issues — all from the CLI.

### Setup

[](#setup-1)

Copy the skill into your project's `.claude/skills/` directory:

```
mkdir -p .claude/skills/forms
cp vendor/logicoforms/laravel-forms/.claude/skills/forms/SKILL.md .claude/skills/forms/SKILL.md
```

Or if you're using a path repository (development):

```
mkdir -p .claude/skills/forms
cp ../packages/laravel-forms/.claude/skills/forms/SKILL.md .claude/skills/forms/SKILL.md
```

### Usage

[](#usage)

Once installed, use `/forms` followed by what you want to do:

```
/forms create a customer feedback survey with NPS branching
/forms review form 3 for logic issues
/forms add branching to form 5 based on the role question
/forms export responses for form 3 as CSV
/forms debug why form 3 never completes
/forms show me the routes this package registers

```

The skill knows the full package API — models, logic engine, routes, events, config, and common debugging patterns.

Testing
-------

[](#testing)

```
cd packages/laravel-forms
composer install
./vendor/bin/phpunit
```

License
-------

[](#license)

MIT

###  Health Score

37

—

LowBetter than 83% of packages

Maintenance85

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

75d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/5e0b47f05e4236bedac0ae6c31077cf593002fce4efd33df4bedb770fb5a8f60?d=identicon)[zainzulifqar](/maintainers/zainzulifqar)

---

Top Contributors

[![mzainzulifqar](https://avatars.githubusercontent.com/u/50246160?v=4)](https://github.com/mzainzulifqar "mzainzulifqar (8 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/logicoforms-laravel-forms/health.svg)

```
[![Health](https://phpackages.com/badges/logicoforms-laravel-forms/health.svg)](https://phpackages.com/packages/logicoforms-laravel-forms)
```

###  Alternatives

[wireui/wireui

TallStack components

1.8k1.3M16](/packages/wireui-wireui)[livewire/volt

An elegantly crafted functional API for Laravel Livewire.

4195.3M84](/packages/livewire-volt)[ramonrietdijk/livewire-tables

Dynamic tables for models with Laravel Livewire

21147.4k](/packages/ramonrietdijk-livewire-tables)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
