
Building a Laravel Cloud Pricing Calculator with Livewire
April 3, 2025
projectsI recently built a pricing calculator for Laravel Cloud to help developers better understand and estimate their potential hosting costs. This project was born from personal experience - I got early access to Laravel Cloud and deployed JSONLTools.com there, but I wasn't sure what the pricing would be when Cloud officially launched.
The Laravel team created a video explaining the pricing structure (shared by Chris Sev), which helped me understand how it all works. After watching it, I wanted to build an interactive tool that would make it easier for developers to estimate their costs.
Why Build a Pricing Calculator?
The motivation was simple - I was confused about the pricing myself and thought there might be others facing the same challenge. It's a common pain point in the developer community - trying to estimate costs for cloud services with complex pricing models. I wanted to create a tool that would make this process transparent and straightforward.
The Technical Challenge
Laravel Cloud's pricing model is comprehensive, covering various aspects like:
- Base plan costs (Sandbox, Production, Business)
- Compute resources (web servers and workers)
- Database options (MySQL and PostgreSQL)
- Key-value storage
- Object storage
- Data transfer and request limits
- Custom domains and additional users
Creating an interactive calculator that could handle all these variables while providing real-time cost estimates was an interesting challenge. I chose the TALL stack (Tailwind CSS, Alpine.js, Laravel, Livewire) for this project, which proved to be perfect for this use case.
The Solution
The core of the application is a single Livewire component that handles all the pricing calculations. Here's how the pieces fit together:
1. Livewire Component Architecture
The component maintains state for:
- Selected plan and region
- Compute configurations (web and worker instances)
- Database settings
- Storage options
- Usage metrics
class PricingCalculator extends Component
{
public string $plan = 'production';
public string $region = 'us-ohio';
public string $webComputeSize;
public int $webInstances = 1;
public bool $includeWorkers = false;
// ... other properties
}
2. Pricing Service Layer
To keep the component clean and maintainable, I extracted all pricing logic into a dedicated service:
class PricingService
{
public function calculateBasePlanCost(string $plan): float
{
return $this->config['plans'][$plan]['price_monthly'] ?? 0;
}
public function calculateMonthlyComputeCost(string $sizeKey, int $instances): float
{
$priceInfo = Arr::get($this->config, "compute.{$this->region}.{$sizeKey}");
return round($priceInfo['price_monthly'] * $instances, 2);
}
// ... other calculation methods
}
3. Pricing Data Structure
One of the key challenges was organizing the pricing data from the Laravel Cloud documentation into a maintainable configuration structure. I created a comprehensive configuration file that maps all the pricing information:
return [
'plans' => [
'sandbox' => [
'price_monthly' => 0,
'description' => 'Shared compute resources',
'features' => [
'compute' => 'Shared',
'ram' => '256MB',
'cpu' => '0.5',
'web_instances' => 1,
'worker_instances' => 0,
'data_transfer' => 10,
'custom_domains' => 0,
],
],
// ... other plans
],
'compute' => [
'us-ohio' => [
'flex-1c-256m' => [
'price_monthly' => 4.89,
'price_hourly' => 0.0067,
'ram' => '256MB',
'cpu' => '0.5',
],
// ... other compute sizes
],
],
'database' => [
'us-ohio' => [
'mysql' => [
'sizes' => [
'mysql-flex-1c-512m' => [
'cpu' => 1,
'ram_gb' => 0.5,
'price_monthly' => 5.47,
],
// ... other MySQL sizes
],
'storage_price_gb_month' => 0.20,
],
'postgres' => [
'cpu_price_per_hour' => 0.16,
'storage_price_gb_month' => 1.50,
'min_cpu' => 0.25,
],
],
],
'kv' => [
'250mb' => ['storage_mb' => 250, 'price_monthly' => 7],
'1gb' => ['storage_mb' => 1000, 'price_monthly' => 20],
// ... other KV tiers
],
'object_storage' => [
'storage_price_gb_month' => 0.02,
'class_a_price_per_thousand' => 0.005,
'class_b_price_per_thousand' => 0.0005,
],
'usage_allowances' => [
'data_transfer' => [
'sandbox' => 10,
'production' => 100,
'business' => 1000,
'price_per_gb' => 0.10,
],
'requests' => [
'sandbox' => 1,
'production' => 10,
'business' => 100,
'price_per_million' => 1.00,
],
// ... other allowances
],
];
This configuration structure:
- Mirrors the Documentation: Follows the same organization as the Laravel Cloud pricing documentation
- Supports Multiple Regions: Allows for future expansion to other regions
- Separates Concerns: Keeps pricing data separate from business logic
- Maintains Accuracy: All values are directly sourced from the official documentation
- Enables Easy Updates: When prices change, only the configuration needs to be updated
The configuration file serves as a single source of truth for all pricing calculations, making it easy to maintain and update when Laravel Cloud's pricing changes.
4. Real-time Updates
One of the key features is real-time cost updates as users adjust their configuration. Livewire makes this incredibly simple:
#[Computed]
public function totalMonthlyCost()
{
return $this->basePlanCost +
$this->webComputeCost +
$this->workerComputeCost +
$this->databaseCost +
$this->kvCost +
$this->objectStorageCost +
$this->dataTransferCost +
$this->requestsCost +
$this->customDomainsCost +
$this->usersCost;
}
Key Features
- Interactive UI: Users can adjust their configuration and see cost updates in real-time
- Plan-specific Options: Different features and pricing tiers available based on the selected plan
- Comprehensive Calculations: Covers all aspects of Laravel Cloud pricing
- Usage Allowances: Automatically handles free allowances for data transfer, requests, and other metrics
- Responsive Design: Works well on both desktop and mobile devices
AI-Powered Configuration Assistant
One of the most exciting additions to the calculator is the AI-powered configuration assistant. Once I started using the calculator myself, I realized I was still confused. I knew what kind of sites and projects I had, but I didn't know what configuration that translated to in Laravel Cloud terms. Initially, I thought about setting up some happy defaults like "blog" or "SaaS app," but then decided to try using an LLM to provide a natural language interface instead. While the interactive UI makes it easy to explore different pricing options, users (including myself) still struggled with determining the right configuration for their specific use case. To address this, I integrated OpenAI's GPT-4 Turbo model to provide intelligent recommendations based on natural language descriptions of applications.
Why We Added AI Assistance
The complexity of cloud pricing isn't just about understanding individual component costs - it's about knowing what components you actually need. Many developers can easily get lost in questions like:
- "Do I need workers for my Laravel application?"
- "What size database should I choose for my expected traffic?"
- "Should I use MySQL or PostgreSQL for my use case?"
- "How much object storage might I need?"
The AI assistant helps bridge this knowledge gap by translating plain English descriptions of applications into concrete infrastructure recommendations.
How It Works
The implementation leverages OpenAI's GPT-4 Turbo model through a carefully designed system that:
Processes Natural Language Input: Users can describe their application in plain English, such as "I'm building a social media platform that will handle about 10,000 users with photo sharing capabilities"
Analyzes Requirements: The AI analyzes the description against the complete Laravel Cloud pricing configuration data to understand:
- Plan limitations and features
- Available compute sizes and their specifications
- Database options and pricing tiers
- KV store and object storage capabilities
- Usage allowances for each plan
Generates Recommendations: The system produces a structured configuration that includes:
- Recommended plan (Sandbox, Production, or Business)
- Appropriate compute size selection
- Database configuration (type and size)
- KV store recommendations if needed
- Detailed explanation of the choices
Applies Configuration: The recommendations are automatically applied to the calculator, allowing users to see the estimated costs and further refine the settings if needed.
Technical Implementation
The AI assistant is implemented through a service-based architecture that integrates seamlessly with the existing calculator:
class AiPricingConfigurator extends Component
{
protected PricingService $pricingService;
public string $userDescription = '';
public array $aiConfiguration = [];
public function generateConfiguration()
{
$configuration = $this->pricingService->generatePricingConfiguration($this->userDescription);
if (!isset($configuration['error'])) {
$this->aiConfiguration = $configuration;
// Automatically apply the configuration to the calculator
$this->dispatch('applyAiConfiguration', configuration: $configuration['configuration']);
}
}
}
The PricingService
handles the interaction with OpenAI's API and processes the response:
class PricingService
{
public function generatePricingConfiguration(string $userDescription)
{
// Send the complete pricing configuration and user description to GPT-4
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $this->apiKey,
])->post('https://api.openai.com/v1/chat/completions', [
'model' => 'gpt-4-turbo',
'messages' => [
[
'role' => 'system',
'content' => 'You are a pricing configuration assistant for Laravel Cloud...'
],
[
'role' => 'user',
'content' => "Based on the following Laravel Cloud pricing configuration data:\n" .
json_encode($this->config, JSON_PRETTY_PRINT) .
"\n\nCreate a configuration recommending the best plan and resources for:\n" .
$userDescription
]
],
'function_call' => ['name' => 'generate_pricing_configuration']
]);
// Process the AI response into a structured configuration
return $this->buildAiConfigurationResponse($configuration);
}
protected function buildAiConfigurationResponse(array $configuration)
{
// Calculate costs based on AI recommendations
$totalPrice = 0;
$details = [];
// Build a detailed response with costs and explanations
return [
'configuration' => $configuration,
'details' => $details,
'total_monthly_price' => $totalPrice,
'explanation' => $configuration['explanation'] ?? ''
];
}
}
The UI presents the AI recommendations in a clear, actionable format:
<div class="mt-4 bg-zinc-50 dark:bg-neutral-800 p-4 rounded-md">
<div class="flex flex-col items-center text-center mb-3">
<h3 class="text-md font-semibold mb-1">Monthly Estimate</h3>
<div class="text-3xl font-bold text-red-500">
${{ number_format($aiConfiguration['total_monthly_price'] ?? 0, 2)}}
</div>
</div>
<div class="mb-3 bg-white dark:bg-neutral-700 border border-zinc-200 dark:border-neutral-600 p-3 rounded">
<p class="text-sm text-zinc-700 dark:text-zinc-300">
{{ $aiConfiguration['explanation'] }}
</p>
</div>
<!-- Display recommended configuration details -->
</div>
This integration of AI technology has significantly improved the user experience by:
- Reducing Complexity: Users can describe their needs in plain language instead of navigating technical options
- Providing Education: Each recommendation comes with an explanation, helping users understand the choices
- Saving Time: Quick initial configuration that users can then fine-tune
- Optimizing Costs: Intelligent recommendations that balance performance and cost
Technical Decisions
- Single Component Approach: While the calculator could have been split into multiple components, keeping it as a single component made state management simpler
- Service Layer: Extracting pricing logic into a service made the code more maintainable and testable
- Computed Properties: Using Livewire's computed properties for cost calculations ensures values are always up-to-date
- Configuration-based: All pricing data is stored in configuration files, making it easy to update when prices change
- Transparency First: I designed the calculator to be completely transparent about how costs are calculated, showing the breakdown of each component
Testing Strategy
One of the most important aspects of this project was ensuring the pricing calculations were accurate. I implemented a comprehensive test suite using Pest PHP, which provides a more expressive and readable testing syntax. The test suite covers:
Unit Tests: Testing individual calculation methods in the PricingService, including:
- Base plan costs
- Compute pricing
- Database costs (both MySQL and PostgreSQL)
- Key-value storage costs
- Object storage costs
- Bandwidth pricing
- User costs
Here's an example of a Pest test for database cost calculations:
test('calculates mysql cost with specific size and storage', function () {
// mysql-flex-1c-1g: 10.95 / month compute
// storage: 0.20 / GB-month
$dbType = 'mysql';
$mysqlSizeKey = 'mysql-flex-1c-1g';
$postgresCpuUnits = null;
$storageGB = 50;
$expectedComputeCost = 10.95;
$expectedStorageCost = 50 * 0.20;
$expectedTotalCost = $expectedComputeCost + $expectedStorageCost; // 10.95 + 10.00 = 20.95
$actualCost = $this->pricingService->calculateDatabaseCost($dbType, $mysqlSizeKey, $postgresCpuUnits, $storageGB);
expect($actualCost)->toBe($expectedTotalCost);
});
The test suite includes edge cases and boundary conditions, such as:
- Minimum and maximum storage values
- Invalid configuration inputs
- Null values
- Plan-specific restrictions
Using Pest's expressive syntax makes the tests more readable and maintainable, while its built-in expectations provide clear error messages when tests fail. This comprehensive test coverage gives me confidence that the calculator's pricing estimates are accurate and reliable.
Future Improvements
While the calculator is functional, there are several improvements I'm considering:
- Recipes: Show users common configurations as easy recipes to check costs
- Cost History: Allow users to save and compare different configurations
- Region Selection: Add support for different regions with their specific pricing
- Usage Forecasting: Help users estimate their future usage based on current metrics
- Export Options: Allow users to export their configuration and cost breakdown
Try It Out
You can try out the live version of the calculator at pricingcalculator.laravel.cloud. The code is also available on GitHub for anyone interested in contributing or learning from the implementation.
Conclusion
Building this calculator was a fun side project that scratches my own itch while helping the Laravel community. The TALL stack made it possible to build a responsive, interactive tool without the overhead of a complex JavaScript framework.
I was able to rapidly develop this application while keeping the codebase clean and maintainable. The project structure showcases effective patterns for Livewire applications that prioritize both performance and user experience.
What I'm most proud of is addressing a genuine pain point in the Laravel ecosystem. By demystifying Laravel Cloud's pricing structure, developers can now confidently plan their hosting strategy without the confusion I initially faced. This embodies what I love about the Laravel community - we build tools that solve real problems for each other, making the entire ecosystem stronger and more accessible.
Have you tried out the calculator? Let me know if you have any feedback or suggestions for improvements in the comments or reach out on X.
Links
- Try the app
- Give Feedback
- Laravel Cloud Pricing Documentation
- GitHub Repository
- Laravel Cloud
- JSONLTools.com