# elixir.menu — Tools for your Elixir app

THE ELIXIR APPLICATION GUIDE

# Tools for your
Elixir app.

A starting point for each kind of application.
Recommended tools, why we use them, and when to choose something else.

**Using a coding agent?** [Start here: agent instructions](https://elixir.menu/agents.md)

OUR WEB APP DEFAULT

## Phoenix + LiveView

Ecto and PostgreSQL for data. Contexts for business logic. Tailwind and HEEx for the interface.

[Explore the web stack](https://elixir.menu/#stack)[Read the setup recipe](https://elixir.menu/setup.md)

THE MENU

**A reference, not an installer.**

Use the parts that match the application. Follow existing project decisions first.

[Machine-readable index](https://elixir.menu/llms.txt)

01 / STARTING POINTS

## What are you building?

Phoenix is our first choice for web applications. A CLI, library or device starts elsewhere.

**Web application or API**Browser products, customer portals and HTTP APIs.PhoenixLiveView for interactive screens

### Starting point

Use Phoenix for routing, controllers and web application conventions. Add LiveView for server-driven interactive screens; an API-only product does not need a browser UI.

```
mix phx.new my_web_app
```

### Account for

Choose persistence from the product's needs. PostgreSQL + Ecto is our recommendation for shared relational web data, not a prerequisite for every Elixir program. Review generator options for API-only or database-free applications.

[Phoenix generator options](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.New.html)[Phoenix application guide](https://elixir.menu/#stack)[Phoenix setup recipe](https://elixir.menu/setup.md)

**Command-line tool**Developer tools, local automation and terminal applications.Mix + OptionParser

### Starting point

Keep command parsing separate from the modules that perform the work. OptionParser handles flags; the application owns help text, subcommands, output and exit codes.

```
mix new my_tool
```

### Account for

An escript needs Erlang/OTP on the target machine. Evaluate Burrito when distributing a bundled executable to users without that runtime, and test each supported OS and architecture.

[Mix projects](https://hexdocs.pm/mix/Mix.Tasks.New.html)[OptionParser](https://hexdocs.pm/elixir/OptionParser.html)[Escript packaging](https://hexdocs.pm/mix/Mix.Tasks.Escript.Build.html)[Burrito](https://hexdocs.pm/burrito/readme.html)

**Library**Reusable modules used by other Elixir applications.Mix

### Starting point

Define a small public module API, examples and tests. Generate documentation with ExDoc; publish to Hex if the package is intended for reuse outside the project. Add a supervision tree only if the library owns long-lived processes.

```
mix new my_library
```

### Account for

Choose supported Elixir/OTP versions and dependency constraints for consumers. A library does not need an HTTP server or database unless that is its purpose.

[Mix projects](https://hexdocs.pm/mix/Mix.Tasks.New.html)[ExDoc](https://hexdocs.pm/ex_doc/readme.html)[Publishing to Hex](https://hexdocs.pm/hex/Mix.Tasks.Hex.Publish.html)

**Background service**Workers, integrations and processes that keep running.Mix + OTP supervision

### Starting point

Use supervision for process lifecycles and recovery. Keep calculations and business operations in ordinary modules; introduce stateful processes where they are needed.

```
mix new my_service --sup
```

### Account for

Supervision does not persist work. Choose durable storage or a queue when recovery requires it. Add Plug + Bandit for a small HTTP interface if needed; use Mix releases for deployment.

[Supervision](https://hexdocs.pm/elixir/Supervisor.html)[Bandit](https://hexdocs.pm/bandit/Bandit.html)[Mix releases](https://hexdocs.pm/mix/Mix.Tasks.Release.html)

**Data analysis or machine learning**Notebooks, data transformations and numerical models.Livebook; Mix for the application

### Starting point

Use Livebook for interactive exploration, Explorer for tabular data, and Nx for numerical computation. Add Axon when defining or training neural networks is the requirement. Move reusable work into a Mix application when it needs a maintained API, tests or a service lifecycle.

### Account for

Hosted model calls, local inference and training are different requirements. Check native backends, memory and hardware before selecting a deployment environment.

[Livebook](https://hexdocs.pm/livebook/readme.html)[Nx](https://hexdocs.pm/nx/Nx.html)[Explorer](https://hexdocs.pm/explorer/Explorer.html)[Axon](https://github.com/elixir-nx/axon)

**Embedded device**Hardware products, sensors and deployed Linux devices.Nerves

### Starting point

Start from the Nerves installation and project guides for the target hardware. Build firmware with the system and libraries that the device requires.

### Account for

Hardware support, firmware updates and access to the device determine the setup. A web interface can be added when useful; it does not define the device application.

[Nerves getting started](https://hexdocs.pm/nerves/getting-started.html)

**Audio or video system**Streaming, transcoding and realtime media processing.Membrane + an OTP application

### Starting point

Build media pipelines with the source, processing and output elements needed for the product. Phoenix may provide a separate control interface if there is a web UI.

### Account for

Protocols, codecs and native dependencies determine the pipeline and deployment. Ordinary file uploads do not require a media framework.

[Membrane](https://membrane.stream/)

### Checks for every Mix project

Use mix format for formatting, compile with warnings as errors, and test behavior with ExUnit. Add Credo for useful static feedback. Use Boundary when domains or layers need enforced module dependency rules; declare allowed dependencies and exports, enable its Mix compiler, and fail CI on violations. Keep the same checks in local work and CI.

[Mix formatter](https://hexdocs.pm/mix/Mix.Tasks.Format.html)[ExUnit](https://hexdocs.pm/ex_unit/ExUnit.html)[Credo](https://hexdocs.pm/credo/overview.html)[Boundary setup and limits](https://elixir.menu/#boundary-checks)

02 / THE WEB STACK

## A Phoenix application, by task.

21 recommendations

Start with the generated foundation. Add accounts, jobs, email and other features when the product needs them.

[Read the stack as Markdown](https://elixir.menu/stack.md)[Phoenix setup recipe](https://elixir.menu/setup.md)

### Application

Web framework**Phoenix**

Routes, controllers, HTML and application conventions in one place.

#### Why we recommend it

Start with one Phoenix application and its generated structure. Keep the standard HTTP server and asset setup until a measured requirement calls for a change.

#### Limitations

Phoenix does not choose every application policy for you. This guide supplies the next layer of defaults; it does not replace Phoenix.

#### Next step

Use the official getting-started guide and a supported Elixir/OTP pair. Commit the resolved dependency lockfile.

[Phoenix getting started](https://hexdocs.pm/phoenix/up_and_running.html)

Interactive interfaces**Phoenix LiveView**

Build forms, dashboards and live updates alongside your Elixir code.

#### Why we recommend it

Use HEEx and function components for markup, with LiveView for interactive screens. Start ordinary content pages as server-rendered HTML when they need no live process.

#### Limitations

Offline-first products, rich canvas editors and heavy local interaction can justify a dedicated client application. Add small JavaScript hooks for isolated browser behavior.

#### Next step

Keep business rules in contexts; use LiveView for interaction and presentation.

[LiveView documentation](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.html)

Styling and components**Tailwind CSS + HEEx components**

Own a small set of reusable components and the visual language around them.

#### Why we recommend it

Use Tailwind for styling and HEEx function components to share markup and behavior. Keep theme tokens and application components in your project, where you can shape them around the product.

#### Limitations

Phoenix 1.8 includes daisyUI, but its generators do not require it. Keep daisyUI when its component classes and themes save useful work; it is optional, not the design system every product must adopt.

#### Next step

Define the product’s type, spacing and color rules, then build the components repeated across its screens.

[Phoenix 1.8 release](https://phoenixframework.org/blog/phoenix-1-8-released)[daisyUI customization](https://daisyui.com/docs/customize/)

Database and queries**PostgreSQL + Ecto**

One durable store, explicit queries, changesets and migrations.

#### Why we recommend it

Use Ecto for data access and changesets, backed by PostgreSQL. Database constraints enforce invariants; transactions keep related writes together.

#### Limitations

Ecto is not Active Record: queries and persistence remain explicit. SQLite is reasonable for a genuinely embedded or single-file application, outside this web-product default.

#### Next step

Use Ecto.Multi for multi-step transactions. Inspect slow queries and their plans before adding caches.

[Ecto documentation](https://hexdocs.pm/ecto/Ecto.html)[Ecto.Multi](https://hexdocs.pm/ecto/Ecto.Multi.html)

Business logic**Phoenix contexts**

Plain Elixir modules around the language of your product.

#### Why we recommend it

Give related business operations a clear public API. Both LiveViews and controllers should call that API instead of implementing separate versions of the same rules.

#### Limitations

A context is an organizational boundary, not a process. Do not turn ordinary CRUD or pure business logic into a GenServer.

#### Next step

Define public operations around the application’s domain. Call those operations from controllers, LiveViews and workers; keep database access behind the context boundary.

[Phoenix contexts](https://hexdocs.pm/phoenix/contexts.html)

### Accounts & permissions

Accounts and sign-in**phx.gen.auth**

Start with Phoenix’s generated authentication.

#### Why we recommend it

Use the authentication generator for a first-party web application. Phoenix 1.8 includes magic-link authentication and sudo-mode conventions; the generated code lives in your application.

#### Limitations

Authentication is not authorization. Enterprise SSO, external identity or complex organization requirements need their own deliberate integration.

#### Next step

Read the generated code and current security guidance. Configure real email delivery before relying on magic links.

[Authentication generator](https://hexdocs.pm/phoenix/mix_phx_gen_auth.html)

Authorization**Scopes + context checks**

Carry the actor into business operations and constrain data access.

#### Why we recommend it

Pass the authenticated scope through context functions. Apply ownership and permission rules to reads and writes; test denied access as deliberately as the successful path.

#### Limitations

Scopes carry identity and context; they are not an automatic policy engine. Hidden buttons and client parameters are never sufficient access control.

#### Next step

Pass the current scope into context operations. Test that another user cannot read or modify the protected resource, including through direct context calls.

[Phoenix scopes](https://hexdocs.pm/phoenix/scopes.html)

### Jobs & integrations

Durable background jobs**Oban**

Retries and persistent jobs using the database you already run.

#### Why we recommend it

Use Oban with PostgreSQL for work that must survive a process or application restart. Insert related jobs and domain changes within the same transaction.

#### Limitations

Jobs may be retried. Make side effects idempotent; uniqueness is not an exactly-once guarantee. Some advanced orchestration features belong to paid Oban Pro.

#### Next step

Use separate queues for distinct workloads and monitor retries. An ordinary Task is suitable for disposable concurrent work, not a durable queue.

[Oban documentation](https://hexdocs.pm/oban/Oban.html)

Recurring tasks**Oban Cron**

Put scheduled work in the same queue as other durable jobs.

#### Why we recommend it

Use Oban.Cron for periodic job insertion. Keep execution, retries and operational visibility in the job system.

#### Limitations

A schedule is not a catch-up policy for time when the app is down. Define missed-run behavior explicitly; dynamic scheduling has different requirements.

#### Next step

Set the intended timezone, check daylight-saving behavior where applicable, and keep workers idempotent.

[Oban.Cron](https://hexdocs.pm/oban/Oban.Cron.html)

Transactional email**Swoosh**

Compose mail in Elixir and send through a delivery adapter.

#### Why we recommend it

Use Swoosh, included in generated Phoenix applications, for account mail and product notifications. Use Oban when delivery needs durable retries.

#### Limitations

Swoosh is a library, not an email delivery service. The provider, verified domain and deliverability setup are separate operational choices.

#### Next step

Keep development mail local. Test message content and recipient selection before enabling production delivery.

[Swoosh documentation](https://hexdocs.pm/swoosh/Swoosh.html)

Outgoing HTTP**Req**

A readable client for calling external APIs.

#### Why we recommend it

Use Req for request construction, response handling and client features rather than assembling a new HTTP abstraction for each integration.

#### Limitations

Timeouts, retries and error handling are part of the integration design. A retried payment or other side effect needs an idempotency strategy.

#### Next step

Wrap each external service behind a small module. Use Req.Test for deterministic request tests.

[Req documentation](https://hexdocs.pm/req/Req.html)[Req.Test](https://hexdocs.pm/req/Req.Test.html)

Realtime notifications**Phoenix PubSub**

Broadcast changes to connected parts of your application.

#### Why we recommend it

Use Phoenix.PubSub to notify subscribed LiveViews or processes of a change. Persist important facts in PostgreSQL and load their current state when clients reconnect.

#### Limitations

PubSub is not a persistent message log. Multiple nodes require a suitable cluster or adapter configuration.

#### Next step

Use Presence only when you actually need to track who is connected.

[Phoenix.PubSub](https://hexdocs.pm/phoenix_pubsub/Phoenix.PubSub.html)

File uploads**LiveView uploads**

Progress, validation and direct-to-cloud upload support.

#### Why we recommend it

Start with LiveView’s upload flow. For durable production attachments, pair it with object storage and store ownership and file metadata in PostgreSQL.

#### Limitations

An upload widget does not supply permanent storage. Ephemeral application disks are not a durable attachment store; client metadata does not establish file safety.

#### Next step

Set size/type limits, authorize downloads, and implement the storage provider’s documented signing flow.

[LiveView uploads](https://hexdocs.pm/phoenix_live_view/uploads.html)

### Queries & APIs

Product text search**PostgreSQL full-text search**

Search your product’s data before operating another service.

#### Why we recommend it

For ordinary application search, start with PostgreSQL text-search features and an appropriate index. Keep the query and ranking logic close to your data model.

#### Limitations

Advanced relevance, typo tolerance or specialist search scale can justify a dedicated engine. Evaluate against actual queries and user expectations.

#### Next step

Build representative search cases and inspect query plans; avoid claiming that an unindexed text scan will scale.

[PostgreSQL text search](https://www.postgresql.org/docs/current/textsearch-intro.html)

Filtering and pagination**Flop**

Validated filter, sort and page parameters for Ecto queries.

#### Why we recommend it

Use Flop when product lists need reusable sorting, filtering and pagination. Keep the allowed fields explicit and restrict the base query to authorized records first.

#### Limitations

For one simple bounded list, an explicit Ecto query may be enough. Pagination does not replace tenant or ownership checks.

#### Next step

Use cursor pagination when the list and ordering warrant it; add Flop Phoenix only for the corresponding UI helpers.

[Flop documentation](https://hexdocs.pm/flop/readme.html)

Local read caching**ETS**

Use the runtime’s in-memory tables for disposable cached data.

#### Why we recommend it

First measure and improve database queries. When a local cache earns its keep, ETS provides concurrent in-memory storage without another service.

#### Limitations

ETS is node-local, loses data when its owner dies, and does not supply an automatic TTL or invalidation policy. It is never the source of truth.

#### Next step

Define table ownership, expiry and invalidation. Shared durable state requires a different design.

[ETS documentation](https://www.erlang.org/doc/apps/stdlib/ets.html)

JSON APIs**Phoenix controllers**

Expose your existing contexts through explicit HTTP endpoints.

#### Why we recommend it

Use Phoenix controllers and JSON rendering when a mobile client, partner or external integration needs an API. Share the business API with your web interface.

#### Limitations

Do not build an API simply to connect LiveView to its own server. Add GraphQL only when clients need that query model; Absinthe is the established Elixir option.

#### Next step

Define authentication, authorization, error shapes, pagination and versioning as part of the API contract.

[Phoenix JSON and APIs](https://hexdocs.pm/phoenix/json_and_apis.html)

### Testing & deployment

Application tests**ExUnit + LiveViewTest**

Test business behavior, persistence and server-driven interaction.

#### Why we recommend it

Use ExUnit and Phoenix’s generated test setup. Test contexts with the database sandbox and interactive screens with Phoenix.LiveViewTest.

#### Limitations

Server-side LiveView tests do not execute browser JavaScript or prove the final visual layout. Avoid asserting incidental markup when behavior is the contract.

#### Next step

Prioritize permission boundaries, data invariants, job behavior and core user journeys.

[ExUnit](https://hexdocs.pm/ex_unit/ExUnit.html)[LiveViewTest](https://hexdocs.pm/phoenix_live_view/Phoenix.LiveViewTest.html)

Browser integration tests**PhoenixTest.Playwright**

Exercise the small set of flows that need a real browser.

#### Why we recommend it

Use the Playwright-backed PhoenixTest driver for JavaScript hooks, browser navigation and integrations that server-side tests cannot cover.

#### Limitations

This adds browser tooling and setup cost. Keep most application tests in ExUnit; this is an editorial extension, not a Phoenix-generated default.

#### Next step

Cover representative critical flows and keep browser tests focused on observable behavior.

[PhoenixTest.Playwright](https://hexdocs.pm/phoenix_test_playwright/readme.html)

Instrumentation**Telemetry + Logger**

Expose timings, failures and structured operational events.

#### Why we recommend it

Use Telemetry events and Logger as the instrumentation foundation. Track request latency, database time, job failures and the product operations that matter.

#### Limitations

Instrumentation is not a hosted monitoring backend. Choose collection, storage and alerting separately; restrict any production LiveDashboard access.

#### Next step

Make logs useful without exposing secrets. Establish alerts and retention before calling the production system operationally complete.

[Telemetry](https://hexdocs.pm/telemetry/readme.html)[Logger](https://hexdocs.pm/logger/Logger.html)

Deployment artifact**Mix releases**

Package the application and runtime in a repeatable release.

#### Why we recommend it

Use Mix releases with runtime configuration. A container is a practical transport when the chosen host supports it; Phoenix documents the release and Dockerfile path.

#### Limitations

A release is not a hosting platform. Database backups, migrations, TLS, monitoring and rollback remain production responsibilities.

#### Next step

Choose a host that fits the team. Rehearse migrations and restoration, and keep secrets out of the build artifact.

[Phoenix releases](https://hexdocs.pm/phoenix/releases.html)

03 / OTP AND PERFORMANCE

## Choose the runtime tool.

Start with functions. Add processes for state ownership, concurrency or lifecycle. Choose shared storage by its read/write pattern; measure before changing the architecture.

[Read runtime choices as Markdown](https://elixir.menu/runtime.md)[JSON for agents](https://elixir.menu/runtime.json)

Built-in Elixir and Erlang tools need no extra package. Follow the installed Elixir/OTP documentation; node-local memory and supervision do not provide durable storage.

### Computation and process state

Ordinary computation**Functions + Enum**

#### Reach for it when

The work is business logic or a transformation that needs no independent lifecycle.

#### Know the tradeoff

Keep it in functions. Adding a process adds messaging and coordination costs; it does not make a function faster.

[Functions + Enum documentation](https://hexdocs.pm/elixir/Enum.html)

Lazy processing**Stream + File.stream!**

#### Reach for it when

A file or collection should be processed incrementally, without building every intermediate result in memory.

#### Know the tradeoff

Streams are lazy: enumerate them to run the work. They are not parallel; collecting all results can still exhaust memory.

[Stream + File.stream! documentation](https://hexdocs.pm/elixir/Stream.html)

One concurrent operation**Task**

#### Reach for it when

Short-lived work can run alongside its caller, such as fetching independent inputs.

#### Know the tradeoff

Task.async links failures to the caller. Await the result and define timeout/cleanup behavior. Tasks do not survive node restarts as durable jobs.

[Task documentation](https://hexdocs.pm/elixir/Task.html)

Supervised concurrent work**Task.Supervisor**

#### Reach for it when

Tasks need an application-owned supervisor or must fail independently of the requesting process.

#### Know the tradeoff

async still links to the caller; choose async_nolink when isolation is required and handle results/exits. max_children rejects excess starts; it is not a waiting queue or a rate limiter.

[Task.Supervisor documentation](https://hexdocs.pm/elixir/Task.Supervisor.html)

Bounded parallel batches**Task.async_stream**

#### Reach for it when

Independent items can be processed concurrently with a bounded number of tasks.

#### Know the tradeoff

Enumerate the stream; set concurrency and timeout policy. ordered: false avoids buffering for input order when order is unnecessary. Task.Supervisor.async_stream_nolink adds supervised, unlinked task execution.

[Task.async_stream documentation](https://hexdocs.pm/elixir/Task.html#async_stream/3)

Simple shared process state**Agent**

#### Reach for it when

One process needs to hold a small value accessed through get/update functions.

#### Know the tradeoff

This is Elixir Agent, not an AI agent. Operations run serially inside its process. Choose GenServer for messages, timers or a richer lifecycle; ETS for concurrent table access.

[Agent documentation](https://hexdocs.pm/elixir/Agent.html)

State and coordination**GenServer**

#### Reach for it when

A long-lived process owns state or coordinates a resource, for example a connection or session.

#### Know the tradeoff

Callbacks execute serially. Keep slow work out of callbacks when responsiveness matters; call timeouts do not cancel server work. In-memory state needs a separate persistence strategy.

[GenServer documentation](https://hexdocs.pm/elixir/GenServer.html)

Explicit runtime transitions**:gen_statem**

#### Reach for it when

A protocol or connection has distinct states, state-specific events and transition/timeout rules.

#### Know the tradeoff

Use functions or a data model for ordinary business statuses. The behaviour models a running process; supervision does not make its state durable.

[:gen_statem documentation](https://www.erlang.org/doc/apps/stdlib/gen_statem.html)

### Lifecycle, naming and coordination

Application lifecycle**Application + Supervisor**

#### Reach for it when

Long-running children must start in order and recover according to their dependencies.

#### Know the tradeoff

Choose restart and shutdown policies deliberately. Restarts do not restore lost state, and terminate callbacks are not a durability guarantee. Slow child initialization delays later children.

[Application + Supervisor documentation](https://hexdocs.pm/elixir/Supervisor.html)

Workers created at runtime**DynamicSupervisor**

#### Reach for it when

The application starts and stops workers as demand changes, such as one worker per active room.

#### Know the tradeoff

Use Registry for discovery. A restarted supervisor does not remember the former dynamic child set; reconcile it from an authoritative source when required.

[DynamicSupervisor documentation](https://hexdocs.pm/elixir/DynamicSupervisor.html)

Find local processes**Registry**

#### Reach for it when

Processes need names based on runtime keys, such as tenant/session IDs, or local duplicate-key dispatch.

#### Know the tradeoff

Use :via tuples rather than creating atoms from user input. Registry is node-local; it is neither cluster discovery nor durable storage.

[Registry documentation](https://hexdocs.pm/elixir/Registry.html)

Reduce supervisor contention**PartitionSupervisor**

#### Reach for it when

Measurements show one process, such as a DynamicSupervisor or Task.Supervisor, bottlenecking concurrent starts.

#### Know the tradeoff

Route work across partitioned children. This reduces contention in that layer; it does not parallelize a single worker or distribute work across nodes.

[PartitionSupervisor documentation](https://hexdocs.pm/elixir/PartitionSupervisor.html)

Observe failure and schedule messages**Process monitors + timers**

#### Reach for it when

A process must observe another process exiting or receive a delayed message.

#### Know the tradeoff

Monitors report DOWN without coupling failures; links couple lifecycles. Process.send_after schedules a message, not a durable job. Account for stale timer messages and mailbox growth.

[Process monitors + timers documentation](https://hexdocs.pm/elixir/Process.html)

Inspect a running process**:sys + Process.info**

#### Reach for it when

A running server has unexpected state, memory growth or a growing mailbox.

#### Know the tradeoff

Use :sys for OTP process state and bounded debugging; Process.info reports process memory and queue length. Inspecting full state can expose sensitive values and allocate large results. These tools diagnose behavior; they do not repair it.

[OTP sys](https://www.erlang.org/doc/apps/stdlib/sys.html)[Process.info](https://hexdocs.pm/elixir/Process.html#info/2)

### Shared data and hot paths

Mutable shared tables**:ets**

#### Reach for it when

Many processes need concurrent lookups or updates to node-local in-memory data.

#### Know the tradeoff

Choose table type, ownership and access rights. Tune read/write concurrency against measurements. The table normally dies with its owner; TTL, invalidation and durability are separate.

[:ets documentation](https://www.erlang.org/doc/apps/stdlib/ets.html)

Read-mostly shared values**:persistent_term**

#### Reach for it when

Many processes repeatedly read a value that changes rarely, such as a static lookup or a stable resource reference. A stable :counters reference can be stored once while the counter array itself is updated.

#### Know the tradeoff

Reads avoid locks and copying the value onto the caller heap. Writes copy the key table; replacing/deleting complex terms triggers a node-wide GC scan. Avoid request-time updates and expiring caches. Persistent means VM lifetime, not disk durability.

[:persistent_term documentation](https://www.erlang.org/doc/apps/erts/persistent_term.html)

Frequent shared increments**:counters**

#### Reach for it when

Many processes update numeric metrics without routing each increment through one server.

#### Know the tradeoff

write_concurrency favors add/sub throughput with weaker read consistency. Choose atomics mode when those semantics do not fit. Fixed-width integers wrap; this is node-local memory, not an accounting ledger.

[:counters documentation](https://www.erlang.org/doc/apps/erts/counters.html)

Atomic numeric coordination**:atomics**

#### Reach for it when

An integer operation needs an atomic result or compare-and-exchange, such as claiming a numeric slot.

#### Know the tradeoff

Individual operations are atomic and mutually ordered. A sequence of operations is not a transaction. Integers wrap on overflow, and these values are not cluster-wide.

[:atomics documentation](https://www.erlang.org/doc/apps/erts/atomics.html)

FIFO data structure**:queue**

#### Reach for it when

A process holds a FIFO buffer and repeated list appends would be costly.

#### Know the tradeoff

A queue is a data structure, not a worker, backpressure mechanism or persistent job system. Bound its size and define overload behavior.

[:queue documentation](https://www.erlang.org/doc/apps/stdlib/queue.html)

Build output from fragments**iodata**

#### Reach for it when

Output combines many byte fragments and its destination accepts iodata.

#### Know the tradeoff

Keep binaries and byte lists nested until a binary is required. Avoid repeated copying; benchmark the actual construction because BEAM binary appends can also be optimized.

[iodata documentation](https://hexdocs.pm/elixir/IO.html#module-io-data)

Control retained binary memory**:binary**

#### Reach for it when

Small slices of large payloads live in process state or another long-lived store.

#### Know the tradeoff

Inspect referenced_byte_size. Copy selected retained slices when they pin a much larger binary; copying every binary adds allocation and work.

[:binary documentation](https://www.erlang.org/doc/apps/stdlib/binary.html)

### When a task is not enough

[**GenStage**](https://elixir.menu/#genstage) — Producers and consumers need a custom event pipeline with demand-driven backpressure.

[**Flow**](https://elixir.menu/#flow) — A large enumerable needs parallel mapping, partitioned grouping, aggregation or windows.

[**Broadway**](https://elixir.menu/#ingestion) — The application consumes a stream from Kafka, RabbitMQ, SQS or another supported source.

### Choose durability separately

Use Task for disposable work and Oban for application jobs that need persistence and retries. GenStage and Broadway regulate ingestion; source acknowledgements and retry-safe handlers determine delivery behavior.

[Oban](https://hexdocs.pm/oban/Oban.html)

### Measure the limiting resource

Track latency, throughput, memory, mailbox growth, database queries and pool waits on representative traffic. Extra tasks can overload a database or an upstream API. Use Benchee for code comparisons and profilers to find where work accumulates.

[Benchee](https://hexdocs.pm/benchee/readme.html)[OTP profiling](https://www.erlang.org/doc/apps/tools/tprof.html)

### Stream database exports deliberately

Use Ecto.Repo.stream for incremental row processing when the adapter supports it. SQL adapters require enumeration inside a transaction. Long streams occupy a database connection; batching and collecting results can change memory use.

[Ecto.Repo.stream](https://hexdocs.pm/ecto/Ecto.Repo.html#c:stream/2)

04 / OPTIONAL TOOLS

## Libraries for the features you need.

Choose these when the product needs them. Each entry explains the use case, how it fits, and the additional setup.

[Read optional tools as Markdown](https://elixir.menu/optional.md)[JSON for agents](https://elixir.menu/optional.json)

### Accounts and product controls

Social login and OIDC**Assent**

#### Use it when

Users need to sign in with Google, GitHub, Apple or an OpenID Connect provider.

#### How it fits

Integrate provider authentication with the application's existing accounts and sessions.

#### What else to account for

Account linking, session management and permissions remain application concerns. SAML is a separate requirement.

[Assent](https://github.com/pow-auth/assent)

Rate limiting**Hammer**

#### Use it when

Login attempts, API calls, uploads or expensive actions need limits.

#### How it fits

Define limits by actor, operation and time window; choose a backend that matches the deployment.

#### What else to account for

A node-local counter does not automatically enforce a cluster-wide quota. Choose the algorithm's burst behavior deliberately.

[Hammer](https://hexdocs.pm/hammer/readme.html)

Feature flags**FunWithFlags**

#### Use it when

Features need gradual rollout, per-customer access or an operational off switch.

#### How it fits

Choose an Ecto or Redis persistence adapter and configure synchronization between nodes.

#### What else to account for

Keep permission checks separate from rollout flags. Remove expired flags and restrict the management interface.

[FunWithFlags](https://hexdocs.pm/fun_with_flags/readme.html)

### Files and documents

Object storage**ExAws.S3**

#### Use it when

Uploads need to live in an S3 or compatible object store.

#### How it fits

Use ExAws with its S3 service module for object operations and signed URLs. In a LiveView app, connect it to the upload flow.

#### What else to account for

The storage service, credentials, access rules and lifecycle policy are separate. Check which operations a compatible service actually supports.

[ExAws.S3](https://hexdocs.pm/ex_aws_s3/ExAws.S3.html)

Image processing**Image**

#### Use it when

The product needs thumbnails, resized uploads, image conversion or watermarks.

#### How it fits

Process images through the libvips-backed Image API; use Oban for work that needs retries.

#### What else to account for

Vix/libvips introduces native runtime requirements. Check the deployment target and required codecs, and limit input dimensions and processing work.

[Image](https://hexdocs.pm/image/readme.html)

Markdown parsing and rendering**MDEx**

#### Use it when

The application needs CommonMark parsing, rendered Markdown content or transformations over a Markdown document tree.

#### How it fits

Use MDEx to parse and transform a document or render HTML. Choose extensions and syntax highlighting deliberately; reserve HEEx components and expressions for trusted application-owned content.

#### What else to account for

Treat user-authored Markdown as untrusted input: configure and verify HTML sanitization, link handling and size limits. Never evaluate its HEEx expressions. MDEx uses native Rust code; verify precompiled artifact support or a Rust build toolchain for the deployment target.

[MDEx](https://github.com/leandrocp/mdex)

PDF generation**ChromicPDF**

#### Use it when

Invoices, reports or other HTML documents need downloadable PDFs.

#### How it fits

Render application-owned HTML and CSS through a managed Chrome process.

#### What else to account for

Chrome is an additional runtime dependency; PDF/A conversion also uses Ghostscript. Isolate rendering and control access to external resources.

[ChromicPDF](https://hexdocs.pm/chromic_pdf/ChromicPDF.html)

CSV import and export**NimbleCSV**

#### Use it when

Users need bulk uploads, data exports or integrations through CSV files.

#### How it fits

Parse and write streams; validate each imported row through the application's business rules.

#### What else to account for

CSV parsing does not validate field types or business rules. Define malformed-row handling and spreadsheet formula escaping for exports.

[NimbleCSV](https://hexdocs.pm/nimble_csv/NimbleCSV.html)

### APIs and collaboration

Documented HTTP APIs**OpenApiSpex**

#### Use it when

External consumers need an OpenAPI contract for the Phoenix API.

#### How it fits

Describe operations and schemas, validate requests, and test responses against the specification.

#### What else to account for

A schema does not enforce ownership or authorization. Keep the published contract aligned with application behavior.

[OpenApiSpex](https://hexdocs.pm/open_api_spex/readme.html)

GraphQL APIs**Absinthe**

#### Use it when

Clients specifically need GraphQL queries, mutations or subscriptions.

#### How it fits

Expose the existing business layer through a schema; use Dataloader where batching is needed.

#### What else to account for

Resolvers still need authorization and query-cost limits. Ordinary JSON endpoints remain simpler when GraphQL adds no client benefit.

[Absinthe](https://hexdocs.pm/absinthe/overview.html)

Who is online**Phoenix Presence**

#### Use it when

Chat, collaborative screens or live rooms need connected-user state.

#### How it fits

Track presence metadata and broadcast joins and leaves through Phoenix's existing realtime infrastructure.

#### What else to account for

Presence is ephemeral and eventually consistent. It is not a durable audit trail, access-control system or editing-conflict resolver.

[Phoenix Presence](https://hexdocs.pm/phoenix/Phoenix.Presence.html)

### Languages, locales and money

Translated interface text**Gettext**

#### Use it when

The application needs interface copy in multiple languages.

#### How it fits

Use the Gettext integration already present in typical Phoenix projects; maintain translation catalogs and plural forms.

#### What else to account for

It does not translate user-authored content automatically. Dates, amounts and units need locale-aware formatting too.

[Gettext](https://hexdocs.pm/gettext/Gettext.html)

Localized dates and numbers**Localize**

#### Use it when

Dates, numbers, currencies and units must follow the user's locale.

#### How it fits

Use CLDR-based formatting and parsing. For new projects, evaluate Localize as the documented successor to the ex_cldr family.

#### What else to account for

Existing ex_cldr applications need a planned migration. Check runtime requirements and package locale data for deployment.

[Localize](https://hexdocs.pm/localize/readme.html)[ex_cldr migration notice](https://hexdocs.pm/ex_cldr/readme.html)

Currency amounts**Money (ex_money)**

#### Use it when

Prices, invoices or balances need explicit currencies and decimal arithmetic.

#### How it fits

Represent amount and currency together and make rounding rules explicit.

#### What else to account for

This is not payment processing, tax calculation or an accounting ledger. The package is ex_money; check its major-version migration notes.

[Money](https://hexdocs.pm/ex_money/readme.html)

### AI features

Calling language models**ReqLLM**

#### Use it when

The product needs text generation, streaming, structured outputs, embeddings or model tool calls through supported provider APIs.

#### How it fits

Use a common Elixir interface to supported providers, including schema-constrained output and embedding generation. Keep provider-specific settings explicit; store embeddings separately when retrieval needs persistence.

#### What else to account for

Provider and model capabilities differ. Start here for direct model calls; add an agent framework only when orchestration needs it. Define application validation, permissions and representative evaluations separately.

[ReqLLM](https://github.com/agentjido/req_llm)

Tool-using AI agents**Jido.AI 2.x**

#### Use it when

A language model must select tools, keep agent state or run a bounded multistep reasoning loop.

#### How it fits

Add Jido.AI to a Jido agent and use ReqLLM for provider access. Define tools as actions, and keep model selection, timeouts and tool policy explicit.

#### What else to account for

Model output is untrusted and nondeterministic. Restrict tool permissions and side effects, set cost and step limits, require approval for high-risk operations, and test representative tasks.

[Jido.AI documentation](https://hexdocs.pm/jido_ai/readme.html)[Jido ecosystem](https://jido.run/ecosystem)

Validated structured extraction**InstructorLite**

#### Use it when

The main requirement is extracting typed fields from text into Ecto schemas, with casting, validation and retries.

#### How it fits

Define an instruction with an Ecto schema and use changeset validation to check the returned fields. Choose this alternative when its Ecto integration fits better than ReqLLM structured output.

#### What else to account for

It is not an agent runtime and does not provide response streaming. Valid fields can still contain incorrect facts; handle failed validation, retry limits and domain checks explicitly.

[InstructorLite](https://github.com/martosaur/instructor_lite)

Conversational chains and tool loops**LangChain for Elixir**

#### Use it when

The application is organized around message history, model responses and chained tool calls, or already uses the Elixir LangChain abstractions.

#### How it fits

Compose messages, model adapters and tools through LLMChain. Use its callbacks for streaming and inspect tool-call trajectories when evaluating a conversation workflow.

#### What else to account for

This is an alternative orchestration approach, not an extra layer every ReqLLM or Jido application needs. Bound tool loops, authorize actions and implement persistence and retry behavior for the actual product.

[LangChain for Elixir](https://github.com/brainlid/langchain)

AI features for Ash applications**Ash AI**

#### Use it when

An application already uses Ash resources and needs to expose selected actions as model tools or MCP tools, generate structured outputs or maintain embeddings.

#### How it fits

Add Ash AI to the existing Ash domains and resources. Select the actions to expose and carry the authenticated actor and tenant into their execution; configure model access only for features that require it.

#### What else to account for

Choose Ash as an architecture first. Ash AI does not justify migrating an ordinary contexts application by itself. Test authorization for every exposed action and verify embedding updates, retrieval quality and model costs.

[Ash AI](https://github.com/ash-project/ash_ai)

Vector similarity search**pgvector**

#### Use it when

Embeddings are useful for semantic retrieval or recommendations alongside existing PostgreSQL data.

#### How it fits

Enable the PostgreSQL vector extension and use the Elixir pgvector integration with Ecto or Postgrex.

#### What else to account for

The library does not generate embeddings. Verify database-extension support, dimensions, indexes and retrieval quality against representative queries.

[pgvector for Elixir](https://hexdocs.pm/pgvector/readme.html)

Running pretrained models**Bumblebee + Nx**

#### Use it when

Inference should run on infrastructure you control, using a supported pretrained model.

#### How it fits

Load supported model architectures with Bumblebee and serve predictions through Nx.Serving.

#### What else to account for

Plan model memory, a suitable numerical backend and hardware. Model compatibility and licensing need to be checked individually.

[Bumblebee](https://hexdocs.pm/bumblebee/Bumblebee.html)

### Data processing and machine learning

Message ingestion pipelines**Broadway**

#### Use it when

The application consumes a stream from Kafka, RabbitMQ, SQS or another supported source.

#### How it fits

Build concurrent processing stages with batching, acknowledgements and back-pressure.

#### What else to account for

The source connector determines delivery behavior. Keep handlers safe to retry; ordinary application jobs still fit Oban.

[Broadway](https://hexdocs.pm/broadway/Broadway.html)

Tabular data analysis**Explorer**

#### Use it when

Imports, analytics or reports need dataframe transformations over CSV, Parquet or similar datasets.

#### How it fits

Use typed series and dataframes for grouping, joining and transforming tabular data.

#### What else to account for

The default Polars backend uses native code. Check deployment support and memory use; routine application queries still belong in Ecto.

[Explorer](https://hexdocs.pm/explorer/Explorer.html)

Building and training neural networks**Axon + Nx**

#### Use it when

The project needs to define or train a neural network in Elixir rather than only run a supported pretrained model.

#### How it fits

Use Axon to build models and training loops on Nx, with a numerical compiler/backend suited to the target hardware. Use Bumblebee when loading a supported pretrained model meets the requirement.

#### What else to account for

Check native backend support, hardware, memory and training data. Validate on held-out data and measure deployment behavior; adding Axon does not establish model quality or a performance advantage.

[Axon](https://github.com/elixir-nx/axon)

### Performance and scaling

Custom demand-driven pipelines**GenStage**

#### Use it when

Producers and consumers need a custom event pipeline with demand-driven backpressure.

#### How it fits

Model stages around runtime concurrency and data transfer; keep business steps in functions.

#### What else to account for

You own buffering, subscriptions and failure behavior. Use Task.async_stream for simpler bounded parallel work, or Broadway for its ingestion features.

[GenStage](https://hexdocs.pm/gen_stage/GenStage.html)

Parallel dataset transformations**Flow**

#### Use it when

A large enumerable needs parallel mapping, partitioned grouping, aggregation or windows.

#### How it fits

Build a Flow pipeline and choose partition keys, stages and windows for the workload.

#### What else to account for

Coordination has overhead; small inputs can favor Enum or Task. Partitioning affects grouping and order; bound accumulating state.

[Flow](https://hexdocs.pm/flow/Flow.html)

Compare code performance**Benchee**

#### Use it when

A measured hot path has alternative implementations to compare.

#### How it fits

Benchmark representative inputs with warmup, runtime, memory and reduction measurements.

#### What else to account for

Microbenchmarks do not establish application throughput or production latency. Check correctness and end-to-end behavior separately.

[Benchee](https://hexdocs.pm/benchee/readme.html)

Locate runtime bottlenecks**Mix + OTP profilers**

#### Use it when

The application is slow and you need to locate expensive calls or repeated work.

#### How it fits

Use the supported mix profile task or OTP profiler for the question; combine findings with the existing Telemetry events.

#### What else to account for

Check installed runtime support for tprof, eprof and fprof. Tracing can change timing and add overhead; profile a representative bounded workload.

[Mix + OTP profilers](https://hexdocs.pm/mix/Mix.Tasks.Profile.Tprof.html)

Managed in-memory caching**Cachex**

#### Use it when

A node-local cache needs expiration, eviction or fallback loading beyond a small ETS implementation.

#### How it fits

Configure cache limits, expiration and loading behavior around the data lifecycle.

#### What else to account for

Define invalidation and stale-data policy. A local cache is not a durable source of truth or a cluster-wide consistency guarantee.

[Cachex](https://hexdocs.pm/cachex/Cachex.html)

Native computation and Rust integration**Rustler**

#### Use it when

Profiling identifies CPU-heavy work suited to native code, or the product must call an existing Rust library.

#### How it fits

Expose a narrow NIF interface and select normal versus dirty scheduling appropriate to the work.

#### What else to account for

Native faults can crash the VM. Validate target builds, scheduler impact and boundary-copying costs; consider a separate OS process when fault isolation is required.

[Rustler](https://hexdocs.pm/rustler/readme.html)

Compiled tensor computation**EXLA + Nx**

#### Use it when

Nx numerical work needs a compiled backend on supported CPU or accelerator hardware.

#### How it fits

Use EXLA as the Nx compiler/backend and select the supported target, precision and memory settings.

#### What else to account for

Compilation, data transfer and native dependencies have costs. Verify hardware/toolchain support and measure representative workloads; it is not a general accelerator for arbitrary Elixir functions.

[EXLA + Nx](https://hexdocs.pm/exla/EXLA.html)

Elastic remote execution**FLAME**

#### Use it when

Bursty expensive work should run on additional ephemeral nodes, such as media processing or model inference.

#### How it fits

Configure a bounded runner pool and an appropriate backend. Start only required application children and size runner database pools deliberately.

#### What else to account for

Boot latency, network transfer and capacity costs matter. FLAME supplies compute execution, not a durable job queue; pair it with Oban when jobs must persist.

[FLAME](https://hexdocs.pm/flame/FLAME.html)

### Development tools

Module dependency rules**Boundary**

#### Use it when

Domains or layers need explicit, compiler-checked dependencies and public module exports. Useful for agent-maintained applications as well as human-maintained code.

#### How it fits

Declare each boundary in its root module with use Boundary, explicit deps and a small exports list. Add the compile-time dependency and compiler below. A boundary always exports its root module; prefer explicit exports over exports: :all. Keep allowed calls aligned with the architecture.

#### What else to account for

Violations are compiler warnings unless compilation uses --warnings-as-errors. External OTP application calls are allowed by default; opt into selected app checks or strict mode when required. Dynamic calls such as apply/3 are not checked. Boundary enforces static module references; it does not isolate an agent’s files, processes or network access. Libraries can limit the compiler to dev/test as the compiler documentation describes.

[Boundary reference](https://boundary.hexdocs.pm/Boundary.html)[Boundary installation](https://boundary.hexdocs.pm/readme.html)[Compiler and CI enforcement](https://boundary.hexdocs.pm/Mix.Tasks.Compile.Boundary.html)

#### Set it up

```
# In mix.exs deps/0:
{:boundary, "~> 0.11", runtime: false}

# In mix.exs project/0:
compilers: [:boundary] ++ Mix.compilers()

# In each domain root module (adapt the names):
use Boundary, deps: [MyApp.Accounts], exports: []
```

Run mix deps.get, then mix compile --warnings-as-errors in the environments your CI checks. Add a temporary forbidden static call to confirm the check fails, remove it, and rerun successfully. The dependency alone does not enforce boundaries.

AI-assisted Phoenix development**Tidewave**

#### Use it when

A coding agent needs runtime context from a Phoenix application during development.

#### How it fits

Add the Tidewave Phoenix integration as a development-only dependency and plug. Connect your coding agent to inspect logs, evaluate code, query the development database and read installed-version documentation.

#### What else to account for

This gives the agent access to the running development application. Use a trusted local environment and keep the dependency and endpoint out of production; this is tooling for building the app, not an AI feature for its users.

[Tidewave Phoenix](https://github.com/tidewave-ai/tidewave_phoenix)

### A different application architecture

Declarative business applications**Ash**

#### Use it when

Resources, actions, policies and derived APIs form a substantial part of the application.

#### How it fits

Evaluate Ash early as the domain layer beneath Phoenix, with only the extensions the product needs.

#### What else to account for

This changes how business logic is modeled. It is an architectural choice, not a small utility to install beside an unchanged contexts design.

[What is Ash?](https://hexdocs.pm/ash/what-is-ash.html)

Stateful agent workflows**Jido 2.x**

#### Use it when

The application needs cooperating agents that choose or coordinate steps, share reusable actions and react to routed signals.

#### How it fits

Model the system with agents, actions, signals and directives, and run long-lived agents through Jido's supervised runtime. AI is optional; add Jido.AI only when decisions need a language model.

#### What else to account for

Prefer a plain GenServer, durable Oban jobs or an explicit function pipeline when behavior is fixed and simple. Supervision and in-memory state alone do not preserve progress across restarts; choose and verify persistence and resume behavior.

[Jido documentation](https://hexdocs.pm/jido/readme.html)[Jido ecosystem](https://jido.run/ecosystem)

**Specialist projects**

These need their own architecture and deployment plan:

- [Nerves](https://hexdocs.pm/nerves/getting-started.html) — Embedded devices and firmware.

- [Membrane](https://membrane.stream/) — Audio, video and streaming pipelines.

05 / THE THINKING

## Defaults with reasons.

### The application decides the architecture.

A command-line tool can start with Mix and OptionParser. A long-running service needs a supervision tree. A browser product benefits from Phoenix. These are different starting points within the same ecosystem.

[Mix project types](https://hexdocs.pm/mix/Mix.Tasks.New.html)

### Keep Phoenix’s conventions where they fit.

For web apps, use Phoenix, LiveView, contexts and Ecto as the foundation. Keep the generated HTTP server, asset pipeline and test setup.

[Phoenix generator documentation](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.New.html)

### Decide on Ash early.

Contexts and Ecto are our default. Choose Ash when a resource-and-action model, policies and generated APIs fit the domain. It affects how the application is structured, so evaluate it before building out the data layer.

[How Ash models an application](https://hexdocs.pm/ash/what-is-ash.html)

### A dependency still needs integration.

Oban needs database migrations and workers. Swoosh needs a delivery adapter. File uploads need storage and access rules. Every recommendation includes the remaining setup and the limits of the choice.

06 / FOR AGENTS

## Start with the requirements.

Read the existing project, choose an application path, and use the relevant reference. Do not install the whole menu.

[Start here: agent instructions](https://elixir.menu/agents.md)[Download application guide](https://elixir.menu/app-guide.md)[All Markdown and JSON exports](https://elixir.menu/llms.txt)

### Dependency guidance for agents

Use usage_rules in any Mix project to collect dependency-authored instructions and find documentation. Follow the project’s existing conventions for where agents read guidance, keep Phoenix’s generated guidance when using its default setup, and refresh dependency rules when versions change.

[usage_rules documentation](https://hexdocs.pm/usage_rules/readme.html)

01

### Read the existing project

First read https://elixir.menu/agents.md for direct Markdown and JSON retrieval. In the application, start with README.md, mix.exs, mix.lock and runtime pins. Preserve its architecture and follow its maintained workflow. Do not regenerate an existing project.

02

### State the application requirements

Identify the interface, whether work must keep running, persistence needs, and deployment target. Choose one of the starting points above; a product may combine more than one. Do not assume Phoenix or PostgreSQL.

03

### Check the environment

Check elixir --version and mix --version. Follow the official Elixir installation guide if prerequisites are missing; respect existing version management. Install a web generator, database or specialist toolchain only for the selected path.

04

### Generate in an empty destination

Use the selected starter and its current documentation. The commands above are scaffolding examples, not complete applications. For the Phoenix web path, follow setup.md; for Nerves and Membrane, follow their own project guides.

05

### Select libraries by requirement

Read runtime.md for built-in state, concurrency and storage choices. Read optional.md and add only tools whose use cases match the product. Check versions, native dependencies and deployment constraints. Record the reasons and setup in the project’s maintained documentation. Preserve its existing agent-guidance conventions.

06

### Verify the actual application

Run formatting, compilation and relevant tests. Exercise the real interface: CLI help, output and exit codes; service startup and recovery; HTTP behavior; or the target device. Verify the packaged artifact on the intended target and report what remains untested.

Phoenix + LiveView setup recipe

For a new web application with PostgreSQL. Check the current generator and supported runtime versions before running these steps.

[Download Phoenix recipe](https://elixir.menu/setup.md)

Verified 6 October 2026 on macOS: Phoenix 1.8.15, LiveView 1.2.12, Elixir 1.20.4 / OTP 29.1.1 and PostgreSQL 18.3. Setup, auth migrations, formatting, compilation, 112 generated tests and four HTTP routes passed. Browser flows and production deployment remain untested.

01

### Check the machine and the destination

Read the project README and runtime configuration if they exist. Confirm the operating system, intended app name and destination. Check the tools below; a missing command identifies a prerequisite to install. Do not generate into a directory containing unrelated work.

```
elixir --version
mix --version
mix phx.new --version
psql --version
```

**Check:** Record the detected versions and missing tools. A PostgreSQL client version does not prove that a database server is running or accessible.

02

### Install missing prerequisites

Use the official Elixir instructions for the detected operating system and a compatible Erlang/OTP version. Reuse the machine’s existing runtime manager. Install and start PostgreSQL using its operating-system-specific instructions. Linux development also needs inotify-tools for live reload. After Elixir is working, install missing Mix tooling and the Phoenix generator with the commands below. Respect any existing version pins; these unversioned commands are for a fresh setup.

```
mix local.hex
mix local.rebar
mix archive.install hex phx_new
```

**Check:** Record the selected versions in the project’s runtime configuration. Verify the application can connect to PostgreSQL using the intended local credentials before creating databases.

03

### Generate the application

Replace my_app with the agreed application name. Keep Phoenix’s LiveView, mailer, asset and agent-guidance defaults. Respect the project’s established documentation conventions.

```
mix phx.new my_app --database postgres
cd my_app
```

**Check:** Configure the new application’s local database connection before running mix setup. Keep private credentials out of source control. Accept dependency installation when the generator prompts, or let mix setup fetch them.

04

### Set up the database and assets

Run this from the generated application directory, after configuring PostgreSQL. The generated setup task fetches dependencies, prepares the database and builds the development assets. Read its definition in mix.exs before using it in an existing application.

```
mix setup
```

**Check:** Setup must finish successfully. If a step fails, fix the reported prerequisite and resume from that step; do not regenerate over the application.

05

### Add accounts if the product needs them

For first-party user accounts, generate Phoenix authentication with the LiveView option. Skip this step for an application without accounts. Follow any additional instructions printed by the generator.

```
mix phx.gen.auth Accounts User users --live
mix deps.get
mix ecto.migrate
```

**Check:** Review the generated account flows and authorization boundaries. Configure email delivery before relying on production magic links.

06

### Verify and hand off

Format the generated code and any local configuration changes, then run the checks. Start the development server using the project’s normal process. Open the printed URL and verify the page loads. If accounts were generated, exercise registration and sign-in with development email.

```
mix format
mix format --check-formatted
mix compile --warnings-as-errors
mix test
mix phx.server
```

**Check:** Report exact versions, the app location, startup URL, checks that passed and anything unverified. Keep README.md and mix.lock current. Do not describe the setup as production-ready or benchmarked.

---

Canonical page: https://elixir.menu/
