phoenix-contexts

Phoenix Contexts Reference

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "phoenix-contexts" with this command: npx skills add oliver-kriska/claude-elixir-phoenix/oliver-kriska-claude-elixir-phoenix-phoenix-contexts

Phoenix Contexts Reference

Reference for designing and implementing Phoenix contexts (bounded contexts).

Iron Laws — Never Violate These

  • CONTEXTS OWN THEIR DATA — Never query another context's schema directly via Repo

  • SCOPES ARE MANDATORY (Phoenix 1.8+) — Every context function MUST accept scope as first parameter

  • THIN CONTROLLERS/LIVEVIEWS — Controllers translate HTTP, business logic stays in contexts

  • NO SIDE EFFECTS IN SCHEMAS — Use Ecto.Multi for transactions with side effects

Context Structure

lib/my_app/ ├── accounts/ # Context directory │ ├── user.ex # Schema │ ├── scope.ex # Scope struct (Phoenix 1.8+) ├── accounts.ex # Context module (public API)

Phoenix 1.8+ Scopes (CRITICAL)

All context functions MUST accept scope as first parameter:

def list_posts(%Scope{} = scope) do from(p in Post, where: p.user_id == ^scope.user.id) |> Repo.all() end

def create_post(%Scope{} = scope, attrs) do %Post{user_id: scope.user.id} |> Post.changeset(attrs) |> Repo.insert() |> broadcast(scope, :created) end

Quick Decisions

When to SPLIT contexts?

  • Module exceeds ~400 lines

  • Functions don't share domain language

  • Could theoretically be a separate microservice

  • Team member could own it independently

When to KEEP together?

  • Resources share vocabulary and domain concepts

  • Functions frequently operate on same data together

  • Splitting would create excessive cross-context calls

Cross-Context References

✅ Reference by ID, convert at boundary

def create_order(%Scope{} = scope, user_id, product_ids) do with {:ok, user} <- Accounts.fetch_user(scope, user_id) do do_create_order(scope, user.id, product_ids) end end

❌ Reaching into other context's internals

alias MyApp.Accounts.User # Don't do this Repo.all(from o in Order, join: u in User, ...) # Don't query other schemas

Anti-patterns

Wrong Right

Service objects (UserCreationService ) Context functions (Accounts.create_user/2 )

Repository pattern wrapping Repo Repo IS the repository

Direct Repo calls in controllers Delegate to context

Schema callbacks with side effects Use Ecto.Multi

Version Notes

  • Phoenix 1.8+: Uses built-in %Scope{} struct for authorization context

  • Phoenix 1.7: Requires manual authorization context (see references/scopes-auth.md "Pre-Scopes Patterns")

References

For detailed patterns, see:

  • references/context-patterns.md

  • Full context module, PubSub, Multi, cross-boundary

  • references/scopes-auth.md

  • Scope struct, multi-tenant, authorization, plugs

  • references/routing-patterns.md

  • Verified routes, pipelines, API auth

  • references/plug-patterns.md

  • Function/module plugs, placement, guards

  • references/json-api-patterns.md

  • JSON controllers, FallbackController, API auth

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

oban

No summary provided by upstream source.

Repository SourceNeeds Review
General

phx:full

No summary provided by upstream source.

Repository SourceNeeds Review
General

ecto-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

tidewave-integration

No summary provided by upstream source.

Repository SourceNeeds Review