diff --git a/lib/algora_web/components/header.ex b/lib/algora_web/components/header.ex index 83452f7a8..5de4bff87 100644 --- a/lib/algora_web/components/header.ex +++ b/lib/algora_web/components/header.ex @@ -5,6 +5,15 @@ defmodule AlgoraWeb.Components.Header do import AlgoraWeb.CoreComponents + defp nav_links do + [ + %{name: "Bounties", path: ~p"/bounties"}, + %{name: "Testimonials", path: ~p"/testimonials"}, + %{name: "Crowdfund", path: ~p"/crowdfund"}, + %{name: "Pricing", path: ~p"/pricing"} + ] + end + def header(assigns) do ~H"""
@@ -25,30 +34,14 @@ defmodule AlgoraWeb.Components.Header do + +
@@ -222,10 +225,19 @@ defmodule AlgoraWeb.HomeLive do
+
+ +
+
+

+ Hire by building product +

+

+ Use bounties to evaluate developers based on actual contributions to your codebase +

-
-
-
+
+
<.modal_video class="aspect-[9/16] rounded-xl lg:rounded-2xl lg:rounded-r-none" @@ -241,7 +253,7 @@ defmodule AlgoraWeb.HomeLive do href="https://github.com/golemcloud/golem/issues/1004" rel="noopener" target="_blank" - class="relative flex aspect-[1121/1343] w-full items-center justify-center overflow-hidden rounded-xl lg:rounded-2xl lg:rounded-l-none bg-gray-800" + class="relative flex aspect-[1121/1343] w-full items-center justify-center overflow-hidden rounded-xl lg:rounded-2xl lg:rounded-l-none" >
-
-
-
-
- Fund any issue - - in seconds - -
-
- Help improve the OSS you love and rely on -
-
-
- <.icon name="tabler-check" class="h-4 w-4 mr-1 text-success-400" /> - Pay when PRs are merged -
-
- <.icon name="tabler-check" class="h-4 w-4 mr-1 text-success-400" /> - Pool bounties with other sponsors -
-
- <.icon name="tabler-check" class="h-4 w-4 mr-1 text-success-400" /> - Algora handles invoices, payouts, compliance -
-
-
- <.form - for={@bounty_form} - phx-submit="create_bounty" - class="lg:col-span-3 grid grid-cols-1 gap-4 sm:gap-6 w-full" - > - <.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]} - class="placeholder:text-success" - /> -
- <.button size="lg" class="w-full drop-shadow-[0_1px_5px_#34d39980]"> - Fund issue - -
No credit card required
-
- -
-
- <.link - href="https://github.com/zed-industries/zed/issues/4440" - rel="noopener" - target="_blank" - class="relative flex flex-col sm:flex-row items-start sm:items-center gap-4 sm:gap-x-4 rounded-xl bg-black p-4 sm:p-6 ring-1 ring-border transition-colors" - > -
- Zed - Scott Chacon -
-
-
- GitHub cofounder funds new feature in Zed Editor -
-
- Zed Editor, Scott Chacon -
-
- <.button size="lg" variant="secondary" class="hidden sm:flex mt-2 sm:mt-0"> - View issue - - - - <.link - href="https://github.com/PX4/PX4-Autopilot/issues/22464" - rel="noopener" - target="_blank" - class="relative flex flex-col sm:flex-row items-start sm:items-center gap-4 sm:gap-x-4 rounded-xl bg-black p-4 sm:p-6 ring-1 ring-border transition-colors" - > -
- Alex Klimaj - PX4 - Andrew Wilkins -
-
-
- DefenceTech CEOs fund obstacle avoidance in PX4 Autopilot -
-
- Alex Klimaj, Founder of ARK Electronics & Andrew Wilkins, CEO of Ascend Engineering -
-
- <.button size="lg" variant="secondary" class="hidden sm:flex mt-2 sm:mt-0"> - View issue - - - - <.link - href={~p"/org/coollabsio"} - rel="noopener" - class="relative flex flex-col sm:flex-row items-start sm:items-center gap-4 sm:gap-x-4 rounded-xl bg-black p-4 sm:p-6 ring-1 ring-border transition-colors" - > -
- Coolify - Andras Bacsai -
-
-
- Coolify community crowdfunds new feature development -
-
- Andras Bacsai, Founder of Coolify -
-
- <.button - size="lg" - variant="secondary" - class="hidden sm:flex mt-2 sm:mt-0 ring-2 ring-emerald-500" - > - View bounty board - - -
-
-
-
-
- -
-
- Y Combinator Logo -

- YCombinator companies use Algora
to build product and hire engineers -

-
- <.yc_logo_cloud /> -
- -
-
-
-
- Tal Borenstein -
-
-
-

- Keep has 90+ integrations to alert our customers about critical events. Of these, - <.link - href="https://github.com/keephq/keep/issues?q=state%3Aclosed%20label%3A%22%F0%9F%92%8E%20Bounty%22%20%20label%3A%22%F0%9F%92%B0%20Rewarded%22%20label%3AProvider%20" - rel="noopener" - target="_blank" - class="text-success inline-flex items-center hover:text-success-300" - > - 42 integrations <.icon name="tabler-external-link" class="size-5 ml-1 mb-4" /> - - were built - using bounties on Algora. -

-
-
-
-
- Tal Borenstein -
-
- Co-founder & CEO at Keep (YC W23) -
-
-
-
-
-
-
-
-
- -
-
-

- Build product faster -

-

- Use bounties for outcome-based contract work with full GitHub integration. -

-
-
-
-
- Louis Beaumont -
-
-
-

- I posted our bounty on Upwork - to try it, overall it's 1000x more friction - than OSS bounties with Algora. -

-
-
-
-
- Louis Beaumont -
-
- Co-founder & CEO at Screenpipe -
-
-
-
-
-
-
- -
-
-
-
- Cal.com - PeerRich - Bailey Pumfleet -
-
-
-
- Used bounties -
-
- every month -
-
- for 2+ years -
-
-
-
-
-
- Shipped by 86 contributors -
-
    -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 14 - High Priority tickets -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 24 Improvements -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 21 Bugs -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 36 - Medium priority tickets -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 13 UI updates -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 68 New Features -
  • -
  • - <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> - 18 Integrations -
  • -
-
-
-
- -
-
-
-
- Josh Pigford -
-
-
-

- Let's offer a bounty - to say "Hey, someone please prioritize this, who has the skillset for it?" I think long term I'd like to make it a - very consistent - part of our development process. -

-
-
-
-
- Josh Pigford -
-
- Co-founder & CEO at Maybe -
-
-
-
-
-
-
-
-
-
- John A De Goes -
-
-
-

- We used Algora extensively at Ziverge to reward over - $70,000 - in bounties and introduce a whole - new generation of contributors - to the ZIO ecosystem. -

-
-
-
-
- John A De Goes -
-
- Founder & CEO at Ziverge -
-
-
-
- <%!--
-
-
- Total awarded -
-
- $77,175 -
-
-
-
- Bounties completed -
-
- 359 -
-
-
-
- Contributors rewarded -
-
- 79 -
-
-
--%> -
-
-
-
-
- -
-
-

- Hire by building product -

-

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

@@ -743,7 +307,7 @@ defmodule AlgoraWeb.HomeLive do src="https://www.youtube.com/embed/3wZGDuoPajk" start={13} title="OSS Bounties & Hiring engineers on Algora.io | Founder Testimonial" - poster="https://img.youtube.com/vi/3wZGDuoPajk/maxresdefault.jpg" + poster={~p"/images/misc/3wZGDuoPajk.png"} alt="Tushar Mathur" />
@@ -771,88 +335,7 @@ defmodule AlgoraWeb.HomeLive do
-
-
-
- <.link - class="font-bold font-display text-2xl whitespace-nowrap flex items-center justify-center brightness-0 invert" - aria-label="Logo" - navigate={~p"/org/mendableai"} - > - 🔥 - Firecrawl - -

- Open source contributor to full-time engineer -

-
-
-
-
-
- Nicolas Camara -
-
- Founder & CTO -
-
- Nicolas Camara -
-
- <.icon - name="tabler-git-merge" - class="size-6 sm:size-8 text-purple-400 hidden sm:block" - /> -
-
- Gergő Móricz -
-
- Gergő Móricz -
-
- Contributor -
-
-
-
-
-
-
- <.modal_video - class="aspect-[9/16] rounded-xl lg:rounded-2xl" - src="https://www.youtube.com/embed/j4fLNIJCywk" - title="High school student solves #opensource bounties" - poster="https://img.youtube.com/vi/j4fLNIJCywk/maxresdefault.jpg" - alt="Gergő Móricz" - /> -
-
- <.modal_video - class="rounded-xl lg:rounded-2xl" - src="https://www.youtube.com/embed/HhTT-GX5tjQ" - start={293} - title="🧑🏻‍💻 Building your bounty hunter reputation & Mendable contributions 💸" - poster={~p"/images/people/mogery.png"} - alt="Gergő Móricz" - /> -
-
-
-
-
- -
+
@@ -860,7 +343,7 @@ defmodule AlgoraWeb.HomeLive do

Simple, transparent pricing

-

+

For individuals, OSS communities, and open/closed source companies

@@ -887,106 +370,54 @@ defmodule AlgoraWeb.HomeLive do <% end %>
+
+
-
-
-
-

-
- <.icon name="tabler-building-store" class="h-6 w-6 text-purple-400" /> Platform -
-

-

- Connect with top open source talent, increase project visibility, and hire proven contributors -

+
+
+
+
+
+ Algora dashboard
-
- <%= for plan <- @plans2 do %> - - <% end %> -
-
-
- -
-
-

- Did you know? -

-

- You can tip your favorite open source contributors with Algora. -

- -
-
-
-
-

- Tip any contributor - instantly -

-

- Support the maintainers behind your favorite open source projects -

-
-
- <.icon name="tabler-check" class="h-5 w-5 text-indigo-400 flex-none" /> - Send tips directly to GitHub usernames -
-
- <.icon name="tabler-check" class="h-5 w-5 text-indigo-400 flex-none" /> - Algora handles payouts, compliance & 1099s -
-
-
+
+ <.glow class="absolute opacity-25 xl:opacity-75 top-[-320px] md:top-[-480px] xl:right-[120px] -z-[10]" /> - <.form - for={@tip_form} - phx-submit="create_tip" - class="lg:col-span-4 space-y-4 sm:space-y-6" + <.form + for={@repo_form} + phx-submit="submit_repo" + class="mt-6 sm:mt-10 w-full max-w-lg xl:max-w-2xl mx-auto hidden" + > +
+ <.input + field={@repo_form[:url]} + placeholder="github.com/your/repo" + class={ + classes([ + "w-full h-10 sm:h-16 text-sm sm:text-lg xl:text-2xl pl-8 sm:pl-[3.75rem] pr-24 sm:pr-48 ring-2 ring-emerald-500 font-display rounded-lg sm:rounded-xl", + @repo_form[:url].errors != [] && "ring-destructive" + ]) + } + /> + + <.button + type="submit" + class="absolute right-2 top-1.5 sm:top-2 bottom-1.5 sm:bottom-2 px-2 sm:px-8 h-7 sm:h-[3rem] text-sm sm:text-xl sm:font-semibold drop-shadow-[0_1px_5px_#34d39980] rounded-lg sm:rounded-xl" > -
- <.input - label="GitHub handle" - field={@tip_form[:github_handle]} - placeholder="jsmith" - /> - <.input - label="Amount" - icon="tabler-currency-dollar" - field={@tip_form[:amount]} - class="placeholder:text-indigo-500" - /> -
- <.input - label="URL" - field={@tip_form[:url]} - placeholder="https://github.com/owner/repo/issues/123" - helptext="We'll comment to notify the developer." - /> -
- <.button - size="lg" - class="w-full drop-shadow-[0_1px_5px_#818cf880]" - variant="indigo" - > - Tip contributor - -
- + Get Started +
-
- -
- Tip contributor -
+
diff --git a/lib/algora_web/live/testimonials.ex b/lib/algora_web/live/testimonials.ex new file mode 100644 index 000000000..91e4188da --- /dev/null +++ b/lib/algora_web/live/testimonials.ex @@ -0,0 +1,1534 @@ +defmodule AlgoraWeb.TestimonialsLive do + @moduledoc false + use AlgoraWeb, :live_view + use LiveSvelte.Components + + import Ecto.Changeset + import Ecto.Query + + alias Algora.Accounts + alias Algora.Accounts.User + alias Algora.Bounties + alias Algora.Github + alias Algora.Payments.Transaction + alias Algora.Repo + alias Algora.Workspace + alias AlgoraWeb.Components.Footer + alias AlgoraWeb.Components.Header + alias AlgoraWeb.Components.Logos + alias AlgoraWeb.Data.PlatformStats + alias AlgoraWeb.Forms.BountyForm + alias AlgoraWeb.Forms.TipForm + + require Logger + + defmodule RepoForm do + @moduledoc false + use Ecto.Schema + + import Ecto.Changeset + + @primary_key false + embedded_schema do + field :url, :string + end + + def changeset(form, attrs) do + form + |> cast(attrs, [:url]) + |> validate_required([:url]) + end + end + + @impl true + def mount(params, _session, socket) do + stats = [ + %{label: "Paid Out", value: format_money(get_total_paid_out())}, + %{label: "Completed Bounties", value: format_number(get_completed_bounties_count())}, + %{label: "Contributors", value: format_number(get_contributors_count())}, + %{label: "Countries", value: format_number(get_countries_count())} + ] + + if connected?(socket) do + Phoenix.PubSub.subscribe(Algora.PubSub, "auth:#{socket.id}") + end + + {:ok, + socket + |> assign(:page_title, "Algora - The open source Upwork for engineers") + |> assign(:page_image, "#{AlgoraWeb.Endpoint.url()}/images/og/home.png") + |> assign(:screenshot?, not is_nil(params["screenshot"])) + |> assign(:oauth_url, Github.authorize_url(%{socket_id: socket.id})) + |> assign(:featured_devs, Accounts.list_featured_developers()) + |> assign(:stats, stats) + |> assign(:bounty_form, to_form(BountyForm.changeset(%BountyForm{}, %{}))) + |> assign(:tip_form, to_form(TipForm.changeset(%TipForm{}, %{}))) + |> assign(:repo_form, to_form(RepoForm.changeset(%RepoForm{}, %{}))) + |> assign(:pending_action, nil) + |> assign(:plans1, AlgoraWeb.PricingLive.get_plans1()) + |> assign(:plans2, AlgoraWeb.PricingLive.get_plans2())} + end + + attr :src, :string, required: true + attr :poster, :string, required: true + attr :title, :string, default: nil + attr :alt, :string, default: nil + attr :class, :string, default: nil + attr :autoplay, :boolean, default: true + attr :start, :integer, default: 0 + + defp modal_video(assigns) do + ~H""" +
JS.set_attribute({"src", @src <> "?autoplay=#{@autoplay}&start=#{@start}"}, + to: "#video-modal-iframe" + ) + |> JS.set_attribute({"title", @title}, to: "#video-modal-iframe") + |> show_modal("video-modal") + } + > + {@alt} +
+
+ <.icon name="tabler-player-play-filled" class="size-5 sm:size-8 text-white" /> +
+
+
+ """ + end + + @impl true + def render(assigns) do + ~H""" +
+ <%= if @screenshot? do %> +
+ <% else %> + + <% end %> + +
+
+
+ Y Combinator Logo +

+ YCombinator companies use Algora
to build product and hire engineers +

+
+ <.yc_logo_cloud /> +
+ +
+
+
+
+ Tal Borenstein +
+
+
+

+ Keep has 90+ integrations to alert our customers about critical events. Of these, + <.link + href="https://github.com/keephq/keep/issues?q=state%3Aclosed%20label%3A%22%F0%9F%92%8E%20Bounty%22%20%20label%3A%22%F0%9F%92%B0%20Rewarded%22%20label%3AProvider%20" + rel="noopener" + target="_blank" + class="text-success inline-flex items-center hover:text-success-300" + > + 42 integrations <.icon name="tabler-external-link" class="size-5 ml-1 mb-4" /> + + were built + using bounties on Algora. +

+
+
+
+
+ Tal Borenstein +
+
+ Co-founder & CEO at Keep (YC W23) +
+
+
+
+
+
+
+
+
+ +
+
+

+ Build product faster +

+

+ Use bounties for outcome-based contract work with full GitHub integration. +

+
+
+
+
+ Louis Beaumont +
+
+
+

+ I posted our bounty on Upwork + to try it, overall it's 1000x more friction + than OSS bounties with Algora. +

+
+
+
+
+ Louis Beaumont +
+
+ Co-founder & CEO at Screenpipe +
+
+
+
+
+
+
+ +
+
+
+
+ Cal.com + PeerRich + Bailey Pumfleet +
+
+
+
+ Used bounties +
+
+ every month +
+
+ for 2+ years +
+
+
+
+
+
+ Shipped by 86 contributors +
+
    +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 14 + High Priority tickets +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 24 Improvements +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 21 Bugs +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 36 + Medium priority tickets +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 13 UI updates +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 68 New Features +
  • +
  • + <.icon name="tabler-check" class="size-6 sm:size-8 text-success" /> + 18 Integrations +
  • +
+
+
+
+ +
+
+
+
+ Josh Pigford +
+
+
+

+ Let's offer a bounty + to say "Hey, someone please prioritize this, who has the skillset for it?" I think long term I'd like to make it a + very consistent + part of our development process. +

+
+
+
+
+ Josh Pigford +
+
+ Co-founder & CEO at Maybe +
+
+
+
+
+
+
+ +
+
+
+
+ John A De Goes +
+
+
+

+ We used Algora extensively at Ziverge to reward over + $70,000 + in bounties and introduce a whole + new generation of contributors + to the ZIO ecosystem. +

+
+
+
+
+ John A De Goes +
+
+ Founder & CEO at Ziverge +
+
+
+
+ <%!--
+
+
+ Total awarded +
+
+ $77,175 +
+
+
+
+ Bounties completed +
+
+ 359 +
+
+
+
+ Contributors rewarded +
+
+ 79 +
+
+
--%> +
+
+
+
+
+ +
+
+

+ Hire by building product +

+

+ Use bounties to evaluate developers based on actual contributions to your codebase. +

+ +
+
+
+ <.modal_video + class="aspect-[9/16] rounded-xl lg:rounded-2xl lg:rounded-r-none" + src="https://www.youtube.com/embed/xObOGcUdtY0" + start={122} + title="$15,000 Open source bounty to hire a Rust engineer" + poster={~p"/images/people/john-de-goes.jpg"} + alt="John A De Goes" + /> +
+
+ <.link + href="https://github.com/golemcloud/golem/issues/1004" + rel="noopener" + target="_blank" + class="relative flex aspect-[1121/1343] w-full items-center justify-center overflow-hidden rounded-xl lg:rounded-2xl lg:rounded-l-none" + > + Golem bounty to hire + +
+
+
+ +
+
+
+ <.modal_video + class="rounded-xl lg:rounded-2xl" + src="https://www.youtube.com/embed/FXQVD02rfg8" + start={8} + title="How Nick got a job with Open Source Software" + poster="https://img.youtube.com/vi/FXQVD02rfg8/maxresdefault.jpg" + alt="Eric Allam" + /> +
+
+

+ It was the easiest hire + because we already knew how great he was +

+
+
+
+
+ Eric Allam +
+
+ Co-founder & CTO at Trigger.dev (YC W23) +
+
+
+
+
+
+
+ +
+
+
+ <.modal_video + class="rounded-xl lg:rounded-2xl" + src="https://www.youtube.com/embed/3wZGDuoPajk" + start={13} + title="OSS Bounties & Hiring engineers on Algora.io | Founder Testimonial" + poster="https://img.youtube.com/vi/3wZGDuoPajk/maxresdefault.jpg" + alt="Tushar Mathur" + /> +
+
+

+ Bounties help us control our burn rate, get work done & meet new hires. I've made + 3 full-time hires + using Algora +

+
+
+
+
+ Tushar Mathur +
+
+ Founder & CEO at Tailcall +
+
+
+
+
+
+
+
+
+ +
+
+
+ <.link + class="font-bold font-display text-2xl whitespace-nowrap flex items-center justify-center brightness-0 invert" + aria-label="Logo" + navigate={~p"/org/mendableai"} + > + 🔥 + Firecrawl + +

+ Open source contributor to full-time engineer +

+
+
+
+
+
+ Nicolas Camara +
+
+ Founder & CTO +
+
+ Nicolas Camara +
+
+ <.icon + name="tabler-git-merge" + class="size-6 sm:size-8 text-purple-400 hidden sm:block" + /> +
+
+ Gergő Móricz +
+
+ Gergő Móricz +
+
+ Contributor +
+
+
+
+
+
+
+ <.modal_video + class="aspect-[9/16] rounded-xl lg:rounded-2xl" + src="https://www.youtube.com/embed/j4fLNIJCywk" + title="High school student solves #opensource bounties" + poster="https://img.youtube.com/vi/j4fLNIJCywk/maxresdefault.jpg" + alt="Gergő Móricz" + /> +
+
+ <.modal_video + class="rounded-xl lg:rounded-2xl" + src="https://www.youtube.com/embed/HhTT-GX5tjQ" + start={293} + title="🧑🏻‍💻 Building your bounty hunter reputation & Mendable contributions 💸" + poster={~p"/images/people/mogery.png"} + alt="Gergő Móricz" + /> +
+
+
+
+
+ +
+
+

+ The open source + Upwork for engineers +

+
+ <.button navigate={~p"/auth/signup"}> + Get started + + <.button + class="pointer-events-none opacity-75" + href={AlgoraWeb.Constants.get(:github_repo_url)} + variant="secondary" + > + <.icon name="github" class="size-4 mr-2 -ml-1" /> View source code + +
+
+
+ +
+ +
+ Upwork® is a registered trademark of Upwork Global Inc. Algora is not affiliated with, sponsored by, or endorsed by Upwork Global Inc, mmmkay? +
+
+
+
+ + <.dialog + id="video-modal" + show={false} + class="aspect-video h-full sm:h-auto w-full lg:max-w-none p-2 sm:p-4 lg:p-[5rem]" + on_cancel={ + %JS{} + |> JS.set_attribute({"src", ""}, to: "#video-modal-iframe") + |> JS.set_attribute({"title", ""}, to: "#video-modal-iframe") + } + > + <.dialog_content class="flex items-center justify-center"> + + + + """ + end + + @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 user = socket.assigns[:current_user] do + case Bounties.create_bounty(%{creator: user, owner: user, amount: amount, ticket_ref: ticket_ref}) do + {:ok, _bounty} -> + user |> change(last_context: user.handle) |> Repo.update() + + {:noreply, + socket + |> put_flash(:info, "Bounty created") + |> redirect(to: AlgoraWeb.UserAuth.generate_login_path(user.email))} + + {:error, :already_exists} -> + {:noreply, put_flash(socket, :warning, "You already have 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 user = socket.assigns[:current_user] do + with {:ok, token} <- Accounts.get_access_token(user), + {:ok, recipient} <- + Workspace.ensure_user(token, get_field(changeset, :github_handle)), + {:ok, checkout_url} <- + Bounties.create_tip(%{ + creator: user, + owner: user, + recipient: recipient, + amount: get_field(changeset, :amount) + }) do + user |> change(last_context: user.handle) |> Repo.update() + {:noreply, redirect(socket, to: AlgoraWeb.UserAuth.generate_login_path(user.email, 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_event("submit_repo", %{"repo_form" => params}, socket) do + changeset = + %RepoForm{} + |> RepoForm.changeset(params) + |> Map.put(:action, :validate) + + if changeset.valid? do + url = get_field(changeset, :url) + + case Algora.Util.parse_github_url(url) do + {:ok, {repo_owner, repo_name}} -> + token = Algora.Admin.token() + + case Workspace.ensure_repository(token, repo_owner, repo_name) do + {:ok, _repo} -> + {:noreply, push_navigate(socket, to: ~p"/go/#{repo_owner}/#{repo_name}")} + + {:error, reason} -> + Logger.error("Failed to create repository: #{inspect(reason)}") + {:noreply, assign(socket, :repo_form, to_form(add_error(changeset, :url, "Repository not found")))} + end + + {:error, message} -> + {:noreply, assign(socket, :repo_form, to_form(add_error(changeset, :url, message)))} + end + else + {:noreply, assign(socket, :repo_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""" + <.link navigate={User.url(@dev)} target="_blank" class="relative"> + {@dev.name} +
+
+ {@dev.name} {Algora.Misc.CountryEmojis.get(@dev.country)} +
+
{@dev.bio}
+ +
+ Total Earned: + + {Money.to_string!(@dev.total_earned, no_fraction_if_integer: true)} + +
+
+ + """ + end + + defp get_total_paid_out do + subtotal = + Repo.one( + from(t in Transaction, + where: t.type == :credit, + where: t.status == :succeeded, + where: not is_nil(t.linked_transaction_id), + select: sum(t.net_amount) + ) + ) || Money.new(0, :USD) + + subtotal |> Money.add!(PlatformStats.get().extra_paid_out) |> Money.round(currency_digits: 0) + end + + defp get_completed_bounties_count do + bounties_subtotal = + Repo.one( + from(t in Transaction, + where: t.type == :credit, + where: t.status == :succeeded, + where: not is_nil(t.linked_transaction_id), + where: not is_nil(t.bounty_id), + select: count(fragment("DISTINCT (?, ?)", t.bounty_id, t.user_id)) + ) + ) || 0 + + tips_subtotal = + Repo.one( + from(t in Transaction, + where: t.type == :credit, + where: t.status == :succeeded, + where: not is_nil(t.linked_transaction_id), + where: not is_nil(t.tip_id), + select: count(fragment("DISTINCT (?, ?)", t.tip_id, t.user_id)) + ) + ) || 0 + + bounties_subtotal + tips_subtotal + PlatformStats.get().extra_completed_bounties + end + + defp get_contributors_count do + subtotal = + Repo.one( + from(t in Transaction, + where: t.type == :credit, + where: t.status == :succeeded, + where: not is_nil(t.linked_transaction_id), + select: count(fragment("DISTINCT ?", t.user_id)) + ) + ) || 0 + + subtotal + PlatformStats.get().extra_contributors + end + + defp get_countries_count do + Repo.one( + from(u in User, + join: t in Transaction, + on: t.user_id == u.id, + where: t.type == :credit, + where: t.status == :succeeded, + where: not is_nil(t.linked_transaction_id), + where: not is_nil(u.country) and u.country != "", + select: count(fragment("DISTINCT ?", u.country)) + ) + ) || 0 + end + + defp format_money(money), do: money |> 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) + + defp yc_logo_cloud(assigns) do + ~H""" +
+
+ <.link + class="font-bold font-display text-base sm:text-4xl whitespace-nowrap flex items-center justify-center" + navigate={~p"/org/browser-use"} + > + Browser Use + + <.link class="relative flex items-center justify-center" navigate={~p"/org/outerbase"}> + + + + + + + + + + + + + + + + + + + + + + <.link class="relative flex items-center justify-center" navigate={~p"/org/triggerdotdev"}> + Trigger.dev + + <.link class="relative flex items-center justify-center" navigate={~p"/org/traceloop"}> + Traceloop + + <.link + class="font-bold font-display text-base sm:text-5xl whitespace-nowrap flex items-center justify-center" + navigate={~p"/org/trieve"} + > + Trieve logo Trieve + + <.link + class="font-bold font-display text-base sm:text-5xl whitespace-nowrap flex items-center justify-center" + navigate={~p"/org/twentyhq"} + > + + + + Twenty + + <.link class="relative flex items-center justify-center" navigate={~p"/org/aidenybai"}> + Million + + <.link class="relative flex items-center justify-center" navigate={~p"/org/moonrepo"}> + moon + + <.link class="relative flex items-center justify-center" navigate={~p"/org/dittofeed"}> + Dittofeed + + + <.link + class="relative flex items-center justify-center brightness-0 invert" + navigate={~p"/org/onyx-dot-app"} + > + Onyx Logo + + + <.link + class="font-bold font-display text-base sm:text-4xl whitespace-nowrap flex items-center justify-center brightness-0 invert" + aria-label="Logo" + navigate={~p"/org/mendableai"} + > + 🔥 + Firecrawl + + + <.link class="relative flex items-center justify-center" navigate={~p"/org/keephq"}> + Keep + + + <.link + class="font-bold font-display text-base sm:text-5xl whitespace-nowrap flex items-center justify-center" + navigate={~p"/org/windmill-labs"} + > + Windmill Windmill + + + <.link class="relative flex items-center justify-center" navigate={~p"/org/panoratech"}> + Panora + + + <.link class="relative flex items-center justify-center" navigate={~p"/org/highlight"}> + Highlight + +
+
+ """ + end + + defp pattern(assigns) do + ~H""" + + +
+ + + + + + +
+ + + """ + end + + defp glow(assigns) do + ~H""" + <%!-- "absolute top-[-320px] md:top-[-480px] xl:right-[120px] -z-[10]" --%> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ """ + end +end diff --git a/lib/algora_web/router.ex b/lib/algora_web/router.ex index 993659a18..839ef1209 100644 --- a/lib/algora_web/router.ex +++ b/lib/algora_web/router.ex @@ -155,6 +155,8 @@ defmodule AlgoraWeb.Router do on_mount: [{AlgoraWeb.Analytics, :current_country}] do live "/onboarding/org", Onboarding.OrgLive live "/onboarding/dev", Onboarding.DevLive + live "/crowdfund", CrowdfundLive, :index + live "/testimonials", TestimonialsLive, :index live "/pricing", PricingLive live "/challenges", ChallengesLive live "/challenges/prettier", Challenges.PrettierLive diff --git a/priv/static/images/misc/3wZGDuoPajk.png b/priv/static/images/misc/3wZGDuoPajk.png new file mode 100644 index 000000000..6c0fe1f00 Binary files /dev/null and b/priv/static/images/misc/3wZGDuoPajk.png differ diff --git a/priv/static/images/screenshots/bounty-to-hire-golem2.png b/priv/static/images/screenshots/bounty-to-hire-golem2.png index e01243883..03ee261d5 100644 Binary files a/priv/static/images/screenshots/bounty-to-hire-golem2.png and b/priv/static/images/screenshots/bounty-to-hire-golem2.png differ diff --git a/priv/static/images/screenshots/org-dashboard.png b/priv/static/images/screenshots/org-dashboard.png new file mode 100644 index 000000000..279b1cc02 Binary files /dev/null and b/priv/static/images/screenshots/org-dashboard.png differ