diff --git a/lib/algora_web/live/home_live.ex b/lib/algora_web/live/home_live.ex index 996fd76b2..651a422a4 100644 --- a/lib/algora_web/live/home_live.ex +++ b/lib/algora_web/live/home_live.ex @@ -2,18 +2,26 @@ defmodule AlgoraWeb.HomeLive do @moduledoc false use AlgoraWeb, :live_view + import Ecto.Changeset import Ecto.Query import Phoenix.LiveView.TagEngine import Tails, only: [classes: 1] alias Algora.Accounts alias Algora.Accounts.User + alias Algora.Bounties alias Algora.Payments.Transaction + alias Algora.PSP.ConnectCountries alias Algora.Repo + alias Algora.Workspace alias AlgoraWeb.Components.Footer alias AlgoraWeb.Components.Header alias AlgoraWeb.Components.Wordmarks alias AlgoraWeb.Data.PlatformStats + alias AlgoraWeb.Forms.BountyForm + alias AlgoraWeb.Forms.TipForm + + require Logger @impl true def mount(%{"country_code" => country_code}, _session, socket) do @@ -29,17 +37,21 @@ defmodule AlgoraWeb.HomeLive do {:ok, socket |> assign(:featured_devs, Accounts.list_featured_developers(country_code)) - |> assign(:stats, stats)} + |> assign(:stats, stats) + |> assign(:faq_items, get_faq_items()) + |> assign(:bounty_form, to_form(BountyForm.changeset(%BountyForm{}, %{}))) + |> assign(:tip_form, to_form(TipForm.changeset(%TipForm{}, %{}))) + |> assign(:pending_action, nil)} end @impl true def render(assigns) do ~H""" -
+
-
+
- +
+ +
+
+

+ Fund GitHub Issues +

+

+ Support open source development with bounties on GitHub issues +

+ +
+ <.link + href="https://github.com/zed-industries/zed/issues/4440" + rel="noopener" + class="relative flex items-center gap-x-4 rounded-xl bg-card/50 p-6 ring-1 ring-border hover:bg-card/70 transition-colors" + > +
+ Zed + Scott Chacon +
+
+
Scott Chacon
+
GitHub Cofounder
+
+ Funded Vim replace mode in Zed Editor +
+
+
$500
+ + + <.link + href="https://github.com/PX4/PX4-Autopilot/issues/22464" + rel="noopener" + class="relative flex items-center gap-x-4 rounded-xl bg-card/50 p-6 ring-1 ring-border hover:bg-card/70 transition-colors" + > + PX4 +
+
PX4 Autopilot
+
+ Open Source Autopilot for Drone Developers +
+
+ Community funded collision prevention system +
+
+
$1,000
+ + + <.link + href="https://github.com/calcom/cal.com/issues/11953" + class="relative flex items-center gap-x-4 rounded-xl bg-card/50 p-6 ring-1 ring-border hover:bg-card/70 transition-colors" + > +
+ Cal.com + Framer +
+
+
Framer
+
Design & Prototyping Tool
+
+ Funded multiple round-robin hosts in Cal.com +
+
+
$500
+ + <.link + navigate={~p"/org/coollabsio"} + class="relative flex items-center gap-x-4 rounded-xl bg-card/50 p-6 ring-1 ring-border hover:bg-card/70 transition-colors" + > + Coolify +
+
Coolify
+
+ Self-Hosted Heroku Alternative +
+
+ Community funded features +
+
+
$2,543
+ +
+
+
+

+ Fund any issue + in seconds +

+
+ <.card class="bg-muted/30"> + <.card_header> +
+ <.icon name="tabler-diamond" class="h-8 w-8" /> +

Post a bounty

+
+ + <.card_content> + <.simple_form for={@bounty_form} phx-submit="create_bounty"> +
+ <.input + label="URL" + field={@bounty_form[:url]} + placeholder="https://github.com/owner/repo/issues/1337" + /> + <.input + label="Amount" + icon="tabler-currency-dollar" + field={@bounty_form[:amount]} + /> +
+ <.button variant="subtle">Submit +
+
+ + + + <.card class="bg-muted/30"> + <.card_header> +
+ <.icon name="tabler-gift" class="h-8 w-8" /> +

Tip a developer

+
+ + <.card_content> + <.simple_form for={@tip_form} phx-submit="create_tip"> +
+ <.input + label="GitHub handle" + field={@tip_form[:github_handle]} + placeholder="jsmith" + /> + <.input label="Amount" icon="tabler-currency-dollar" field={@tip_form[:amount]} /> +
+ <.button variant="subtle">Submit +
+
+ + + +
+
+
+ +
+
+

+ Streamline Contract Work +

+

+ Use bounties in your own repositories to manage contract work efficiently. Pay only for completed tasks, with full GitHub integration. +

+
+
+ <.icon name="tabler-git-pull-request" class="h-12 w-12 mb-4 text-primary" /> +

Native GitHub Workflow

+

+ Work directly in GitHub using issues and pull requests - no context switching needed. +

+
+
+ <.icon name="tabler-shield-check" class="h-12 w-12 mb-4 text-primary" /> +

Secure Payments

+

+ Pay only for completed work. No upfront costs - payments are processed after successful code review and merge. +

+
+
+ <.icon name="tabler-users" class="h-12 w-12 mb-4 text-primary" /> +

Global Talent Pool

+

+ Access vetted developers from around the world, specialized in your tech stack. +

+
+
+
+
+
+ +
+

Bounties

+

+ Fund Issues +

+

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

+
+
+
+
+
+ +
+

Tips

+

+ Show Appreciation +

+

+ Say thanks with tips to recognize valuable contributions +

+
+
+
+
+
+
+
+
+
+
+
+ +

+ Merged pull request +

+
+
+
+
+ +

+ Completed payment +

+
+
+
+
+ + + + + + +

+ Transferring funds to contributor +

+
+
+
+
+
+
+

Payments

+

+ Pay When Merged +

+

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

+
+
+
+ +
+

Payouts

+

+ Fast, Global Payouts +

+

+ Receive payments directly to your bank account from all around the world + (120 countries supported) +

+
+
+
+
+
+
+ +
+

Contracts

+

+ Flexible Engagement +

+

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

+
+
+
+
+
+
+ +
+
+

+ Hire with Confidence +

+

+ Find your next team member through real-world collaboration. Use bounties to evaluate developers based on actual contributions to your codebase. +

+
+
+ <.icon name="tabler-code" class="h-12 w-12 mb-4 text-primary" /> +

Try Before You Hire

+

+ Evaluate candidates through real contributions to your projects, not just interviews. +

+
+
+ <.icon name="tabler-target" class="h-12 w-12 mb-4 text-primary" /> +

Find Domain Experts

+

+ Connect with developers who have proven expertise in your specific tech stack. +

+
+
+ <.icon name="tabler-rocket" class="h-12 w-12 mb-4 text-primary" /> +

Fast Onboarding

+

+ Hire developers who are already familiar with your codebase and workflow. +

+
+
+
+
+
+
+ +
+
+
+

+ $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 %> +
+ + +
+ <% end %> +
+
+
+ +
+
+

+ The open source + UpWork alternative. +

+
+ <.button navigate="/onboarding/org"> + Start your project + + <.button href="https://cal.com/ioannisflo" variant="secondary"> + Request a demo + +
+
+
+ +
@@ -161,7 +827,97 @@ defmodule AlgoraWeb.HomeLive do """ end - def dev_card(assigns) do + @impl true + def handle_event("create_bounty" = event, %{"bounty_form" => params} = unsigned_params, socket) do + changeset = + %BountyForm{} + |> BountyForm.changeset(params) + |> Map.put(:action, :validate) + + amount = get_field(changeset, :amount) + ticket_ref = get_field(changeset, :ticket_ref) + + if changeset.valid? do + if socket.assigns[:current_user] do + case Bounties.create_bounty(%{ + creator: socket.assigns.current_user, + owner: socket.assigns.current_user, + amount: amount, + ticket_ref: ticket_ref + }) do + {:ok, _bounty} -> + {:noreply, + socket + |> put_flash(:info, "Bounty created") + |> redirect(to: ~p"/")} + + {:error, :already_exists} -> + {:noreply, put_flash(socket, :warning, "You have already created a bounty for this ticket")} + + {:error, _reason} -> + {:noreply, put_flash(socket, :error, "Something went wrong")} + end + else + {:noreply, + socket + |> assign(:pending_action, {event, unsigned_params}) + |> push_event("open_popup", %{url: socket.assigns.oauth_url})} + end + else + {:noreply, assign(socket, :bounty_form, to_form(changeset))} + end + end + + @impl true + def handle_event("create_tip" = event, %{"tip_form" => params} = unsigned_params, socket) do + changeset = + %TipForm{} + |> TipForm.changeset(params) + |> Map.put(:action, :validate) + + if changeset.valid? do + if socket.assigns[:current_user] do + with {:ok, token} <- Accounts.get_access_token(socket.assigns.current_user), + {:ok, recipient} <- Workspace.ensure_user(token, get_field(changeset, :github_handle)), + {:ok, checkout_url} <- + Bounties.create_tip(%{ + creator: socket.assigns.current_user, + owner: socket.assigns.current_user, + recipient: recipient, + amount: get_field(changeset, :amount) + }) do + {:noreply, redirect(socket, external: checkout_url)} + else + {:error, reason} -> + Logger.error("Failed to create tip: #{inspect(reason)}") + {:noreply, put_flash(socket, :error, "Something went wrong")} + end + else + {:noreply, + socket + |> assign(:pending_action, {event, unsigned_params}) + |> push_event("open_popup", %{url: socket.assigns.oauth_url})} + end + else + {:noreply, assign(socket, :tip_form, to_form(changeset))} + end + end + + @impl true + def handle_info({:authenticated, user}, socket) do + socket = assign(socket, :current_user, user) + + case socket.assigns.pending_action do + {event, params} -> + socket = assign(socket, :pending_action, nil) + handle_event(event, params, socket) + + nil -> + {:noreply, socket} + end + end + + defp dev_card(assigns) do ~H"""
Money.round(currency_digits: 0) |> Money.to_string!(no_fraction_if_integer: true) defp format_number(number), do: Number.Delimit.number_to_delimited(number, precision: 0) + + defmodule FaqItem do + @moduledoc false + defstruct [:id, :question, :answer] + end + + defp get_faq_items do + [ + %FaqItem{ + id: "platform-fee", + question: "How do the platform fees work?", + answer: + "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: "payment-methods", + question: "What payment methods do you support?", + answer: + ~s(We support payments via Stripe for funding bounties. Contributors can receive payments directly to their bank accounts in #{ConnectCountries.count()} countries/regions worldwide.) + }, + %FaqItem{ + id: "payment-process", + question: "How does the payment process work?", + answer: + "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." + }, + %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." + }, + %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/regions 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 end diff --git a/priv/static/images/screenshots/payout-account-compact.png b/priv/static/images/screenshots/payout-account-compact.png new file mode 100644 index 000000000..cbc21bf5d Binary files /dev/null and b/priv/static/images/screenshots/payout-account-compact.png differ