/pot

Just playing aryound

Primary LanguageElixir

Pot

Render React components from Elixir. Remix but with an Elixir backend. I'll write more, one day...

Running the demo

  • asdf install
  • pushd assets && pnpm install && popd
  • Ensure postgres is started
  • mix ecto.create
  • mix ecto.migrate
  • mix phx.server

Todo

  • Data (useLoaderData)
  • and route transitions
  • Start vite with phx automatically
  • Actions
  • useTransition
  • Styling
  • Add the concept of a controller (Pot?) that defines the React component, props, and stuff.
    • How to define custom headers
    • How to 404 (also done in loader in Remix)
  • Layout component trees
    • pot_layout Pot in router
    • not_found Pot in router
    • loader Pot in router
  • Robust error handling during navigations
  • Render ~H""" layouts and add server-rendered HTML support.
  • Make it deployable (properly in prod)
    • Fix Vite setup
    • Load entrypoint modules from manifest
  • Layout nesting
    • How to only load layout data when you need it? -> Compute a route key that the backend can diff against the new route key and include layouts for the necessary stuff
  • SSR for initial loads with a JS runtime
  • Fix CSRF token issue
  • Move package.json to root and colocate js with ex?
  • useMatches()

Long-term ideas

LiveView heex templates are statically analyzed: can we use that compile phase to extract a list of React component we need to preload? If this is possible, instead of returning an entrypoint we could allow for a special syntax to render React components inside heex:

  def simple_form(assigns) do
    ~H"""
    <.form :let={f} for={@for} as={@as} {@rest}>
      <div class="space-y-8 bg-white mt-10">
        <%= render_slot(@inner_block, f) %>
        <div :for={action <- @actions} class="mt-2 flex items-center justify-between gap-6">
          <%= render_slot(action, f) %>
          <JS.MyComponent myProp={@myprop}>
            More Elixir server-side rendered content!
          </JS.MyComponent>
        </div>
      </div>
    </.form>
    """
  end

This, in turn, could allow us to serialize only those parts of the data to the frontend that we actually need for the React components. The rest could be manual DOM placement that uses LiveView to manage state.

There's going to be a conflict between how to update state from React vs. how to update state from heex that we'll need to figure out. Who knows, maybe this will never work šŸ¤·.

Links