<:description>
building blocks that scale with the complexity of your application.
<:icon>
<:description>
Easily create rich, customizable, full featured backed by Absinthe.
<:icon>
<:description>
Create JSON:API spec compliant apis in not days.
<:icon>
<:description>
Effortless authentication with and out of the box.
<:icon>
<:description>
A thriving community of people to
<:icon>
<:description>
Add row and field level policies to to data.
<:icon>
<:description>
for splitting your application by tenant.
<:icon>
<:description>
Postgres, Ets, Mnesia, CSV and
<:icon>
<:description>
A you can drop right into your application.
<:icon>
<:description>
A suite of tools for you to extensions and DSLs.
<:icon>
<:description>
Custom tracers and rich telemetry events allow you to export
<:icon>
<:description>
Works great with and all the other in the Elixir ecosystem.
<:icon>
Backed by our
<.testimonial
text="The ease of defining our domain model and configuring Ash to generate a powerful GraphQL API has been a game-changer. What used to be complex and time-consuming has become simplicity itself."
author="Alan Heywood"
title="CTO, HereTask"
/>
<.testimonial
text="Through its declarative extensibility, Ash delivers more than you'd expect: Powerful APIs with filtering/sorting/pagination/calculations/aggregations, pub/sub, authorization, rich introspection, GraphQL... It's what empowers this solo developer to build an ambitious ERP!"
author="Frank Dugan III"
title="System Specialist, SunnyCor Inc."
class_overrides="md:-mt-20"
/>
<.testimonial
text="I’m constantly blown away with the quality of work and support the Ash community has put into this project. It’s gotten to the point that I can’t imagine starting a new Elixir project that doesn’t use Ash."
author="Brett Kolodny"
title="Full stack engineer, MEW"
class_overrides="md:-mt-4"
/>
<.testimonial
text="Ash is an incredibly powerful idea that gives Alembic a massive competitive advantage. It empowers us to build wildly ambitious applications for our clients with tiny teams, while consistently delivering the high level of quality that our customers have come to expect."
author="Josh Price"
title="Technical Director, Alembic"
class_overrides="md:-mt-20"
/>
<.testimonial
text="Ash Framework enabled us to build a robust platform for delivering financial services using bitcoin. Ash proved itself to our team by handling innovative use cases with ease and it continues to evolve ahead of our growing list of needs."
author="Yousef Janajri"
title="CTO & Co-Founder, Coinbits"
class_overrides="md:-mt-4"
/>
<.testimonial
text="The more I’ve used Ash, the more blown away I am by how much I get out of it – and how little boilerplate I have to write. I’m yet to encounter a situation where I would need to fight the “Ash way” of doing things, but the framework still allows me to choose how I build my software."
author="Juha Lehtonen"
title="Senior Software Developer"
class_overrides="md:-mt-20"
/>
It wouldn't be possible without our amazing community. and counting!
{#if @signed_up}
Thank you for joining our mailing list!
{#else}
Join our mailing list for (tastefully paced) updates!
{/if}
Custom Solutions
can help
Alembic specializes in providing custom solutions that ensure the success of your Ash Framework projects.
Leveraging extensive knowledge of both Ash Framework and the broader Elixir ecosystem, our team is
well-equipped to craft personalized projects, implement innovative features, or optimize your existing codebases.
Reach out to learn more about how our tailored solutions can make your project excel.
Simple declarative DSL
A taste of how to configure Ash
Below are some examples of the way you can model your resources with actions, attributes and relationships.
You can easily swap data layers between Postgres or ETS for example, or add your own data layer extension.
Once you've modelled your resources, you can derive GraphQL or JSON API external APIs from them.
"""
end
attr(:class_overrides, :string, default: "")
def testimonial(assigns) do
~F"""
"{@text}"
{@author}
{@title}
"""
end
def mount(socket) do
contributors = AshHq.Github.Contributor.in_order!()
{:ok,
assign(
socket,
signed_up: false,
contributor_count: Enum.count(contributors),
contributors: contributors,
email_form:
AshPhoenix.Form.for_create(AshHq.MailingList.Email, :create,
api: AshHq.MailingList,
upsert?: true,
upsert_identity: :unique_email
)
)}
end
def handle_event("toggle-theme", _, socket) do
if socket.assigns.theme == :default do
{:noreply, assign(socket, :theme, :dark)}
else
{:noreply, assign(socket, :theme, :default)}
end
end
def handle_event("validate_email_form", %{"form" => form}, socket) do
{:noreply,
assign(socket, email_form: AshPhoenix.Form.validate(socket.assigns.email_form, form))}
end
def handle_event("submit_email_form", _, socket) do
case AshPhoenix.Form.submit(socket.assigns.email_form) do
{:ok, _} ->
{:noreply, assign(socket, :signed_up, true)}
{:error, form} ->
{:noreply, assign(socket, email_form: form)}
end
end
@changeset_example """
post = Example.Post.create!(%{
text: "Declarative programming is fun!"
})
Example.Post.react!(post, %{type: :like})
Example.Post
|> Ash.Query.filter(likes > 10)
|> Ash.Query.sort(likes: :desc)
|> Example.read!()
"""
|> to_code()
defp changeset_example do
@changeset_example
end
@live_view_example """
def mount(_params, _session, socket) do
form = AshPhoenix.Form.for_create(Example.Post, :create)
{:ok, assign(socket, :form, form)}
end
def handle_event("validate", %{"form" => input}, socket) do
form = AshPhoenix.Form.validate(socket.assigns.form, input)
{:ok, assign(socket, :form, form)}
end
def handle_event("submit", _, socket) do
case AshPhoenix.Form.submit(socket.assigns.form) do
{:ok, post} ->
{:ok, redirect_to_post(socket, post)}
{:error, form_with_errors} ->
{:noreply, assign(socket, :form, form_with_errors)}
end
end
"""
|> to_code()
defp live_view_example do
@live_view_example
end
@graphql_example """
graphql do
type :post
queries do
get :get_post, :read
list :feed, :read
end
mutations do
create :create_post, :create
update :react_to_post, :react
end
end
"""
|> to_code()
defp graphql_example do
@graphql_example
end
@policies_example """
policies do
policy action_type(:read) do
authorize_if expr(visibility == :everyone)
authorize_if relates_to_actor_via([:author, :friends])
end
end
"""
|> to_code()
defp policies_example do
@policies_example
end
@notifier_example """
pub_sub do
module ExampleEndpoint
prefix "post"
publish_all :create, ["created"]
publish :react, ["reaction", :id] event: "reaction"
end
"""
|> to_code()
defp notifier_example do
@notifier_example
end
@aggregate_example """
aggregates do
count :likes, :reactions do
filter expr(type == :like)
end
count :dislikes, :reactions do
filter expr(type == :dislike)
end
end
calculations do
calculate :like_ratio, :float do
expr(likes / (likes + dislikes))
end
end
"""
|> to_code()
defp aggregate_example do
@aggregate_example
end
@post_example """
defmodule Example.Post do
use Ash.Resource,
data_layer: AshPostgres.DataLayer
resource do
description "A post is the primary sharable entity in our system"
end
postgres do
table "posts"
repo Example.Repo
end
attributes do
attribute :text, :string do
allow_nil? false
description "The body of the text"
end
attribute :visibility, :atom do
constraints [
one_of: [:friends, :everyone]
]
description "Which set of users this post should be visible to"
end
end
actions do
update :react do
argument :type, Example.Types.ReactionType do
allow_nil? false
end
change manage_relationship(
:type,
:reactions,
type: :append
)
end
end
relationships do
belongs_to :author, Example.User do
allow_nil? true
end
has_many :reactions, Example.Reaction
end
end
"""
|> to_code()
defp post_example do
@post_example
end
end