Getting Started


Server Requirements

To run SetSail - Laravel SaaS Starter Kit properly, make sure your server meets the following minimum requirements:

  • PHP >= 8.2.0
  • MySQL 5.7+ or MariaDB 10.3+
  • BCMath PHP Extension
  • Ctype PHP Extension
  • Fileinfo PHP Extension
  • JSON PHP Extension
  • Mbstring PHP Extension
  • OpenSSL PHP Extension
  • PDO PHP Extension
  • Tokenizer PHP Extension
  • XML PHP Extension
  • Curl PHP Extension
  • Imagick PHP Extension
  • Zip PHP Extension

Browsers

This application is compatible with all modern browsers. Please ensure JavaScript is enabled for optimal performance.


Build Tools

  1. Laravel
  2. Filament
  3. Tailwind CSS
  4. Alpine.js
  5. Livewire
  6. Heroicons
  7. Phosphor Icons
  8. Vite
  9. Spatie Laravel Permission

Installation

To install SetSail, you need a local PHP development environment with PHP ≥ 8.2 and MySQL. You may use Laravel Valet, Laragon, XAMPP, MAMP, or any environment you're comfortable with.

Installation Steps

  1. Unzip the Downloaded File
    Extract the contents of the ZIP file you downloaded from CodeCanyon.
  2. Move to Your Development Directory
    Rename the extracted folder if you want, then move it to your preferred development path (e.g., ~/Sites).
  3. Copy the .env File
    In the terminal, navigate to the project folder and run:
    cp .env.example .env
  4. Install PHP Dependencies
    Run the following command to install Composer dependencies:
    composer install
  5. Generate Application Key
    php artisan key:generate
  6. Configure the Database
    Update the .env file with your database credentials:
    DB_CONNECTION=mysql
    DB_HOST=127.0.0.1
    DB_PORT=3306
    DB_DATABASE=your_database
    DB_USERNAME=your_username
    DB_PASSWORD=your_password
  7. Run Migrations and Seeders
    php artisan migrate --seed
  8. Install Frontend Dependencies
    npm install
  9. Build Frontend Assets
    npm run build
  10. Start Your Local Server
    php artisan serve
    Visit http://localhost:8000 in your browser.

Login Credentials

After installation, use the following default credentials to log in:

  • Email: admin@example.com
  • Password: password

You can change these credentials in the user settings after logging in.

You're Ready!

SetSail is now installed and ready to use. Extend it however you like and start building your SaaS application!


Local Development

SetSail uses Laravel Vite for compiling frontend assets and enabling fast hot-reloading in development. Follow the steps below to set up your local environment.

Install Node Dependencies

From the root of your project, run the following command:

npm install

This will install all frontend dependencies including Tailwind CSS, Alpine.js, and Vite.

Start Asset Watcher

To enable live-reload and development compilation, run:

npm run dev

This will start the asset watcher. Whenever you update frontend code (Blade templates, Tailwind classes, JavaScript, etc.), Vite will automatically refresh the page or inject changes.

Build Assets for Production

When you're ready to deploy your app, compile and minify your assets by running:

npm run build

This step ensures that all assets are optimized for speed and performance in a production environment.

Optimize Laravel for Production

To further enhance performance, you can optimize the Laravel application by running:

php artisan optimize

This will cache routes, configuration, and views for improved performance.

Optimize Filament

If your project uses Filament Admin Panel, you can cache its components and icons for faster rendering by running:

php artisan filament:optimize

You're now ready to build and extend your SaaS app with full development tools in place.


Customizations

SetSail is designed to be fully customizable. Below are a few common areas you might want to personalize right away, including your logo, favicon, primary color, and authentication views.

Change Your Logo

Update the default logo by editing the following Blade components:

  • resources/views/components/logo.blade.php – Full logo (icon + name)
  • resources/views/components/logo-icon.blade.php – Icon-only version

Each file contains an SVG tag like this:

<svg {{ $attributes->merge(['class' => 'text-gray-900 dark:text-white']) }} ... ></svg>

You can replace the SVG with your own SVG markup, or use an <img> tag:

<img src="/images/your-logo.png" {{ $attributes->merge(['class' => 'h-8']) }} />

This approach preserves passed attributes like class names when using the component:

<x-logo class="h-8" />

Change Your Favicon

Replace the default favicon files to reflect your brand:

  • public/setsail/favicon.png – Light mode favicon
  • public/setsail/favicon-dark.png – Dark mode favicon
  • public/favicon.ico – Optional for older browsers

You can also customize the favicon component located at:

resources/views/components/favicon.blade.php

Change the Default Color

Update the primary color used throughout the UI by modifying:

config/setsail.php
'primary_color' => '#1DA1F2',

Authentication Views

SetSail uses DevDojo Auth for authentication. To customize the design of login, register, and reset-password views, visit:

/auth/setup
Auth Setup

From this interface, you can customize layout, logo, color scheme, background, and alignment of the authentication forms.


Features


Authentication

SetSail is built on top of DevDojo Auth, providing all the essential authentication features required for most SaaS applications. You can easily customize login pages, enable 2FA, and configure social logins without extra setup.

Auth Customizations

SetSail comes with a powerful setup interface available at /auth/setup. From here, you can:

  • Upload your logo
  • Change your color scheme
  • Toggle social login providers
  • Enable email verification and more

Available Authentication Pages

Out of the box, SetSail includes the following authentication-related pages:

  • Login
  • Register
  • Verify Email
  • Password Confirmation
  • Password Reset Request
  • Password Reset
  • Two-Factor Challenge

Login

Users can log in by visiting the /auth/login route. Upon successful login, they are redirected to the dashboard. A default admin account is included upon installation:

email: admin@example.com
password: password

Registration

By default, user registration is open to everyone. If you'd like to restrict access to subscribed users, you can apply the subscribed middleware to routes instead of auth.

This middleware checks if the user is logged in and has an active subscription. You can also use this to offer a free tier with limited features and encourage upgrades.

To customize registration behavior, update the App\Models\User model. SetSail comes preconfigured to auto-generate usernames and assign a default role:

protected static function boot()
{
    parent::boot();
    static::creating(function ($user) {
        if (empty($user->username)) {
            $username = Str::slug($user->name, '');
            $i = 1;
            while (self::where('username', $username)->exists()) {
                $username = Str::slug($user->name, '') . $i;
                $i++;
            }
            $user->username = $username;
        }
    });
    static::created(function ($user) {
        $user->syncRoles([]);
        $user->assignRole(config('setsail.default_user_role', 'registered'));
    });
}
            

Verify Email

Email verification can be required by toggling the Require Email Verification option at /auth/setup/settings. Once enabled, new users must verify their email before gaining access.

Password Confirmation

Protect sensitive routes by applying the confirm middleware. This will prompt the user to re-enter their password to proceed.

Enable Email Verification

Password Reset / Request

Users can reset their passwords via the /auth/password/reset route. They will receive a unique reset link via email and can update their password securely.

Two-Factor Authentication (2FA)

SetSail allows users to enable Two-Factor Authentication for improved account security. This can be toggled from the user settings interface.

Learn how to configure 2FA in the DevDojo Auth documentation.

Social Authentication

Enable social logins (Google, GitHub, etc.) easily by navigating to /auth/setup/providers. There, you can toggle providers and input the necessary API credentials.

Social Providers

Once enabled, users will be able to register and log in via the selected social platforms.


User Profiles

SetSail allows you to manage customizable user profiles with ease. Users can personalize their account information and you can collect additional fields using Custom Profile Fields.

Public Profile Page

Every user has a public profile page available at: /profile/{username}

  • Authenticated users see the profile using the app.blade.php layout.
  • Guest users see the profile using the marketing.blade.php layout.
Public Profile Page

To disable public profile pages, add this route in routes/web.php:

Route::redirect('profile/{username}', '/');

Then run php artisan route:clear to clear cached routes.

Profile Settings

Users can manage their profile by clicking on Settings in the user dropdown menu.

By default, users can update:

  • Avatar
  • Name
  • Email
  • Additional custom profile fields (e.g., About)
Profile Settings

Custom Profile Fields

You can add extra fields to user profiles using the configuration file: config/profiles.php.

Default structure example:

<?php
return [
    'fields' => [
        'about' => [
        'label' => 'About',
        'type' => 'Textarea',
        'rules' => 'required',
        ],
    ],
];

To add another field, like “Occupation”:

'occupation' => [
    'label' => 'What do you do for a living?',
    'type' => 'TextInput',
    'rules' => ''
]

The field data is automatically stored in the profilekeyvalue table.

Get Profile Field Data

To retrieve any profile field value for the authenticated user:

auth()->user()->profile('occupation');

Profile Field Types

SetSail uses Filament Form Builder, so you can use any of the following field types:

  • TextInput
  • Textarea
  • Checkbox, Toggle, Radio
  • Select, CheckboxList, ToggleButtons
  • DateTimePicker, ColorPicker
  • FileUpload
  • RichEditor, MarkdownEditor
  • TagsInput

You can also use third-party Filament field components by specifying their full class path:

'type' => \FilamentTiptapEditor\TiptapEditor::class

Filament Form Documentation


Billing

SetSail integrates seamlessly with Stripe or Paddle to help you accept subscription payments with ease. Below you'll learn how to configure billing for your SaaS platform.

Selecting Your Payment Provider

Choose your preferred billing provider by setting the BILLING_PROVIDER in your .env file:

BILLING_PROVIDER=stripe

This setting is used inside config/setsail.php:

'billing_provider' => env('BILLING_PROVIDER', 'stripe'),

Stripe Integration

Stripe API Credentials

Login to your Stripe dashboard and retrieve:

  • Publishable Key
  • Secret Key
.env
STRIPE_PUBLISHABLE_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
Stripe Webhook Secret

To enable webhook events:

  1. Go to Developers > Webhooks
  2. Create new endpoint: https://yourdomain.com/webhook/stripe
  3. Select all Checkout and Billing Portal events
  4. Copy the Signing Secret
STRIPE_WEBHOOK_SECRET=whsec_...
Webhook Warning

If the webhook is misconfigured, users may reach the success page but their account won't upgrade. Make sure it's working correctly for the payment to reflect in your app.

Stripe Testing

Use Test Mode from the Stripe dashboard to test subscriptions. To test webhook locally, install Stripe CLI and run:

stripe listen --forward-to http://yourdomain.test/webhook/stripe
Stripe Customer Portal

Stripe provides a customer portal where users can manage their plans and payment methods. Configure it under: Settings > Billing > Customer Portal


Paddle Integration

Paddle Environment
.env
            PADDLE_ENV=sandbox

Switch to production when deploying live.

Paddle API Credentials

From your Paddle Dashboard under Developer Tools > Authentication, get:

  • Vendor ID
  • API Key
  • Client-side Token
.env
PADDLE_VENDOR_ID=9999
PADDLE_API_KEY=...
PADDLE_CLIENT_SIDE_TOKEN=...
Paddle Webhooks

Go to Developer Tools > Notifications and add:

https://yourdomain.com/webhook/paddle

Enable these events:

  • subscription.created
  • subscription.updated
  • subscription.cancelled
  • transaction.payment_failed
Paddle Payment Link

Set your default redirect link after cancelation or updates:

https://yourdomain.com/settings/subscription

Test Billing Process

Use these test credentials to simulate a successful payment:

  • Credit Card: 4242 4242 4242 4242
  • Expiry: Any future date
  • CVC: Any 3-digit number

For more details:

Note: Before testing billing, make sure you’ve created at least one subscription plan. The next section will walk you through creating plans.


Subscription Plans

Subscription plans are essential for SaaS platforms, allowing you to offer customers different levels of service with unique features, pricing, and access. In SetSail, each subscription plan is linked to a User Role, enabling automatic permission control when users subscribe.

Current Plans

Upon installation, SetSail comes with three default plans:

  • Basic
  • Premium
  • Pro

Feel free to modify or remove these plans to suit your application's needs.

Deleting Plans

To delete a plan, navigate to /admin/plans and click Delete on the plan you'd like to remove.

Delete Plan

If the plan is associated with a role, you may also want to delete that role from /admin/roles:

Delete Role

Creating a Plan

To create a new subscription plan (e.g. Starter), you’ll first want to create a role with the same name:

  • Go to /admin/roles and click New Role.
  • Name it starter, use the guard web, and add a description.
Create Role

Then go to /admin/plans and click New Plan.

  • Give your plan a name (e.g. starter)
  • Set the pricing (monthly, yearly, lifetime)
  • Leave the Price ID blank for now
  • Associate it with the role starter
Create Plan

That's it! You've created a new subscription plan with role-based access control.

Getting Your Price ID from Stripe

In your Stripe dashboard, go to Product Catalog and create a product. Then:

  1. Create a pricing option (Monthly, Yearly, etc.)
  2. Click the price to view the Price ID
  3. Copy this ID into your SetSail Plan in the admin panel
Stripe Price ID

Organizing Tip:

  • Create a single product with multiple prices inside (monthly, yearly, etc.)
  • Or create separate products for each plan—both approaches work

Getting Your Price ID from Paddle

In your Paddle dashboard, navigate to your product catalog and:

  1. Create a product for each plan
  2. Add a price to each product
  3. Copy the pre_... Price ID
  4. Paste this ID into the Price ID field in your plan inside the admin dashboard

Roles and Permissions

Roles and Permissions allow you to manage who can access different parts of your web application.

Roles

Roles are labels given to users to define their level of access. By default, SetSail includes the following roles:

  • Admin – Developer/administrator with full access.
  • Registered – Default role for newly registered users.
  • Basic – Linked to the Basic subscription plan.
  • Premium – Linked to the Premium subscription plan.
  • Pro – Linked to the Pro subscription plan.

Note: Do not modify the admin role, as it is referenced throughout the codebase.

If you rename the registered role, update the default_user_role value in config/setsail.php.

Creating Roles (via code)
use Spatie\Permission\Models\Role;

            $role = Role::create(['name' => 'writer']);
Assigning Roles to Users
auth()->user()->syncRoles([]);
            auth()->user()->assignRole('writer');
Getting Users by Role
$users = User::role('writer')->get();
Checking if a User Has a Role
auth()->user()->hasRole('writer');
In Blade:
@role('writer')
    I am a writer!
@else
    I am not a writer...
@endrole


Permissions

Permissions allow for more granular control. They can be assigned directly to users or to roles.

Creating Permissions
                
use Spatie\Permission\Models\Permission;
$permission = Permission::create(['name' => 'edit articles']);
                
            
Assigning Permissions

To a role:

                
use Spatie\Permission\Models\Role;
$role = Role::where('name', 'writer')->first();
$role->givePermissionTo('edit articles');
                
            

To a user:

                
auth()->user()->givePermissionTo('edit articles');
                
            
Revoking Permissions
                
use Spatie\Permission\Models\Permission;
$permission = Permission::where('name', 'edit articles')->first();
$role->revokePermissionTo($permission);
                
            
Checking Permissions

Check if a user has a permission:

                
auth()->user()->hasPermissionTo('edit articles');
                
            

Check for multiple permissions:

                
auth()->user()->hasAnyPermission([
    'edit articles', 'publish articles', 'unpublish articles'
]);
                
            
In Blade:
                
@can('edit articles')
    <!-- Your HTML here -->
@endcan
                
            

Or:

                
@if(auth()->user()->can('edit articles') && $someCondition)
    <!-- Some conditional block -->
@endif
                
            

Digging Deeper

SetSail uses the Spatie Laravel Permission package under the hood. Explore their docs for more advanced usage and customization.


User Notifications

SetSail leverages Laravel’s default Notification system with a built-in elegant UI to display notifications to your users.

When to Use Notifications

You can use notifications in any scenario where you want to alert users about activity in your app. Common examples include:

  • Notifying users in a forum when a new response is added.
  • Alerting a user when someone follows them.
  • Informing a user when they receive a message.

Creating Notifications

SetSail builds upon the Laravel Notification system. To create a new notification, run the following command:

php artisan make:notification TestNotification

This will create a file at app/Notifications/TestNotification.php.

By default, the via() method will look like this:

public function via($notifiable)
{
    return ['mail'];
}

Update it to use the database channel:

public function via($notifiable)
{
    return ['database'];
}

Then update the toArray() method to define the content of the notification:

public function toArray($notifiable)
{
    return [
    'icon' => '/storage/users/default.png',
    'body' => 'This is an example, when the user clicks this notification it will go to the link.',
    'link' => '/dashboard',
    'user' => [
        'name' => 'John Doe'
        ]
    ];
}
            

Customize these fields as needed, and ensure any changes match the variables referenced in the pages/notifications/index.blade.php view file.

Triggering Notifications

You can manually trigger notifications using Tinker:

php artisan tinker
App\Models\User::find(1)->notify(new App\Notifications\TestNotification);

Change find(1) to the appropriate user ID.

Viewing Notifications

Authenticated users can visit the /notifications route to view their notifications.

  • Notifications will appear in a list format.
  • If there are no notifications, a clean empty state will be displayed.

💡 You can fully customize the view by modifying the file inside your theme: pages/notifications/index.blade.php.

Getting Notification Count

To get the unread notification count for the current user:

auth()->user()->unreadNotifications->count()

Digging Deeper

To explore more advanced features, visit the official Laravel Notifications documentation:

Laravel Notifications Docs

Pages

SetSail makes it easy to create and manage static content pages such as Terms of Service, Privacy Policy, or About Us directly from the admin panel.

Note: This section refers to content pages created from the admin panel. These are different from dynamic theme pages (Volt pages) located in your resources/views/themes/theme-name/pages folder. Volt pages support more customization and logic.

Creating Pages

To create a new static page:

  1. Visit /admin/pages in your browser.
  2. You’ll see a list of example pages (like Terms or Privacy).
  3. Pages List
  4. Click on the New Page button.
  5. Fill in the form with the title, slug, and content.
Create Page

After saving, the page becomes accessible using the slug. For example, if the slug is hello-world, the URL will be:

https://yourdomain.com/hello-world

Page View

Pages created through the admin use a default Blade view. You can customize this view at:

resources/themes/your-theme/page.blade.php

This is where the static page content is rendered. You can customize styling and structure to match your design.

Which to Use?

Here’s how to decide between using admin-created pages and theme-based pages:

Pages via Admin Pages via Theme Directory
Best for static content like Terms, Privacy, About Best for dynamic content with custom logic or components
Easy to edit directly from the admin panel Provides more control over layout, logic, and routing
Changes take effect immediately Requires code access and deployment

Use admin pages for simplicity. Use theme pages when you need advanced customization.


API

SetSail includes a powerful out-of-the-box API, allowing you to expose endpoints for third-party integrations or power your mobile app with ease.

User API Keys

Users can generate API keys by visiting /settings/api.

  • Enter a name and click Create New Key.
  • Create Api Key
  • View, copy, edit, or delete any generated key.
Api Keys List

Access Tokens

To interact with the API, you'll need an Access Token. You can obtain this token using either:

  1. A user API key
  2. Email/password login
Get Access Token from API Key
POST /api/token?key=API_KEY_HERE

Response:

{
"access_token": "your.jwt.access.token"
}
Get Access Token from Login
POST /api/login?email=user@example.com&password=your_password

Response:

{
"access_token": "your.jwt.access.token",
"token_type": "bearer",
"expires_in": 60
            }
Refresh Token

To refresh an expired token:

POST /api/refresh

Include the old token in the Authorization: Bearer header.

Making Authenticated Requests

Once you have an access token, you can include it in the headers of your API requests:

Authorization: Bearer your.jwt.access.token

Validate roles/permissions inside routes as needed, or leverage an API management package like:

  • Laravel Orion
  • Restify
  • Laravel API Toolkit
  • Filament API Service

Testing Your API

Use tools like Postman or Insomnia to test API endpoints.

Postman Api Test

Download a full list of available endpoints here:

wave-3-api-endpoints.json

Be sure to update the BASE_URL to match your local or live domain.

Registering via API

You can register users by sending a POST request:

/api/register?name=John Doe&username=jdoe&email=user@example.com&password=your_password

This will automatically return a valid access token.

JWT vs Sanctum

SetSail uses a JWT stateless API by default, which validates each request independently. Laravel Sanctum can be added if needed for stateful (session-based) authentication.

You can even use both JWT and Sanctum side-by-side depending on your app's needs.


Admin

The SetSail admin panel is built using FilamentPHP, providing an elegant, powerful, and customizable interface to manage your application.

Admin Interface

Access the admin panel at /admin. You can collapse or expand the sidebar for a cleaner view.

The admin dashboard allows you to manage:

  • Users
  • Roles & Permissions
  • Plans
  • Posts & Categories
  • Media Manager
  • Pages
  • Changelogs
  • Themes
  • Settings
Admin Dashboard

Dashboard Analytics

We use the Filament Google Analytics Plugin (powered by Spatie) to display real-time metrics.

  1. Add your property ID to .env:
    ANALYTICS_PROPERTY_ID=XXXXXXXXX
  2. Download your service account JSON credentials from the Google Cloud Console.
  3. Save it at storage/app/analytics/service-account-credentials.json
  4. Refer to Spatie Laravel Analytics Docs for detailed setup.

Filament Admin Features

Filament provides a modern interface and rich tools for backend development. You can extend any part of the panel with Filament’s flexible architecture.

Explore more at Filament Documentation.

Filament Customer Panel

To build a user-facing dashboard, you can:

  • Use Filament’s Panel Builder
  • Or build a custom view in your theme at resources/themes/{theme}/dashboard/index.blade.php

We recommend the custom dashboard approach for better UX and design flexibility.

Filament Table Builder

Table Builder lets you create interactive and filterable tables. Example from the API Keys page:

public function table(Table $table): Table
{
    return $table->query(App\Models\ApiKey::query()->where('user_id', auth()->id()))
    ->columns([
        TextColumn::make('name'),
        TextColumn::make('created_at')->label('Created'),
        ])
        ->actions([
            ViewAction::make()->slideOver()->modalWidth('md')->form([
            TextInput::make('name'),
            TextInput::make('key')
            ]),
            EditAction::make()->slideOver()->modalWidth('md')->form([
            TextInput::make('name')->required()->maxLength(255),
            ]),
            DeleteAction::make(),
        ]);
}
            

Render it with:

{{ $this->table }}

Filament Form Builder

To create frontend forms in your theme, you can use Filament’s form builder. Example:

public function form(Form $form): Form
{
    return $form->schema([
        TextInput::make('key')
        ->label('Create a new API Key')
        ->required()
    ])->statePath('data');
}
            

Render it with:

{{ $this->form }}

Learn More

To discover more features of FilamentPHP:

https://filamentphp.com/docs


Concepts


Blade Directives

SetSail includes several helpful Blade directives that simplify frontend rendering logic, making your templates more expressive and easier to maintain.

  • @auth / @guest
  • @admin
  • @subscriber / @notsubscriber
  • @subscribed('PlanName')
  • @home
  • @else usage

Auth and Guest

To check if a user is authenticated:

@auth
    <p>Welcome back, {{ auth()->user()->name }}!</p>
@endauth

To check if a visitor is a guest (not logged in):

@guest
<p>Please log in to continue.</p>
    @endguest

Admin

To check if a user is an admin:

@admin
<p>You are logged in as an admin.</p>
    @endadmin

Subscriber

To check if the user has any active subscription:

@subscriber
<p>Thanks for subscribing!</p>
    @endsubscriber

Not Subscriber

To check if the user is not subscribed to any plan:

@notsubscriber
<p>Upgrade to a plan?</p>
    @endnotsubscriber

Subscribed to a Specific Plan

To check if the user is subscribed to a specific plan (e.g. Pro):

@subscribed('Pro')
<p>You’re subscribed to the Pro plan.</p>
    @endsubscribed

Note: The plan name must match exactly.

Home

To check if the user is currently on the homepage route:

@home
    <p>You are on the homepage.</p>
@endhome

Using @else with Directives

You can chain @else inside most directives:

@subscriber
    <p>You are a subscriber.</p>
@else
    <button>Become a subscriber</button>
@endsubscriber

Perfect for showing alternate content based on conditions.


Global Helpers

SetSail provides several global helper functions to simplify logic and improve flexibility throughout your application.

setting()

Access key/value pairs defined in the admin panel at /admin/settings.

Admin Settings Table

Example usage:

echo setting('site.title');

Used in a Blade view for fallback SEO values:

<!-- resources/themes/{theme}/partials/head.blade.php -->
@if(isset($seo->title))
    <title>{{ $seo->title }}</title>
@else
    <title>{{ setting('site.title', 'Laravel SetSail') . ' - ' . setting('site.description', 'The SaaS Starter Kit') }}</title>
@endif

Example for embedding Google Analytics using a saved tracking ID:

<!-- resources/views/themes/{theme}/partials/footer_scripts.blade.php -->
@if(setting('site.google_analytics_tracking_id', ''))
    <script async src="https://www.googletagmanager.com/gtag/js?id={{ setting('site.google_analytics_tracking_id') }}"></script>
    <script>
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag('js', new Date());
    gtag('config', '{{ setting("site.google_analytics_tracking_id") }}');
    </script>
@endif

Tip: Use prefixes like site. to keep settings organized.

blade()

Parses a Blade string and returns rendered HTML.

@php $name = 'Tony'; @endphp
blade('<p>Hello, my name is {{ $name }}</p>');

Output:

<p>Hello, my name is Tony</p>

getMorphAlias($class)

Returns the morph alias for a given Eloquent model class.

getMorphAlias(\App\Models\User::class); // returns 'user'

hasmonthlyyearly_toggle()

Returns true or false depending on whether the pricing toggle (monthly/yearly) should be shown.

getdefaultbilling_cycle()

Returns the default billing cycle: either Monthly or Yearly, based on your config.

More helper functions may be added in future releases. You can also contribute your own by submitting a pull request on GitHub.


Volt Pages

When you create or install a new theme, the pages directory inside the theme folder is automatically mapped to routes. This is powered by Laravel Folio and enhanced with Livewire Volt for dynamic functionality.

Pages Directory and Folio

SetSail uses Laravel Folio to handle automatic routing. Here's how your Blade file structure maps to URLs:

File Route
pages/index.blade.php/
pages/about.blade.php/about
pages/about/index.blade.php/about
pages/blog/index.blade.php/blog
pages/blog/[post].blade.php/blog/{post}
pages/contact.blade.php/contact
pages/services/web.blade.php/services/web
pages/[category]/index.blade.php/{category}
pages/[category]/[id].blade.php/{category}/{id}

Learn more in the Laravel Folio Documentation.

Single File Volt Pages

All SetSail themes support Livewire Volt. This means you can turn any page inside resources/themes/{theme}/pages into a dynamic component using Volt’s single-file syntax.

Here’s an example of a basic Todos Volt component:

<?php

            use function Laravel\Folio\{middleware, name};
            use Livewire\Volt\Component;
            use Livewire\Attributes\Rule;
            use Livewire\Attributes\Computed;

            name('todos');

            new class extends Component
            {
                public $todos;

                #[Rule('required')]
                public $todo;

                public function mount()
                {
                    $this->todos = [
                        ['todo' => 'Install SetSail Application', 'completed' => true],
                        ['todo' => 'Read the documentation', 'completed' => false],
                        ['todo' => 'Learn how to use folio and volt', 'completed' => false],
                        ['todo' => 'Add the todos single-file volt component', 'completed' => false],
                        ['todo' => 'See how simple SetSail will make your life', 'completed' => false]
                    ];
                }

                public function add()
                {
                    $this->validate();
                    $this->todos[] = ['todo' => $this->todo, 'completed' => false];
                    $this->reset('todo');
                }

                #[Computed]
                public function remaining()
                {
                    return collect($this->todos)->where('completed', false)->count();
                }
            };
            ?>

            <x-layouts.marketing>
                @volt('todos')
                    <div class="flex items-center justify-center px-16 py-20 bg-neutral-100 text-neutral-300">
                        <div class="bg-white p-10 rounded">
                            <h2 class="text-base font-semibold text-neutral-900">My Todo</h2>
                            <p class="text-sm text-neutral-500">You have {{ $this->remaining }} things on your todo list.</p>

                            <div class="mt-4 space-y-3">
                                @foreach($todos as $todo)
                                    <div class="flex items-start">
                                        <input type="checkbox" wire:model.live="todos.{{ $loop->index }}.completed" class="w-4 h-4 text-indigo-600 rounded">
                                        <label class="ml-3 text-sm font-medium text-neutral-900">{{ $todo['todo'] }}</label>
                                    </div>
                                @endforeach
                            </div>

                            <form wire:submit="add" class="mt-6">
                                <input type="text" wire:model="todo" placeholder="My new todo..." class="block w-full py-1.5 rounded-md ring-1 ring-inset ring-neutral-300">
                            </form>
                        </div>
                    </div>
                @endvolt
            </x-layouts.marketing>
            

Save this file as resources/themes/anchor/pages/todos.blade.php and visit /todos to view it in action.

Learn more about Volt in the Laravel Volt Documentation.


Prompts


👤 Create a User

The app:create-user command allows you to create a new user and assign them a role through an interactive command-line interface. It uses Laravel's built-in prompt methods and integrates with the Spatie Permission package.

Command Signature

php artisan app:create-user

Usage

When you run the command, it will prompt you for the following:

  • User's name
  • User's email
  • User's username
  • User's password (input will be hidden)

After validation, it will create the user and prompt you to select a role from available roles.

Step-by-step Process

  1. Run the command:
    php artisan app:create-user
  2. Enter the requested information:
    • Name
    • Email
    • Username
    • Password (hidden input)
  3. If validation passes, you’ll be asked to choose a role.
  4. The selected role is assigned and a success message is displayed.

Validation Rules

  • Name: Required, string, max 255 characters
  • Email: Required, valid format, unique, max 255 characters
  • Username: Required, string, unique, max 255 characters
  • Password: Required, must follow default Laravel password rules

Role Assignment

All roles are fetched from the database and displayed for selection. The selected role is assigned using the syncRoles() method, which removes any previously assigned roles before assigning the new one.

Success Output

User created successfully with role: [Selected Role Name]

Error Handling

If validation fails, errors are displayed and the command exits with a status code of 1. You’ll need to rerun the command with correct input.

Notes

  • The new user is automatically marked as verified (verified = 1).
  • This command uses the Spatie Permission package for role management. Ensure it’s properly installed and configured.
  • syncRoles() removes any existing roles before assigning the new one.
  • Use with care in production—users created this way are active and verified immediately.

Create a Role

The app:create-role command allows you to create a new role and optionally assign permissions through an interactive CLI prompt. It leverages Laravel's prompt system and integrates with the Spatie Permission package.

Command Signature

php artisan app:create-role

Usage

When you run the command, you’ll be prompted to:

  • Enter the role name
  • (Optional) Enter a description
  • Decide whether to assign permissions
  • Select permissions to assign (if applicable)

Step-by-step Process

  1. Run the command:
    php artisan app:create-role
  2. Provide the requested information:
    • Role name (required)
    • Description (optional)
  3. If validation passes, the role will be created.
  4. You will be asked if you want to assign permissions.
  5. If yes:
    • All available permissions will be listed.
    • You can select one or more using the prompt interface.
    • Permissions will be synced to the new role.

Validation Rules

  • Name: Required, string, max 255 characters, must be unique in the roles table

Permission Assignment

If you opt to assign permissions:

  • All permissions from the database will be fetched and shown
  • You can select multiple permissions
  • Permissions are assigned using syncPermissions(), replacing any previous assignments

Success Output

Role '[Role Name]' created successfully.

If permissions were assigned, an additional message appears:

Permissions assigned successfully.

Error Handling

  • If validation fails, the command displays errors and exits with status code 1.
  • If no permissions exist during assignment, a warning message is shown.

Notes

  • This command relies on the Spatie Permission package—ensure it’s installed and configured.
  • The role description is optional but helpful for documentation and management.
  • You can always assign or revoke permissions later through the admin panel or code.
  • Use this command carefully in production environments, as role creation affects access control.

License


This product is available for purchase on CodeCanyon and is subject to the Envato Market License terms. Upon purchase, you are granted a Regular or Extended License depending on your selection. You may use the product in accordance with the [Envato License Terms](https://codecanyon.net/licenses). Your purchase code may be required for receiving future updates or customer support. Please keep your CodeCanyon purchase code in a safe place.