**Essential Configuration:**
1. **Mix Project Configuration (mix.exs):**
```elixir
defmodule MyApp.MixProject do
use Mix.Project
def project do
[
app: :myapp,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end
def application do
[
mod: {MyApp.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
defp deps do
[
{:phoenix, "~> 1.7"},
{:phoenix_live_view, "~> 0.20"},
{:phoenix_ecto, "~> 4.4"},
{:ecto_sql, "~> 3.10"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 3.3"},
{:phoenix_live_reload, "~> 1.4", only: :dev},
{:jason, "~> 1.4"},
{:plug_cowboy, "~> 2.6"}
]
end
end
```
2. **Runtime Configuration (config/runtime.exs):**
```elixir
import Config
if config_env() == :prod do
database_url = System.get_env("DATABASE_URL") ||
raise "DATABASE_URL not available"
config :myapp, MyApp.Repo,
url: database_url,
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
socket_options: [:inet6]
secret_key_base = System.get_env("SECRET_KEY_BASE") ||
raise "SECRET_KEY_BASE not available"
host = System.get_env("PHX_HOST") || "example.com"
port = String.to_integer(System.get_env("PORT") || "4000")
config :myapp, MyAppWeb.Endpoint,
url: [host: host, port: 443, scheme: "https"],
http: [ip: {0, 0, 0, 0, 0, 0, 0, 0}, port: port],
secret_key_base: secret_key_base,
server: true
end
```
3. **Phoenix Endpoint Configuration (lib/myapp_web/endpoint.ex):**
```elixir
defmodule MyAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :myapp
# WebSocket configuration
socket "/live", Phoenix.LiveView.Socket,
websocket: [connect_info: [session: @session_options]]
# Session configuration
plug Plug.Session,
store: :cookie,
key: "_myapp_key",
signing_salt: "random_salt"
plug MyAppWeb.Router
end
```
4. **Database Configuration (Ecto):**
```elixir
# config/dev.exs
config :myapp, MyApp.Repo,
username: "postgres",
password: "postgres",
hostname: "localhost",
database: "myapp_dev",
stacktrace: true,
show_sensitive_data_on_connection_error: true,
pool_size: 10
```
5. **Router Configuration:**
```elixir
defmodule MyAppWeb.Router do
use MyAppWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, {MyAppWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", MyAppWeb do
pipe_through :browser
live "/", HomeLive
live "/posts", PostLive.Index
live "/posts/:id", PostLive.Show
end
scope "/api", MyAppWeb do
pipe_through :api
resources "/users", UserController
resources "/posts", PostController
end
end
```
6. **LiveView Example:**
```elixir
defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, assign(socket, :count, 0)}
end
def handle_event("inc", _params, socket) do
{:noreply, update(socket, :count, &(&1 + 1))}
end
def handle_event("dec", _params, socket) do
{:noreply, update(socket, :count, &(&1 - 1))}
end
def render(assigns) do
# Template with counter and buttons
end
end
```
7. **GenServer for State Management:**
```elixir
defmodule MyApp.Counter do
use GenServer
# Client API
def start_link(initial_value) do
GenServer.start_link(__MODULE__, initial_value, name: __MODULE__)
end
def increment do
GenServer.call(__MODULE__, :increment)
end
def get_value do
GenServer.call(__MODULE__, :get_value)
end
# Server callbacks
def init(initial_value) do
{:ok, initial_value}
end
def handle_call(:increment, _from, state) do
{:reply, state + 1, state + 1}
end
def handle_call(:get_value, _from, state) do
{:reply, state, state}
end
end
```
8. **Supervision Tree:**
```elixir
defmodule MyApp.Application do
use Application
def start(_type, _args) do
children = [
MyApp.Repo,
MyAppWeb.Endpoint,
{Phoenix.PubSub, name: MyApp.PubSub},
MyApp.Counter # Add your GenServer here
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
end
```
9. **Testing Configuration:**
```elixir
# test/myapp_web/live/counter_live_test.exs
defmodule MyAppWeb.CounterLiveTest do
use MyAppWeb.ConnCase
import Phoenix.LiveViewTest
test "increments counter", %{conn: conn} do
{:ok, view, _html} = live(conn, "/counter")
assert view |> element("h1") |> render() =~ "Counter: 0"
view |> element("button", "+") |> render_click()
assert view |> element("h1") |> render() =~ "Counter: 1"
end
end
```
10. **Performance & Production Best Practices:**
- Use releases for deployment (not mix phx.server in production)
- Enable connection pooling with proper pool_size
- Configure proper logging levels (info in production, debug in dev)
- Use Ecto's multi for database transactions
- Implement rate limiting with Plug.RateLimiter or Hammer
- Use Phoenix.Tracker for distributed presence
- Enable clustering with libcluster for horizontal scaling
- Monitor with Telemetry and tools like AppSignal or New Relic