diff --git a/.codex b/.codex new file mode 100644 index 0000000..e69de29 diff --git a/assets/images/an/be_event_processing.png b/assets/images/an/be_event_processing.png new file mode 100644 index 0000000..bf4b340 Binary files /dev/null and b/assets/images/an/be_event_processing.png differ diff --git a/assets/images/an/monitoring.png b/assets/images/an/monitoring.png new file mode 100644 index 0000000..e53ec72 Binary files /dev/null and b/assets/images/an/monitoring.png differ diff --git a/assets/images/an/offer_traffic_flow_cpa.png b/assets/images/an/offer_traffic_flow_cpa.png new file mode 100644 index 0000000..cfd0566 Binary files /dev/null and b/assets/images/an/offer_traffic_flow_cpa.png differ diff --git a/assets/images/an/offer_traffic_flow_cpc.png b/assets/images/an/offer_traffic_flow_cpc.png new file mode 100644 index 0000000..6096ba0 Binary files /dev/null and b/assets/images/an/offer_traffic_flow_cpc.png differ diff --git a/assets/images/an/overall_arch.png b/assets/images/an/overall_arch.png new file mode 100644 index 0000000..c0a465f Binary files /dev/null and b/assets/images/an/overall_arch.png differ diff --git a/assets/images/an/overview.png b/assets/images/an/overview.png new file mode 100644 index 0000000..a9cdbee Binary files /dev/null and b/assets/images/an/overview.png differ diff --git a/assets/images/an/path_flow.png b/assets/images/an/path_flow.png new file mode 100644 index 0000000..8e1d225 Binary files /dev/null and b/assets/images/an/path_flow.png differ diff --git a/assets/images/an/stack.png b/assets/images/an/stack.png new file mode 100644 index 0000000..dbc211e Binary files /dev/null and b/assets/images/an/stack.png differ diff --git a/assets/images/an/ui_arch.png b/assets/images/an/ui_arch.png new file mode 100644 index 0000000..1f06a3e Binary files /dev/null and b/assets/images/an/ui_arch.png differ diff --git a/assets/images/an/ui_old_netadmin.png b/assets/images/an/ui_old_netadmin.png new file mode 100644 index 0000000..d241735 Binary files /dev/null and b/assets/images/an/ui_old_netadmin.png differ diff --git a/assets/images/an/ui_tech.png b/assets/images/an/ui_tech.png new file mode 100644 index 0000000..337d8ea Binary files /dev/null and b/assets/images/an/ui_tech.png differ diff --git a/assets/images/market_mate/dashboard.png b/assets/images/market_mate/dashboard.png new file mode 100644 index 0000000..cac6d7c Binary files /dev/null and b/assets/images/market_mate/dashboard.png differ diff --git a/assets/images/market_mate/import_fidelity.png b/assets/images/market_mate/import_fidelity.png new file mode 100644 index 0000000..c9a190a Binary files /dev/null and b/assets/images/market_mate/import_fidelity.png differ diff --git a/assets/images/market_mate/landing_page.png b/assets/images/market_mate/landing_page.png new file mode 100644 index 0000000..0877764 Binary files /dev/null and b/assets/images/market_mate/landing_page.png differ diff --git a/assets/images/market_mate/live_dash.gif b/assets/images/market_mate/live_dash.gif new file mode 100644 index 0000000..2d205bf Binary files /dev/null and b/assets/images/market_mate/live_dash.gif differ diff --git a/assets/images/market_mate/live_dash.mp4 b/assets/images/market_mate/live_dash.mp4 new file mode 100644 index 0000000..a24a09e Binary files /dev/null and b/assets/images/market_mate/live_dash.mp4 differ diff --git a/assets/images/market_mate/set_alert.png b/assets/images/market_mate/set_alert.png new file mode 100644 index 0000000..666f4e5 Binary files /dev/null and b/assets/images/market_mate/set_alert.png differ diff --git a/assets/images/market_mate/set_targets.png b/assets/images/market_mate/set_targets.png new file mode 100644 index 0000000..3cdcca1 Binary files /dev/null and b/assets/images/market_mate/set_targets.png differ diff --git a/assets/images/market_mate/sys_arch.png b/assets/images/market_mate/sys_arch.png new file mode 100644 index 0000000..f23f47d Binary files /dev/null and b/assets/images/market_mate/sys_arch.png differ diff --git a/assets/resume/kyle-neal-resume.pdf b/assets/resume/kyle-neal-resume.pdf index 42eeeab..b14357a 100644 Binary files a/assets/resume/kyle-neal-resume.pdf and b/assets/resume/kyle-neal-resume.pdf differ diff --git a/lib/revstack_web/live/whoami_live.ex b/lib/revstack_web/live/whoami_live.ex index e558361..b55d1f9 100644 --- a/lib/revstack_web/live/whoami_live.ex +++ b/lib/revstack_web/live/whoami_live.ex @@ -46,6 +46,96 @@ defmodule RevstackWeb.WhoamiLive do } ] + @marketmate_gallery_items [ + %{ + src: "/images/market_mate/live_dash.mp4", + title: "Live Portfolio Updates", + category: "Real-Time UI", + description: + "A live portfolio dashboard that reacts to market movement in real time, giving the user instant visibility into portfolio changes without leaving the page.", + highlights: [ + "Real-time stock updates flow directly into the portfolio experience.", + "Phoenix LiveView refreshes the UI instantly with server-rendered state updates.", + "An Erlang event pipeline powers the live update loop behind the dashboard." + ], + why_it_matters: + "This slide proves the product is not just a static dashboard. The value is immediate market awareness delivered in real time, which is the baseline for a tool that users can actually rely on throughout the trading day." + }, + %{ + src: "/images/market_mate/sys_arch.png", + title: "System Architecture", + category: "BEAM-Native Design", + description: + "MarketMate is intentionally split between MMEX, the Elixir + LiveView web layer, and MMERL, the Erlang/OTP engine responsible for long-running event-driven processing.", + highlights: [ + "MMEX owns the browser experience, LiveView state, and product presentation.", + "MMERL was chosen for concurrency, supervision trees, and fault-tolerant background processing.", + "Ash accelerates domain modeling with a clean resource structure and fast iteration.", + "The system keeps a clear separation of concerns between UI delivery and backend event processing." + ], + why_it_matters: + "The architecture slide shows deliberate system boundaries instead of an all-in-one app. That separation makes the product easier to evolve, easier to reason about, and better suited for long-running event workloads on the BEAM." + }, + %{ + src: "/images/market_mate/set_alert.png", + title: "Set Price Alerts", + category: "Alerting Pipeline", + description: + "Users configure price alerts in the web application, but alert evaluation and notification generation happen inside the Erlang engine where event processing belongs.", + highlights: [ + "Alerts are configured by the user in MMEX.", + "Alert conditions are evaluated inside MMERL.", + "Notifications are generated in Erlang and sent through a bridge back to MMEX.", + "Phoenix PubSub broadcasts the result so the UI reflects alert activity in real time." + ], + why_it_matters: + "Alerts are where system design turns into user utility. This flow demonstrates that MarketMate can take user intent, evaluate it continuously in the backend, and push actionable outcomes back to the interface without manual refreshes." + }, + %{ + src: "/images/market_mate/set_targets.png", + title: "Set Price Targets", + category: "Decision Support", + description: + "Price targets follow the same BEAM-native event pipeline as alerts, forming the foundation for a richer investment decision-support system.", + highlights: [ + "Target updates move through the bridge between MMERL and MMEX.", + "Phoenix PubSub keeps the LiveView interface in sync with target changes.", + "Future work includes a news ingestion layer and an AI agent for context-aware analysis.", + "The longer-term vision includes BUY / SELL / HOLD recommendations, intrinsic value modeling, and deeper financial metrics." + ], + why_it_matters: + "Targets expand the product from monitoring into decision support. This is the bridge from raw market tracking to a more opinionated financial assistant that can eventually combine targets, news, and valuation context." + }, + %{ + src: "/images/market_mate/import_fidelity.png", + title: "Portfolio Import", + category: "Data Ingestion", + description: + "The current MVP supports manual Fidelity portfolio import, giving users a pragmatic path to getting real holdings into the system quickly.", + highlights: [ + "Manual Fidelity import keeps the first version simple and operational.", + "The workflow is intentionally MVP-friendly so the product can validate core value before deeper integrations.", + "If API access becomes available, the next step is an automated sync pipeline." + ], + why_it_matters: + "Import is critical because product value depends on real user holdings, not demo data. This MVP workflow favors speed-to-utility first, while still leaving a clear path toward automated brokerage integration later." + }, + %{ + src: "/images/market_mate/landing_page.png", + title: "Product Vision", + category: "Flagship Vision", + description: + "MarketMate is being built as an intelligent personal financial advisor that combines portfolio awareness, alerts, news, and financial metrics into one decision-support experience.", + highlights: [ + "The product centers on portfolio awareness instead of generic market dashboards.", + "Alerts, news, and metrics are designed to converge into one operator-style workflow.", + "The long-term goal is stronger decision support for real users making real financial calls." + ], + why_it_matters: + "The vision slide anchors the entire walkthrough. It clarifies that MarketMate is being built as a cohesive financial operator experience, not a collection of isolated features, and that every subsystem is serving that larger product direction." + } + ] + @section_navigation_items [ %{id: "whoami-hero", label: "Hero"}, %{id: "whoami-experience", label: "Career Highlights"}, @@ -70,6 +160,9 @@ defmodule RevstackWeb.WhoamiLive do admin_gallery_open?: false, admin_gallery_index: 0, admin_gallery_images: @admin_gallery_images, + marketmate_gallery_open?: false, + marketmate_gallery_index: 0, + marketmate_gallery_items: @marketmate_gallery_items, section_nav_open?: false, section_navigation_items: @section_navigation_items, career_modal_open?: false, @@ -106,6 +199,34 @@ defmodule RevstackWeb.WhoamiLive do {:noreply, assign(socket, :admin_gallery_index, String.to_integer(index))} end + def handle_event("open_marketmate_gallery", _params, socket) do + {:noreply, assign(socket, marketmate_gallery_open?: true, marketmate_gallery_index: 0)} + end + + def handle_event("close_marketmate_gallery", _params, socket) do + {:noreply, assign(socket, marketmate_gallery_open?: false)} + end + + def handle_event("marketmate_gallery_prev", _params, socket) do + index = max(socket.assigns.marketmate_gallery_index - 1, 0) + {:noreply, assign(socket, :marketmate_gallery_index, index)} + end + + def handle_event("marketmate_gallery_next", _params, socket) do + max_index = gallery_max_index(socket.assigns.marketmate_gallery_items) + index = min(socket.assigns.marketmate_gallery_index + 1, max_index) + {:noreply, assign(socket, :marketmate_gallery_index, index)} + end + + def handle_event("marketmate_gallery_select", %{"index" => index}, socket) do + index = + index + |> String.to_integer() + |> clamp_gallery_index(socket.assigns.marketmate_gallery_items) + + {:noreply, assign(socket, :marketmate_gallery_index, index)} + end + def handle_event("toggle_section_nav", _params, socket) do {:noreply, assign(socket, :section_nav_open?, !socket.assigns.section_nav_open?)} end @@ -175,7 +296,7 @@ defmodule RevstackWeb.WhoamiLive do expanded_phase_id={@career_expanded_phase_id} /> <.technical_expertise_section /> - <.live_projects_section admin_gallery_images={@admin_gallery_images} /> + <.live_projects_section /> <.leadership_and_teamwork_section /> <.education_section /> <.personal_interests_section /> @@ -193,6 +314,11 @@ defmodule RevstackWeb.WhoamiLive do images={@admin_gallery_images} current_index={@admin_gallery_index} /> + <.marketmate_gallery_modal + :if={@marketmate_gallery_open?} + items={@marketmate_gallery_items} + current_index={@marketmate_gallery_index} + /> """ end @@ -215,7 +341,7 @@ defmodule RevstackWeb.WhoamiLive do id="whoami-skill-signature" class="mt-6 text-lg text-base-content/70 max-w-2xl mx-auto leading-relaxed" > - 12+ years building and owning revenue-critical, high-throughput production systems on the BEAM. Erlang/OTP, Elixir, Phoenix LiveView, and distributed data architecture at scale. + 10+ years building and owning revenue-critical, high-throughput production systems on the BEAM. Erlang/OTP, Elixir, Phoenix LiveView, and distributed data architecture at scale.
<%!-- Grouped proof points for faster recruiter scanning --%> @@ -226,7 +352,7 @@ defmodule RevstackWeb.WhoamiLive doBeyond production systems, I continue to build and deploy independent projects exploring new ideas and technologies.
++ <.icon + name="hero-cursor-arrow-rays" + class="size-5 inline-block align-text-bottom" + /> Click a project to explore +
+ Production-ready launches, deployed experiments, and supporting projects that round out the broader portfolio. +
++ Active projects currently under development. These highlight ongoing system design, architecture decisions, and evolving features. +
+