Using Elixir, Phoenix, LiveView and Ash for everything creates a very well defined and verifiable structure for every part of the codebase with a precommit that looks like this:
precommit: [
"compile --warnings-as-errors", # Fail compilation if any warnings exist
"deps.unlock --check-unused", # Fail if unused dependencies are unlocked
"deps.audit", # Scan dependencies for known security vulnerabilities
"cmd mix hex.audit", # Audit Hex packages for retired or vulnerable versions
"migrations.safety", # Check database migrations for unsafe operations
"format --check-formatted", # Verify code matches the formatter style
"credo --strict", # Run strict static code analysis checks
"sobelow --exit --threshold high --skip", # Fail on high-confidence security issues only
"ash.codegen --check", # Ensure Ash generated code is up to date
"usage_rules.sync --check", # Verify usage rules are synchronized
"cmd bun run lint", # If there's JS beyond LiveView
"test" # Run the full test suite
]
The result has been excellent consistency across my code base and the AI learns fast how it should be working. Everything comes out very readable if I want to dig into something.For the most part, everything I ask for gets 1 shotted with this approach with typically rare minor tweaks and refinements.