Master Elixir development in Cursor with tailored rules for Phoenix, Ecto, LiveView, and more. Boost productivity with precise prompts, code styles, and best practices.
## Setting Up Cursor for Optimal Elixir Development
Cursor is a powerful AI-assisted code editor that shines when configured with custom rules tailored to specific languages and frameworks. For Elixir developers, especially those working with Phoenix, establishing dedicated rules ensures consistent code generation, adherence to idioms, and efficient project management. This guide walks you through implementing a complete set of rules for Elixir projects, drawing from community best practices to handle everything from Mix tasks to LiveView components.
By integrating these rules, Cursor will understand Elixir's functional paradigms, concurrency model via the BEAM VM, and Phoenix's real-time capabilities. You'll reduce errors, speed up scaffolding, and maintain high-quality code. Let's proceed step by step.
## Core System Prompt for Elixir Projects
Begin by defining a foundational system prompt in your Cursor settings. This prompt instructs the AI on Elixir's philosophy, key tools, and response expectations. Here's a refined version:
```
You are an expert Elixir developer with deep knowledge of the Phoenix framework, Ecto, LiveView, Oban, Ash, and Nerves. Always prioritize functional programming principles, immutability, pattern matching, and the BEAM's concurrency strengths.
Key guidelines:
- Use `~H` sigil for HEEx templates in LiveView.
- Prefer named function arguments for clarity.
- Generate concise, readable code with pipe operators (|>) where appropriate.
- For Phoenix apps, structure as `web/` for controllers/views, `lib/` for business logic.
- Always include Mixfile dependencies and `mix.exs` updates when suggesting new libraries.
- Respond with code in fenced blocks, explain changes, and suggest tests.
- Never use `IEx.pry` in production code; use Logger instead.
Official references:
- [Elixir](https://github.com/elixir-lang/elixir)
- [Phoenix](https://github.com/phoenixframework/phoenix)
When generating code, ensure it compiles with `mix compile` and follows `mix credo` standards.
```
This prompt sets the tone. Paste it into Cursor's global rules or project-specific `.cursorrules` file. It emphasizes Elixir's strengths like fault-tolerance and encourages best practices from the outset.
## Project-Level Rules Configuration
For individual projects, create a `.cursorrules` file in the root directory. This allows rules scoped to your app's structure. Expand on the system prompt with project-specific instructions:
### 1. Directory Structure and Conventions
Enforce standard Phoenix layout:
```
my_app/
├── lib/
│ ├── my_app/
│ │ ├── application.ex
│ │ └── ...
│ └── my_app_web/
│ ├── controllers/
│ ├── live/
│ └── ...
├── priv/
├── test/
├── config/
├── mix.exs
└── README.md
```
Rule snippet:
```
Always respect Phoenix conventions: web/ for HTTP/LiveView, lib/ for domain logic. Use `MyAppWeb` namespace for web components.
```
### 2. Mix Tasks and Dependencies
Cursor should assist with `mix` commands seamlessly. Include rules for common tasks:
- New app: `mix phx.new my_app --live --database postgres`
- Add deps: Suggest `mix deps.get` after `mix.exs` changes.
Example rule:
```
When adding features, propose `mix.exs` updates like:
defp deps do
[
{:phoenix_live_view, "~> 0.20.0"},
...
]
end
Then run `mix deps.get`.
```
## Phoenix-Specific Rules
Phoenix powers most Elixir web apps. Tailor rules for its components:
### Controllers and Views
- Use `action_fallback` for error handling.
- Render JSON with `Phoenix.View.render_to_json` or plugs.
Example generated controller:
```elixir
defmodule MyAppWeb.UserController do
use MyAppWeb, :controller
def index(conn, _params) do
users = Accounts.list_users()
render(conn, "index.json", users: users)
end
end
```
Rule: "In controllers, alias schemas and use context modules for business logic. Avoid direct DB calls."
### LiveView Mastery
LiveView enables isomorphic Phoenix apps. Rules should promote `.heex` files and `Phoenix.LiveView`.
Key directives:
- Use `~H"""` for inline templates.
- Handle events with `handle_event/3`.
- Prefer `sigil_H/1` for security.
Practical example for a counter LiveView:
```elixir
defmodule MyAppWeb.CounterLive do
use MyAppWeb, :live_view
@impl true
def mount(_params, _session, socket) do
{:ok, assign(socket, count: 0)}
end
@impl true
def handle_event("increment", _params, socket) do
{:noreply, update(socket, :count, &(&1 + 1))}
end
end
```
```heex
<div>
<h1>Count: <%= @count %></h1>
<button phx-click="increment">+</button>
</div>
```
Reference: [Phoenix LiveView](https://github.com/phoenixframework/phoenix_live_view)
## Database Interactions with Ecto
Ecto is Elixir's query language and GenServer-based DB wrapper. Rules must cover schemas, changesets, and migrations.
### Schemas and Changesets
Always validate with changesets:
```elixir
defmodule MyApp.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
field :email, :string
timestamps()
end
def changeset(user, attrs) do
user
|> cast(attrs, [:email])
|> validate_required([:email])
|> unique_constraint(:email)
end
end
```
Rule: "Generate Ecto repos with Repo.preload/3 for associations. Use context modules like Accounts.get_user!/1."
### Migrations
Propose `mix ecto.gen.migration` with precise `alter table` blocks.
Reference: [Ecto](https://github.com/elixir-ecto/ecto)
## Job Processing with Oban
For background jobs, Oban integrates seamlessly. Rules:
```
Use Oban for queues: mix oban.gen.job MyWorker. Define perform/1 with error handling.
```
Example:
```elixir
defmodule MyApp.MyWorker do
use Oban.Worker, queue: :default
@impl Oban.Worker
def perform(%Oban.Job{args: %{"id" => id}}) do
# Process
:ok
end
end
```
Reference: [Oban](https://github.com/sorcererslair/oban)
## Advanced Frameworks: Ash and Nerves
### Ash Framework
Ash provides declarative resources. Rule: "For CRUD, use Ash resources over raw Ecto."
Reference: [Ash](https://github.com/ash-project/ash)
### Nerves for Embedded Systems
For IoT, structure with Nerves firmware. Rule: "Include fwup, nerves_runtime."
Reference: [Nerves](https://github.com/nerves-project/nerves)
## Code Style and Quality Enforcement
Align with `credo` and `dialyzer`:
- 100-char line limit.
- Prefer `with` for error handling.
- Use `GenServer` for stateful processes.
Rule snippet:
```
Run `mix credo --strict` mentally. Avoid `Enum.map` if `for` is clearer.
```
## Testing Strategies
Mandate ExUnit tests:
- `mix test` compatible.
- Use `assert` with pipes.
Example context test:
```elixir
def test "list_users/0 returns all users", %{conn: conn} do
user = accounts_fixture()
json_resp = conn |> get(~p"/api/users") |> json_response(200)
assert length(json_resp["data"]) == 1
end
```
## Deployment and Ops Rules
Suggest Distillery or Elixir releases: `mix release`.
For Docker: Multi-stage builds with Alpine.
## Real-World Application: Building a Todo App
Step-by-step:
1. `mix phx.new todo --live`
2. Add Ecto schema for Todo.
3. Scaffold LiveView index/show.
4. Test with `mix test`.
This setup scales to production apps.
## Troubleshooting Common Issues
- Compile errors: Check `mix compile --warnings-as-errors`.
- LiveView disconnects: Use `phx-presence`.
By following these rules, your Elixir workflow in Cursor becomes streamlined and professional. Customize further based on project needs.
<div style="text-align: center; margin-top: 2rem;">
<a href="https://cursor.directory/elixir-development-cursor-rules" target="_blank" rel="noopener noreferrer" class="view-full-resource-btn" style="display: inline-block; background-color: #f97316; color: white; padding: 12px 24px; border-radius: 8px; text-decoration: none; font-weight: 600; transition: background-color 0.2s;">View Full Resource</a>
</div>