diff --git a/lib/algora/psp/connect_countries.ex b/lib/algora/psp/connect_countries.ex index 7877f514a..d5f7eac0b 100644 --- a/lib/algora/psp/connect_countries.ex +++ b/lib/algora/psp/connect_countries.ex @@ -126,6 +126,8 @@ defmodule Algora.PSP.ConnectCountries do {"Vietnam", "VN"} ] + def count, do: length(list()) + @spec from_code(String.t()) :: String.t() def from_code(code) do list() |> Enum.find(&(elem(&1, 1) == code)) |> elem(0) || code diff --git a/lib/algora_web/live/pricing_live.ex b/lib/algora_web/live/pricing_live.ex index 0e1844296..be3da9d8e 100644 --- a/lib/algora_web/live/pricing_live.ex +++ b/lib/algora_web/live/pricing_live.ex @@ -2,6 +2,11 @@ defmodule AlgoraWeb.PricingLive do @moduledoc false use AlgoraWeb, :live_view + alias Algora.PSP.ConnectCountries + alias AlgoraWeb.Components.Footer + alias AlgoraWeb.Components.Header + alias AlgoraWeb.Components.Wordmarks + defmodule Plan do @moduledoc false defstruct [ @@ -21,173 +26,372 @@ defmodule AlgoraWeb.PricingLive do defstruct [:name, :detail] end - defmodule ComputeOption do - @moduledoc false - defstruct [:name, :cpu, :memory, :price] - end - defmodule FaqItem do @moduledoc false defstruct [:id, :question, :answer] end - defmodule ROIEstimate do - @moduledoc false - defstruct [ - :developers, - :hourly_rate, - :hours_per_week, - :annual_tc, - :platform_fee, - :traditional_cost, - :traditional_overhead, - :traditional_total, - :algora_cost, - :algora_fee, - :monthly_subscription, - :algora_total, - :savings - ] + @impl true + def render(assigns) do + ~H""" +
+ + +
+ +
+
+
+
+

+ Predictable pricing,
designed to scale +

+

+ Start building for free, collaborate with your team, then scale to millions of users +

+
+
+
+
+ <%= for plan <- @plans do %> + <.pricing_card plan={plan} /> + <% end %> +
+
+ +
+
+
+

+ You're in good company +

+

+ Join hundreds of open source companies that use Algora to accelerate their development +

+
+
+ <.logo_cloud /> +
+
+
+ +
+
+
+

+ See what our customers say +

+

+ Discover how Algora helps founders accelerate development and find top talent +

+
+ +
+
+
+
+ +
+
+
+

+ $15,000 Bounty: Delighted by the Results +

+
+ +
+ We've used Algora extensively at Golem Cloud for our hiring needs and what I have found actually over the course of a few decades of hiring people is that many times someone who is very active in open-source development, these types of engineers often make fantastic additions to a team. + + Through our $15,000 bounty, we got hundreds of GitHub stars, more than 100 new users on our Discord, and some really fantastic Rust engineers. + + The bounty system helps us assess real-world skills instead of just technical challenge problems. It's a great way to find talented developers who deeply understand how your system works. +
+
+
+
+ + John A. De Goes + +
+
John A. De Goes
+
Founder & CEO
+
+
+
+
+
+
Total awarded
+
+ $103,950 +
+
+
+
Bounties completed
+
+ 359 +
+
+
+
Contributors rewarded
+
+ 82 +
+
+
+
+
+
+
+
+
+

+ From Bounty Contributor
To Full-Time Engineer +

+
+ +
+ We were doing bounties on Algora, and this one developer Nick kept solving them. His personality really came through in the GitHub issues and code. We ended up hiring him from that, and it was the easiest hire because we already knew he was great from his contributions. + + That's one massive advantage open source companies have versus closed source. When I talk to young people asking for advice, I specifically tell them to go on Algora and find issues there. You get to show people your work, plus you can point to your contributions as proof of your abilities, and you make money in the meantime. +
+
+
+
+ + Eric Allam + +
+
Eric Allam
+
Founder & CTO
+
+
+ +
+
+
+
Total awarded
+
+ $9,920 +
+
+
+
Bounties completed
+
+ 106 +
+
+
+
Contributors rewarded
+
+ 35 +
+
+
+
+
+
+ +
+
+
+
+
+
+ +
+
+

+ Frequently asked questions +

+
+ <%= for item <- @faq_items do %> +
+ + <%= if @active_faq == item.id do %> +
+ {Phoenix.HTML.raw(item.answer)} +
+ <% end %> +
+ <% end %> +
+
+
+ +
+
+

+ The open source + UpWork alternative. +

+
+ <.button navigate="/onboarding/org"> + Start your project + + <.button href="https://cal.com/ioannisflo" variant="secondary"> + Request a demo + +
+ <.features_bento /> +
+
+ +
+ +
+
+ """ end + @impl true def mount(_params, _session, socket) do - initial_estimate = - calculate_roi_estimate(%{ - "developers" => "3", - "hourly_rate" => "75", - "hours_per_week" => "40" - }) - socket = assign(socket, page_title: "Pricing", plans: get_plans(), faq_items: get_faq_items(), - testimonials: get_testimonials(), - page_scroll: 0, - active_faq: nil, - roi_estimate: initial_estimate + active_faq: nil ) {:ok, socket} end - def handle_event("select_plan", %{"plan" => plan_name}, socket) do - {:noreply, push_navigate(socket, to: "/signup?plan=#{plan_name}")} + @impl true + def handle_event("select_plan", %{"plan" => _plan_name}, socket) do + {:noreply, push_navigate(socket, to: "/onboarding/org")} end + @impl true def handle_event("toggle_faq", %{"id" => faq_id}, socket) do active_faq = if socket.assigns.active_faq == faq_id, do: nil, else: faq_id {:noreply, assign(socket, active_faq: active_faq)} end - def handle_event("select_compute", %{"option" => option}, socket) do - {:noreply, assign(socket, selected_compute_option: option)} - end - - def handle_event("calculate_roi", %{"roi" => params}, socket) do - params = calculate_missing_rate_field(params) - estimate = calculate_roi_estimate(params) - {:noreply, assign(socket, roi_estimate: estimate)} - end - - defp calculate_missing_rate_field(params) do - hours_per_week = params["hours_per_week"] |> to_string() |> String.trim() - hourly_rate = params["hourly_rate"] |> to_string() |> String.trim() - annual_tc = params["annual_tc"] |> to_string() |> String.trim() - - # Convert empty strings to nil for clearer logic - hours_per_week = if hours_per_week == "", do: nil, else: String.to_integer(hours_per_week) - hourly_rate = if hourly_rate == "", do: nil, else: String.to_integer(hourly_rate) - annual_tc = if annual_tc == "", do: nil, else: String.to_integer(annual_tc) - - cond do - # Case 1: Annual TC and Hours/Week provided - calculate Hourly Rate - is_nil(hourly_rate) && not is_nil(hours_per_week) && not is_nil(annual_tc) -> - calculated_rate = div(annual_tc, hours_per_week * 52) - - %{ - "developers" => params["developers"], - "hourly_rate" => to_string(calculated_rate), - "hours_per_week" => to_string(hours_per_week), - "annual_tc" => to_string(annual_tc) - } - - # Case 2: Annual TC and Hourly Rate provided - calculate Hours/Week - is_nil(hours_per_week) && not is_nil(hourly_rate) && not is_nil(annual_tc) -> - calculated_hours = div(annual_tc, hourly_rate * 52) - - %{ - "developers" => params["developers"], - "hourly_rate" => to_string(hourly_rate), - "hours_per_week" => to_string(calculated_hours), - "annual_tc" => to_string(annual_tc) - } - - # Case 3: Hours/Week and Hourly Rate provided - calculate Annual TC - is_nil(annual_tc) && not is_nil(hourly_rate) && not is_nil(hours_per_week) -> - calculated_tc = hourly_rate * hours_per_week * 52 - - %{ - "developers" => params["developers"], - "hourly_rate" => to_string(hourly_rate), - "hours_per_week" => to_string(hours_per_week), - "annual_tc" => to_string(calculated_tc) - } - - # Default case: return original params if we don't have enough information - true -> - params - end - end - - defp calculate_roi_estimate(params) do - developers = String.to_integer(params["developers"]) - hourly_rate = String.to_integer(params["hourly_rate"]) - hours_per_week = String.to_integer(params["hours_per_week"]) - annual_tc = hourly_rate * hours_per_week * 52 - - # Base monthly cost (same for both traditional and Algora) - monthly_base_cost = developers * hourly_rate * hours_per_week * 4.3 - - # Traditional hiring costs (35% overhead - industry average per SBA) - traditional_cost = monthly_base_cost - traditional_overhead = traditional_cost * 0.35 - traditional_total = traditional_cost + traditional_overhead - - # Algora costs - platform_fee = 0.15 - monthly_subscription = 599 - algora_cost = monthly_base_cost - algora_fee = algora_cost * platform_fee - algora_total = algora_cost + algora_fee + monthly_subscription - - yearly_savings = (traditional_total - algora_total) * 12 - - %ROIEstimate{ - developers: developers, - hourly_rate: hourly_rate, - hours_per_week: hours_per_week, - annual_tc: annual_tc, - platform_fee: platform_fee, - traditional_cost: traditional_cost, - traditional_overhead: traditional_overhead, - traditional_total: traditional_total, - algora_cost: algora_cost, - algora_fee: algora_fee, - monthly_subscription: monthly_subscription, - algora_total: algora_total, - savings: yearly_savings - } - end - - # Component: Pricing Card - def pricing_card(assigns) do + defp pricing_card(assigns) do ~H""" -
+
@@ -204,19 +408,14 @@ defmodule AlgoraWeb.PricingLive do

{@plan.description}

- -
+ +
<%= if @plan.price do %>
@@ -227,8 +426,22 @@ defmodule AlgoraWeb.PricingLive do
<% else %> -
-

Custom

+
+ <%= if @plan.name == "Individuals" do %> +

+ 100% +

+

+ payout received +

+ <% else %> +

+ 19% +

+

+ pay as you go +

+ <% end %>
<% end %>
@@ -245,7 +458,7 @@ defmodule AlgoraWeb.PricingLive do
  • - <.icon name="tabler-check" class="h-4 w-4 text-primary" /> + <.icon name="tabler-check" class="h-4 w-4 text-success" />
    {feature.name}
    @@ -269,341 +482,38 @@ defmodule AlgoraWeb.PricingLive do """ end - # Component: Compute Add-ons - def compute_addons(assigns) do - ~H""" -
    -
    -

    Compute Add-ons

    -

    - Additional compute resources for demanding workloads -

    -
    -
    - <%= for option <- @compute_addons do %> -
    - -
    - <% end %> -
    -
    - """ - end - - # Component: Plan Comparison Table - def plan_comparison_table(assigns) do - ~H""" -
    -

    Compare Plans

    -
    - - - - - <%= for plan <- @plans do %> - - <% end %> - - - - <%= for feature <- get_comparison_features() do %> - - - <%= for plan <- @plans do %> - - <% end %> - - <% end %> - -
    Features - {plan.name} -
    {feature.name} - <%= if has_feature?(plan, feature) do %> - <.icon name="tabler-check" class="mx-auto h-5 w-5 text-primary" /> - <% else %> - <.icon name="tabler-minus" class="mx-auto h-5 w-5 text-muted-foreground" /> - <% end %> -
    -
    -
    - """ - end - - # Component: FAQ Section - def faq_section(assigns) do - ~H""" -
    -

    - Frequently asked questions -

    -
    - <%= for item <- @faq_items do %> -
    - - <%= if @active_faq == item.id do %> -
    - {item.answer} -
    - <% end %> -
    - <% end %> -
    -
    - """ - end - - # New ROI Calculator Component - def roi_calculator(assigns) do - ~H""" -
    -

    Calculate Your Savings

    - -
    -
    -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    -
    -
    - - <%= if @roi_estimate do %> -
    -
    -
    -

    Traditional Hiring

    -
    -
    - Base Monthly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_cost))} - -
    -
    - Overhead (35%) - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_overhead))} - -
    -
    - Total Monthly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_total))} - -
    -
    - Total Yearly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_total * 12))} - -
    -
    -
    - -
    -

    With Algora

    -
    -
    - Base Monthly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_cost))} - -
    -
    - - Platform Fee ({trunc(@roi_estimate.platform_fee * 100)}%) - - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_fee))} - -
    -
    - - Placement Fee (0%) - - - $0.00 - -
    -
    - Monthly Subscription - - ${Number.Delimit.number_to_delimited(@roi_estimate.monthly_subscription)} - -
    -
    - Total Monthly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_total))} - -
    -
    - Total Yearly Cost - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_total * 12))} - -
    -
    -
    -
    - -
    -
    - Estimated Yearly Savings - - ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.savings))} - -
    -

    - Savings include reduced recruitment costs, social security taxes, and administrative expenses. -

    -
    -
    - <% end %> -
    - """ - end - - # Data functions defp get_plans do [ %Plan{ - name: "Hobby", - description: "Perfect for small projects and indie developers", - price: 0, - cta_text: "Start for Free", + name: "Individuals", + description: "For developers contributing to open source", + price: nil, + cta_text: "Start Contributing", popular: false, features: [ - %Feature{name: "Up to $5,000 in project budgets"}, - %Feature{name: "Algora Network", detail: "15% platform fee"}, - %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, - %Feature{name: "Unlimited projects"}, - %Feature{name: "Community support"}, - %Feature{name: "Basic project management tools"}, - %Feature{name: "Pay per milestone"} - ], - footnote: "Perfect for testing the waters with smaller projects" - }, - %Plan{ - name: "Startup", - description: "For growing companies", - price: 599, - cta_text: "Upgrade now", - popular: true, - previous_tier: "Hobby", - features: [ - %Feature{name: "Up to $50,000 in project budgets"}, - %Feature{name: "Algora Network", detail: "15% platform fee"}, - %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, - %Feature{name: "Priority support"}, - %Feature{name: "Advanced project management"}, - %Feature{name: "Custom workflows"}, - %Feature{name: "Team collaboration tools"}, - %Feature{name: "Analytics dashboard"}, - %Feature{name: "Job board access"}, - %Feature{name: "Unlimited job postings"} + %Feature{name: "Payouts in 3-8 days on average"}, + %Feature{name: "Available in #{ConnectCountries.count()} countries/regions"}, + %Feature{name: "Algora profile with contribution history"}, + %Feature{name: "Free livestreaming on Algora TV"} ] }, %Plan{ - name: "Enterprise", - description: "For large organizations", + name: "Organizations", + description: "For companies and projects", price: nil, - cta_text: "Contact Sales", + cta_text: "Get Started", popular: false, - previous_tier: "Startup", features: [ - %Feature{name: "Unlimited project budgets"}, - %Feature{name: "Algora Network", detail: "15% platform fee"}, - %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, - %Feature{name: "Dedicated account manager"}, - %Feature{name: "Custom contracts & MSA"}, - %Feature{name: "Advanced security features"}, - %Feature{name: "Custom integrations"}, - %Feature{name: "SLA guarantees"}, - %Feature{name: "Onboarding assistance"}, - %Feature{name: "Training for your team"}, - %Feature{name: "Custom job board"}, - %Feature{name: "ATS integration"} + %Feature{name: "Fees drop to 7.5% with volume"}, + %Feature{name: "Public org page with complete history"}, + %Feature{name: "Teammates with granular access rights"}, + %Feature{name: "Slack / Discord notifications (Webhooks)"}, + %Feature{name: "Display bounties on your site (SDK)"}, + %Feature{name: "Auto-pay on merge"}, + %Feature{name: "Embedded livestreaming"}, + %Feature{name: "Experts Network"}, + %Feature{name: "Hiring Portal"}, + %Feature{name: "Live Challenges"} ] } ] @@ -615,182 +525,350 @@ defmodule AlgoraWeb.PricingLive do id: "platform-fee", question: "How do the platform fees work?", answer: - "We charge 15% for projects using the Algora Network of developers, or 5% if you bring your own developers. This fee helps us maintain the platform, provide payment protection, and ensure quality service." + "For organizations, we charge a 19% fee on bounties, which can drop to 7.5% with volume. For individual contributors, you receive 100% of the bounty amount with no fees deducted." }, %FaqItem{ - id: "budget-limits", - question: "What happens if my project exceeds the budget limit?", + id: "payment-methods", + question: "What payment methods do you support?", answer: - "You'll need to upgrade to a higher tier to handle larger project budgets. Contact our sales team if you're close to your limit." + "We support payments via Stripe for funding bounties. Contributors can receive payments directly to their bank accounts in #{ConnectCountries.count()} countries worldwide." }, %FaqItem{ - id: "payment-protection", - question: "How does payment protection work?", + id: "payment-process", + question: "How does the payment process work?", answer: - "We hold payments in escrow and release them based on project milestones. This ensures both clients and developers are protected throughout the project lifecycle." - } - ] - end - - defp get_comparison_features do - [ - %Feature{name: "Project Budget Limit"}, - %Feature{name: "Algora Network Fee"}, - %Feature{name: "Bring Your Own Devs Fee"}, - %Feature{name: "Support Level"}, - %Feature{name: "Team Management"}, - %Feature{name: "Custom Contracts"}, - %Feature{name: "Analytics"} - ] - end - - defp has_feature?(plan, feature) do - Enum.any?(plan.features, &(&1.name == feature.name)) - end - - defp get_testimonials do - [ - %{ - name: "Sarah Chen", - role: "CTO at TechCorp", - avatar: "https://images.unsplash.com/photo-1494790108377-be9c29b29330", - quote: - "Algora has transformed how we hire developers. The quality of talent and the seamless platform experience has made scaling our team effortless." + "There's no upfront payment required for bounties. Organizations can either pay manually after merging pull requests, or save their card with Stripe to enable auto-pay on merge. Manual payments are processed through a secure Stripe hosted checkout page." + }, + %FaqItem{ + id: "invoices-receipts", + question: "Do you provide invoices and receipts?", + answer: + "Yes, users receive an invoice and receipt after each bounty payment. These documents are automatically generated and delivered to your email." }, - %{ - name: "Michael Rodriguez", - role: "Engineering Lead at StartupX", - avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e", - quote: - "The developers we found through Algora have become integral parts of our team. The platform's focus on open source contributors really makes a difference." + %FaqItem{ + id: "tax-forms", + question: "How are tax forms handled?", + answer: + "We partner with Stripe to file and deliver 1099 forms for your US-based freelancers, simplifying tax compliance for organizations working with US contributors." + }, + %FaqItem{ + id: "payout-time", + question: "How long do payouts take?", + answer: + "Payout timing varies by country, typically ranging from 2-7 business days after a bounty is awarded. Initial payouts for new accounts may take 7-14 days. The exact timing depends on your location, banking system, and account history with Stripe, our payment processor." }, - %{ - name: "Emily Thompson", - role: "VP Engineering at ScaleUp Inc", - avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80", - quote: - "What impressed me most was how quickly we could find and onboard qualified developers. Algora's platform streamlines the entire process." + %FaqItem{ + id: "minimum-bounty", + question: "Is there a minimum bounty amount?", + answer: + "There's no strict minimum bounty amount. However, bounties with higher values tend to attract more attention and faster solutions from contributors." + }, + %FaqItem{ + id: "enterprise-options", + question: "Do you offer custom enterprise plans?", + answer: + ~s(Yes, for larger organizations with specific needs, we offer custom enterprise plans with additional features, dedicated support, and volume-based pricing. Please schedule a call with a founder to discuss your requirements.) + }, + %FaqItem{ + id: "supported-countries", + question: "Which countries are supported for contributors?", + answer: + ~s(We support contributors from #{ConnectCountries.count()} countries worldwide. You can receive payments regardless of your location as long as you have a bank account in one of our supported countries. See the full list of supported countries.) } ] end - def render(assigns) do + defp logo_cloud(assigns) do + ~H""" + + """ + end + + defp features_bento(assigns) do ~H""" -
    -
    -
    -
    -

    - Predictable pricing,
    designed to scale -

    -

    - Start building for free, collaborate with your team, then scale to millions of users +

    +
    +
    + +
    +

    Bounties

    +

    + Fund Issues +

    +

    + Create bounties on any Swift issue to incentivize solutions and attract talented contributors

    - -
    -
    -
    - <%= for plan <- @plans do %> - <.pricing_card plan={plan} /> - <% end %> +
    +
    + +
    +

    Tips

    +

    + Show Appreciation +

    +

    + Say thanks with tips to recognize valuable contributions +

    - - <.roi_calculator roi_estimate={@roi_estimate} />
    - -
    -
    -
    -

    - Trusted by companies worldwide -

    -

    - See what our customers have to say about their experience with Algora -

    -
    -
    - <%= for testimonial <- @testimonials do %> -
    -
    - -
    -
    {testimonial.name}
    -
    {testimonial.role}
    -
    +
    +
    +
    +
    +
    +
    +
    +
    + +

    + Merged pull request +

    -
    - {testimonial.quote} -
    - <% end %> -
    -
    -
    - -
    -

    - Frequently asked questions -

    -
    - <%= for item <- @faq_items do %> -
    - - <%= if @active_faq == item.id do %> -
    - {item.answer} +
    + +

    + Completed payment +

    - <% end %> +
    +
    +
    + + + + + + +

    + Transferring funds to contributor +

    +
    +
    - <% end %> +
    +
    +
    +

    Payments

    +

    + Pay When Merged +

    +

    + Set up auto-pay to instantly reward contributors as their PRs are merged +

    - -
    -
    -

    - The open source - UpWork alternative. -

    -
    - <.link - navigate="/signup" - class="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50" - > - Start your project - - <.link - navigate="/contact/sales" - class="inline-flex h-10 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50" - > - Request a demo - +
    +
    + +
    +

    Pooling

    +

    + Fund Together +

    +

    + Companies and individuals can pool their money together to fund important Swift improvements +

    -
    +
    +
    + +
    +

    Payouts

    +

    + Fast, Global Payouts +

    +

    + Receive payments directly to your bank account from all around the world + + (#{ConnectCountries.count()} countries supported) + +

    +
    +
    +
    +
    +
    + +
    +

    Contracts (coming soon)

    +

    + Flexible Engagement +

    +

    + Set hourly rates, weekly hours, and payment schedules for ongoing Swift development work. Track progress and manage payments all in one place. +

    +
    +
    +
    +
  • """ end end diff --git a/lib/algora_web/live/tmp/pricing_live.ex b/lib/algora_web/live/tmp/pricing_live.ex new file mode 100644 index 000000000..fd4765b0a --- /dev/null +++ b/lib/algora_web/live/tmp/pricing_live.ex @@ -0,0 +1,796 @@ +defmodule AlgoraWeb.Tmp.PricingLive do + @moduledoc false + use AlgoraWeb, :live_view + + defmodule Plan do + @moduledoc false + defstruct [ + :name, + :description, + :price, + :cta_text, + :popular, + :previous_tier, + :features, + :footnote + ] + end + + defmodule Feature do + @moduledoc false + defstruct [:name, :detail] + end + + defmodule ComputeOption do + @moduledoc false + defstruct [:name, :cpu, :memory, :price] + end + + defmodule FaqItem do + @moduledoc false + defstruct [:id, :question, :answer] + end + + defmodule ROIEstimate do + @moduledoc false + defstruct [ + :developers, + :hourly_rate, + :hours_per_week, + :annual_tc, + :platform_fee, + :traditional_cost, + :traditional_overhead, + :traditional_total, + :algora_cost, + :algora_fee, + :monthly_subscription, + :algora_total, + :savings + ] + end + + def mount(_params, _session, socket) do + initial_estimate = + calculate_roi_estimate(%{ + "developers" => "3", + "hourly_rate" => "75", + "hours_per_week" => "40" + }) + + socket = + assign(socket, + page_title: "Pricing", + plans: get_plans(), + faq_items: get_faq_items(), + testimonials: get_testimonials(), + page_scroll: 0, + active_faq: nil, + roi_estimate: initial_estimate + ) + + {:ok, socket} + end + + def handle_event("select_plan", %{"plan" => plan_name}, socket) do + {:noreply, push_navigate(socket, to: "/signup?plan=#{plan_name}")} + end + + def handle_event("toggle_faq", %{"id" => faq_id}, socket) do + active_faq = if socket.assigns.active_faq == faq_id, do: nil, else: faq_id + {:noreply, assign(socket, active_faq: active_faq)} + end + + def handle_event("select_compute", %{"option" => option}, socket) do + {:noreply, assign(socket, selected_compute_option: option)} + end + + def handle_event("calculate_roi", %{"roi" => params}, socket) do + params = calculate_missing_rate_field(params) + estimate = calculate_roi_estimate(params) + {:noreply, assign(socket, roi_estimate: estimate)} + end + + defp calculate_missing_rate_field(params) do + hours_per_week = params["hours_per_week"] |> to_string() |> String.trim() + hourly_rate = params["hourly_rate"] |> to_string() |> String.trim() + annual_tc = params["annual_tc"] |> to_string() |> String.trim() + + # Convert empty strings to nil for clearer logic + hours_per_week = if hours_per_week == "", do: nil, else: String.to_integer(hours_per_week) + hourly_rate = if hourly_rate == "", do: nil, else: String.to_integer(hourly_rate) + annual_tc = if annual_tc == "", do: nil, else: String.to_integer(annual_tc) + + cond do + # Case 1: Annual TC and Hours/Week provided - calculate Hourly Rate + is_nil(hourly_rate) && not is_nil(hours_per_week) && not is_nil(annual_tc) -> + calculated_rate = div(annual_tc, hours_per_week * 52) + + %{ + "developers" => params["developers"], + "hourly_rate" => to_string(calculated_rate), + "hours_per_week" => to_string(hours_per_week), + "annual_tc" => to_string(annual_tc) + } + + # Case 2: Annual TC and Hourly Rate provided - calculate Hours/Week + is_nil(hours_per_week) && not is_nil(hourly_rate) && not is_nil(annual_tc) -> + calculated_hours = div(annual_tc, hourly_rate * 52) + + %{ + "developers" => params["developers"], + "hourly_rate" => to_string(hourly_rate), + "hours_per_week" => to_string(calculated_hours), + "annual_tc" => to_string(annual_tc) + } + + # Case 3: Hours/Week and Hourly Rate provided - calculate Annual TC + is_nil(annual_tc) && not is_nil(hourly_rate) && not is_nil(hours_per_week) -> + calculated_tc = hourly_rate * hours_per_week * 52 + + %{ + "developers" => params["developers"], + "hourly_rate" => to_string(hourly_rate), + "hours_per_week" => to_string(hours_per_week), + "annual_tc" => to_string(calculated_tc) + } + + # Default case: return original params if we don't have enough information + true -> + params + end + end + + defp calculate_roi_estimate(params) do + developers = String.to_integer(params["developers"]) + hourly_rate = String.to_integer(params["hourly_rate"]) + hours_per_week = String.to_integer(params["hours_per_week"]) + annual_tc = hourly_rate * hours_per_week * 52 + + # Base monthly cost (same for both traditional and Algora) + monthly_base_cost = developers * hourly_rate * hours_per_week * 4.3 + + # Traditional hiring costs (35% overhead - industry average per SBA) + traditional_cost = monthly_base_cost + traditional_overhead = traditional_cost * 0.35 + traditional_total = traditional_cost + traditional_overhead + + # Algora costs + platform_fee = 0.15 + monthly_subscription = 599 + algora_cost = monthly_base_cost + algora_fee = algora_cost * platform_fee + algora_total = algora_cost + algora_fee + monthly_subscription + + yearly_savings = (traditional_total - algora_total) * 12 + + %ROIEstimate{ + developers: developers, + hourly_rate: hourly_rate, + hours_per_week: hours_per_week, + annual_tc: annual_tc, + platform_fee: platform_fee, + traditional_cost: traditional_cost, + traditional_overhead: traditional_overhead, + traditional_total: traditional_total, + algora_cost: algora_cost, + algora_fee: algora_fee, + monthly_subscription: monthly_subscription, + algora_total: algora_total, + savings: yearly_savings + } + end + + # Component: Pricing Card + def pricing_card(assigns) do + ~H""" +
    +
    +
    +
    +

    + {@plan.name} +

    + <%= if @plan.popular do %> + + Most Popular + + <% end %> +
    +
    +

    + {@plan.description} +

    + +
    +
    + <%= if @plan.price do %> +
    +

    From

    +
    +

    ${@plan.price}

    +

    / month

    +
    +
    + <% else %> +
    +

    Custom

    +
    + <% end %> +
    +
    +
    +
    +

    + {if @plan.previous_tier, + do: "Everything in the #{@plan.previous_tier} Plan, plus:", + else: "Get started with:"} +

    +
      + <%= for feature <- @plan.features do %> +
    • +
      +
      + <.icon name="tabler-check" class="h-4 w-4 text-primary" /> +
      + {feature.name} +
      + <%= if feature.detail do %> +

      {feature.detail}

      + <% end %> +
    • + <% end %> +
    + <%= if @plan.footnote do %> +
    +
    +

    + {@plan.footnote} +

    +
    +
    + <% end %> +
    +
    + """ + end + + # Component: Compute Add-ons + def compute_addons(assigns) do + ~H""" +
    +
    +

    Compute Add-ons

    +

    + Additional compute resources for demanding workloads +

    +
    +
    + <%= for option <- @compute_addons do %> +
    + +
    + <% end %> +
    +
    + """ + end + + # Component: Plan Comparison Table + def plan_comparison_table(assigns) do + ~H""" +
    +

    Compare Plans

    +
    + + + + + <%= for plan <- @plans do %> + + <% end %> + + + + <%= for feature <- get_comparison_features() do %> + + + <%= for plan <- @plans do %> + + <% end %> + + <% end %> + +
    Features + {plan.name} +
    {feature.name} + <%= if has_feature?(plan, feature) do %> + <.icon name="tabler-check" class="mx-auto h-5 w-5 text-primary" /> + <% else %> + <.icon name="tabler-minus" class="mx-auto h-5 w-5 text-muted-foreground" /> + <% end %> +
    +
    +
    + """ + end + + # Component: FAQ Section + def faq_section(assigns) do + ~H""" +
    +

    + Frequently asked questions +

    +
    + <%= for item <- @faq_items do %> +
    + + <%= if @active_faq == item.id do %> +
    + {item.answer} +
    + <% end %> +
    + <% end %> +
    +
    + """ + end + + # New ROI Calculator Component + def roi_calculator(assigns) do + ~H""" +
    +

    Calculate Your Savings

    + +
    +
    +
    + + +
    + +
    + + +
    + +
    + + +
    + +
    + + +
    +
    +
    + + <%= if @roi_estimate do %> +
    +
    +
    +

    Traditional Hiring

    +
    +
    + Base Monthly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_cost))} + +
    +
    + Overhead (35%) + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_overhead))} + +
    +
    + Total Monthly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_total))} + +
    +
    + Total Yearly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.traditional_total * 12))} + +
    +
    +
    + +
    +

    With Algora

    +
    +
    + Base Monthly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_cost))} + +
    +
    + + Platform Fee ({trunc(@roi_estimate.platform_fee * 100)}%) + + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_fee))} + +
    +
    + + Placement Fee (0%) + + + $0.00 + +
    +
    + Monthly Subscription + + ${Number.Delimit.number_to_delimited(@roi_estimate.monthly_subscription)} + +
    +
    + Total Monthly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_total))} + +
    +
    + Total Yearly Cost + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.algora_total * 12))} + +
    +
    +
    +
    + +
    +
    + Estimated Yearly Savings + + ${Number.Delimit.number_to_delimited(trunc(@roi_estimate.savings))} + +
    +

    + Savings include reduced recruitment costs, social security taxes, and administrative expenses. +

    +
    +
    + <% end %> +
    + """ + end + + # Data functions + defp get_plans do + [ + %Plan{ + name: "Hobby", + description: "Perfect for small projects and indie developers", + price: 0, + cta_text: "Start for Free", + popular: false, + features: [ + %Feature{name: "Up to $5,000 in project budgets"}, + %Feature{name: "Algora Network", detail: "15% platform fee"}, + %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, + %Feature{name: "Unlimited projects"}, + %Feature{name: "Community support"}, + %Feature{name: "Basic project management tools"}, + %Feature{name: "Pay per milestone"} + ], + footnote: "Perfect for testing the waters with smaller projects" + }, + %Plan{ + name: "Startup", + description: "For growing companies", + price: 599, + cta_text: "Upgrade now", + popular: true, + previous_tier: "Hobby", + features: [ + %Feature{name: "Up to $50,000 in project budgets"}, + %Feature{name: "Algora Network", detail: "15% platform fee"}, + %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, + %Feature{name: "Priority support"}, + %Feature{name: "Advanced project management"}, + %Feature{name: "Custom workflows"}, + %Feature{name: "Team collaboration tools"}, + %Feature{name: "Analytics dashboard"}, + %Feature{name: "Job board access"}, + %Feature{name: "Unlimited job postings"} + ] + }, + %Plan{ + name: "Enterprise", + description: "For large organizations", + price: nil, + cta_text: "Contact Sales", + popular: false, + previous_tier: "Startup", + features: [ + %Feature{name: "Unlimited project budgets"}, + %Feature{name: "Algora Network", detail: "15% platform fee"}, + %Feature{name: "Bring Your Own Devs", detail: "5% platform fee"}, + %Feature{name: "Dedicated account manager"}, + %Feature{name: "Custom contracts & MSA"}, + %Feature{name: "Advanced security features"}, + %Feature{name: "Custom integrations"}, + %Feature{name: "SLA guarantees"}, + %Feature{name: "Onboarding assistance"}, + %Feature{name: "Training for your team"}, + %Feature{name: "Custom job board"}, + %Feature{name: "ATS integration"} + ] + } + ] + end + + defp get_faq_items do + [ + %FaqItem{ + id: "platform-fee", + question: "How do the platform fees work?", + answer: + "We charge 15% for projects using the Algora Network of developers, or 5% if you bring your own developers. This fee helps us maintain the platform, provide payment protection, and ensure quality service." + }, + %FaqItem{ + id: "budget-limits", + question: "What happens if my project exceeds the budget limit?", + answer: + "You'll need to upgrade to a higher tier to handle larger project budgets. Contact our sales team if you're close to your limit." + }, + %FaqItem{ + id: "payment-protection", + question: "How does payment protection work?", + answer: + "We hold payments in escrow and release them based on project milestones. This ensures both clients and developers are protected throughout the project lifecycle." + } + ] + end + + defp get_comparison_features do + [ + %Feature{name: "Project Budget Limit"}, + %Feature{name: "Algora Network Fee"}, + %Feature{name: "Bring Your Own Devs Fee"}, + %Feature{name: "Support Level"}, + %Feature{name: "Team Management"}, + %Feature{name: "Custom Contracts"}, + %Feature{name: "Analytics"} + ] + end + + defp has_feature?(plan, feature) do + Enum.any?(plan.features, &(&1.name == feature.name)) + end + + defp get_testimonials do + [ + %{ + name: "Sarah Chen", + role: "CTO at TechCorp", + avatar: "https://images.unsplash.com/photo-1494790108377-be9c29b29330", + quote: + "Algora has transformed how we hire developers. The quality of talent and the seamless platform experience has made scaling our team effortless." + }, + %{ + name: "Michael Rodriguez", + role: "Engineering Lead at StartupX", + avatar: "https://images.unsplash.com/photo-1472099645785-5658abf4ff4e", + quote: + "The developers we found through Algora have become integral parts of our team. The platform's focus on open source contributors really makes a difference." + }, + %{ + name: "Emily Thompson", + role: "VP Engineering at ScaleUp Inc", + avatar: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80", + quote: + "What impressed me most was how quickly we could find and onboard qualified developers. Algora's platform streamlines the entire process." + } + ] + end + + def render(assigns) do + ~H""" +
    +
    +
    +
    +

    + Predictable pricing,
    designed to scale +

    +

    + Start building for free, collaborate with your team, then scale to millions of users +

    +
    +
    +
    + +
    +
    +
    + <%= for plan <- @plans do %> + <.pricing_card plan={plan} /> + <% end %> +
    + + <.roi_calculator roi_estimate={@roi_estimate} /> +
    + +
    +
    +
    +

    + Trusted by companies worldwide +

    +

    + See what our customers have to say about their experience with Algora +

    +
    +
    + <%= for testimonial <- @testimonials do %> +
    +
    + +
    +
    {testimonial.name}
    +
    {testimonial.role}
    +
    +
    +
    + {testimonial.quote} +
    +
    + <% end %> +
    +
    +
    + +
    +

    + Frequently asked questions +

    +
    + <%= for item <- @faq_items do %> +
    + + <%= if @active_faq == item.id do %> +
    + {item.answer} +
    + <% end %> +
    + <% end %> +
    +
    +
    + +
    +
    +

    + The open source + UpWork alternative. +

    +
    + <.link + navigate="/signup" + class="inline-flex h-10 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50" + > + Start your project + + <.link + navigate="/contact/sales" + class="inline-flex h-10 items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50" + > + Request a demo + +
    +
    +
    +
    + """ + end +end diff --git a/lib/algora_web/router.ex b/lib/algora_web/router.ex index a27adf879..75fcd7264 100644 --- a/lib/algora_web/router.ex +++ b/lib/algora_web/router.ex @@ -132,6 +132,11 @@ defmodule AlgoraWeb.Router do live "/pricing", PricingLive end + live_session :tmp, + on_mount: [{AlgoraWeb.VisitorCountry, :current_country}] do + live "/tmp/pricing", Tmp.PricingLive + end + live "/trotw", TROTWLive live "/open-source", OpenSourceLive, :index