phx_literate/template/$PROJECT_NAME$/$PROJECT_NAME$_web.org

7.8 KiB
Raw Permalink Blame History

<%= @project_name_camel_case %>Web Phoenix Frontend

<% @project_name_camel_case %>Web= global helpers

This module is use'd in the submodules, views load from the view definition, etc. See the moduledoc for more information. For now this is just what the auto-gen gives me, eventually we'll have more Helper modules to integrate here. Try to keep them cross-referenced.

defmodule <%= @project_name_camel_case %>Web do
  @moduledoc """
  The entrypoint for defining your web interface, such
  as controllers, views, channels and so on.

  This can be used in your application as:

      use <%= @project_name_camel_case %>Web, :controller
      use <%= @project_name_camel_case %>Web, :view

  The definitions below will be executed for every view,
  controller, etc, so keep them short and clean, focused
  on imports, uses and aliases.

  Do NOT define functions inside the quoted expressions
  below. Instead, define any helper function in modules
  and import those modules here.
  """

  <<controller>>
  <<view>>
  <<router>>
  <<channel>>

  @doc """
  When used, dispatch to the appropriate controller/view/etc.
  """
  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end
def controller do
  quote do
    use Phoenix.Controller, namespace: <%= @project_name_camel_case %>Web

    import Plug.Conn
    import <%= @project_name_camel_case %>Web.Gettext
    alias <%= @project_name_camel_case %>Web.Router.Helpers, as: Routes
  end
end
def view do
  quote do
    use Phoenix.View,
      root: "lib/<%= @project_name %>_web/templates",
      namespace: <%= @project_name_camel_case %>Web

    # Import convenience functions from controllers
    import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]

    # Use all HTML functionality (forms, tags, etc)
    use Phoenix.HTML

    import <%= @project_name_camel_case %>Web.ErrorHelpers
    import <%= @project_name_camel_case %>Web.Gettext
    alias <%= @project_name_camel_case %>Web.Router.Helpers, as: Routes
  end
end
def router do
  quote do
    use Phoenix.Router
    import Plug.Conn
    import Phoenix.Controller
  end
end
def channel do
  quote do
    use Phoenix.Channel
    import <%= @project_name_camel_case %>Web.Gettext
  end
end

<% @project_name_camel_case %>Web.Endpoint= OTP application, Phoenix Entrypoint

The Endpoint is where web requests start to pass through the system, Plugs are how this works. Read this entire document, but at least this section to understand how this is put together and how the Plug system works.

defmodule <%= @project_name_camel_case %>Web.Endpoint do
  use Phoenix.Endpoint, otp_app: :<%= @project_name %>

  <<<%= @project_name_camel_case %>Web_UserSocket>>

  <<plug-configurations>>
  <<plug-session>>

  plug <%= @project_name_camel_case %>Web.Router
end

Serve at "/" the static files from "priv/static" directory. Since we will use phx.digest we can gzip the assets.

plug Plug.Static,
  at: "/",
  from: :<%= @project_name %>,
  gzip: true,
  only: ~w(css fonts images js favicon.ico robots.txt)

Code Reloading is enabled in local development by inserting some plugs if the code_reloading?/0 function from Phoenix.Endpoint returns true based on Mix configuration.

if code_reloading? do
  socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
  plug Phoenix.LiveReloader
  plug Phoenix.CodeReloader
end

plug Plug.RequestId
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]

plug Plug.Parsers,
  parsers: [:urlencoded, :multipart, :json],
  pass: ["*/*"],
  json_decoder: Phoenix.json_library()

plug Plug.MethodOverride
plug Plug.Head

Session configuration is still the default, I'm going to want to change and extract that singing_salt at some point.

The session will be stored in the cookie and signed, this means its contents can be read but not tampered with. Set :encryption_salt if you would also like to encrypt it.

plug Plug.Session,
  store: :cookie,
  key: "_<%= @project_name %>_key",
  signing_salt: "ruJdL/3g"

The §<%= @project_name %> client/server push socket will be useful some time, I'm sure of it:

socket "/socket", <%= @project_name_camel_case %>Web.UserSocket,
  websocket: true,
  longpoll: false

<% @project_name_camel_case %>Web.Router= maps HTTP requests to Controllers and Views.

The router is a set of pipelines and a set of scopes.

defmodule <%= @project_name_camel_case %>Web.Router do
  use <%= @project_name_camel_case %>Web, :router

  <<browser-pipeline>>

  <<base-scope>>
end

My browser scope is simple, still built around the defaults. CSRF, session, secure headers and HTML.

pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end

Phoenix gives a single controller, PageController, / routes to that through the browser pipeline above.

scope "/", <%= @project_name_camel_case %>Web do
  pipe_through :browser

  get "/", PageController, :index
end

Translations in <% @project_name_camel_case %>Web.Gettext=

I probably will care about translations some day, but I am going to leave this in its default state for now.

defmodule <%= @project_name_camel_case %>Web.Gettext do
  @moduledoc """
  A module providing Internationalization with a gettext-based API.

  By using [Gettext](https://hexdocs.pm/gettext),
  your module gains a set of macros for translations, for example:

      import <%= @project_name_camel_case %>Web.Gettext

      # Simple translation
      gettext("Here is the string to translate")

      # Plural translation
      ngettext("Here is the string to translate",
               "Here are the strings to translate",
               3)

      # Domain-based translation
      dgettext("errors", "Here is the error message to translate")

  See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
  """
  use Gettext, otp_app: :<%= @project_name %>
end

For now, the POT and PO files are kept illiterate. From the comment at the top of the POT file:

This is a PO Template file.

=msgid=s here are often extracted from source code. Add new translations manually only if they're dynamic translations that can't be statically extracted.

Run mix gettext.extract to bring this file up to date. Leave msgstr's empty as changing them here has no effect: edit them in PO (.po) files instead.

Since this is a semi-automated process, and frankly not a high priority for a little bit, I'm going to keep the translations managed outside. Eventually I would love to generate the PO files from a table rather than an ugly plain-text mono-space representation.