Set up Surface manually

In case you don't want to use mix surface.init, you can configure the project manually with the following steps.

Update your mix.exs, adding the :surface compiler to the list of compilers:

def project do
  [
    ...,
    compilers: Mix.compilers() ++ [:surface]
  ]
end

If you're using mix format, make sure you add surface to the import_deps and set up surface's built-in formatter in your .formatter.exs file:

[
  import_deps: [:phoenix, :surface],
  inputs: ["*.{ex,exs}", "{config,lib,test}/**/*.{ex,exs}", "{lib,test}/**/*.sface"],
  plugins: [Surface.Formatter.Plugin]
]

To allow live reloading for .sface files, add the related patterns to the endpoint configuration in your config/dev.exs:

config :my_app, MyAppWeb.Endpoint,
live_reload: [
  patterns: [
    ...,
    ~r"lib/my_app_web/live/.*(sface)$",
  ]
]

If you're using Gettext and you want to use the built-in <ErrorTag> component, you need to configure it in your config.exs so it can properly translate error messages using gettext. If you don't plan to use ErrorTag, you can skip this configuration.

config :surface, :components, [
  {Surface.Components.Form.ErrorTag, default_translator: {MyAppWeb.ErrorHelpers, :translate_error}}
]

To use Surface's built-in JS Interoperability, you need to:

Update .gitignore:

# Ignore auto-generated hook files
/assets/js/_hooks/

Update assets/js/app.js:

import Hooks from "./_hooks"
// ...
let liveSocket = new LiveSocket("/live", Socket, { hooks: Hooks, ... })

Update the Endpoint options in config/dev.exs for live reload of JS hooks:

config :my_app, MyAppWeb.Endpoint,
  ...
  reloadable_compilers: [:phoenix, :elixir, :surface],
  live_reload: [
    patterns: [
      ~r"lib/my_app_web/(live|components)/.*(ex|js)$",
      ...
    ]