Plato (plato v0.0.24)

Copy Markdown View Source

Plato CMS - A schema-driven content management system for Phoenix.

Configuration

In your config.exs:

config :my_app, :plato,
  repo: MyApp.Repo

Or configure a default:

config :plato,
  default_otp_app: :my_app

Usage

Query content by schema name:

# Get unique content (for singleton schemas like "homepage")
{:ok, homepage} = Plato.get_content("homepage", otp_app: :my_app)

# Get all content for a schema
{:ok, blog_posts} = Plato.list_content("blog_post", otp_app: :my_app)

# Get specific content by ID
{:ok, post} = Plato.get_content_by_id(1, otp_app: :my_app)

Field Access

Content returns a map with field names as keys:

homepage.title
#=> "Welcome to My Site"

homepage.hero_image
#=> %{url: "...", alt_text: "..."} (resolved referenced content)

Summary

Functions

Create content for a schema.

Get unique content by schema name.

Get unique content by schema name, raises on error.

Get content by database ID.

List all content instances for a schema.

Syncs code-defined schemas to the database.

Types

content_map()

@type content_map() :: %{required(atom()) => String.t() | map() | nil}

opts()

@type opts() :: [otp_app: atom(), repo: module()]

Functions

create_content(schema_name, attrs, opts \\ [])

@spec create_content(String.t(), map(), opts()) ::
  {:ok, content_map()} | {:error, Ecto.Changeset.t() | atom()}

Create content for a schema.

Examples

Plato.create_content("blog_post", %{
  title: "My Post",
  body: "Content here",
  author_id: 1  # ID of another content instance
}, otp_app: :my_app)
# => {:ok, %{title: "My Post", body: "Content here", author: %{...}}}

get_content(schema_name, opts \\ [])

@spec get_content(String.t(), opts()) :: {:ok, content_map()} | {:error, atom()}

Get unique content by schema name.

Returns {:ok, content_map} if found, {:error, reason} otherwise. Works only for schemas marked as unique: true.

Examples

Plato.get_content("homepage", otp_app: :my_app)
# => {:ok, %{title: "Welcome", tagline: "...", hero: %{...}}}

Plato.get_content("nonexistent", otp_app: :my_app)
# => {:error, :schema_not_found}

get_content!(schema_name, opts \\ [])

@spec get_content!(String.t(), opts()) :: content_map()

Get unique content by schema name, raises on error.

Examples

Plato.get_content!("homepage", otp_app: :my_app)
# => %{title: "Welcome", tagline: "..."}

get_content_by_field(schema_name, field_name, field_value, opts \\ [])

@spec get_content_by_field(String.t(), String.t(), String.t(), opts()) ::
  {:ok, content_map()} | {:error, atom()}

Get content by matching a field value.

Finds content within a schema where a specific field matches a given value. Useful for slug-based lookups, email searches, etc.

Examples

Plato.get_content_by_field("blog-post", "slug", "my-first-post", otp_app: :my_app)
# => {:ok, %{title: "My First Post", slug: "my-first-post", body: "..."}}

Plato.get_content_by_field("author", "email", "jane@example.com", otp_app: :my_app)
# => {:ok, %{name: "Jane Doe", email: "jane@example.com", ...}}

get_content_by_id(id, opts \\ [])

@spec get_content_by_id(integer(), opts()) :: {:ok, content_map()} | {:error, atom()}

Get content by database ID.

Examples

Plato.get_content_by_id(1, otp_app: :my_app)
# => {:ok, %{title: "My Post", body: "..."}}

list_content(schema_name, opts \\ [])

@spec list_content(String.t(), opts()) :: {:ok, [content_map()]} | {:error, atom()}

List all content instances for a schema.

Examples

Plato.list_content("blog_post", otp_app: :my_app)
# => {:ok, [
#      %{title: "Post 1", body: "...", author: %{name: "John"}},
#      %{title: "Post 2", body: "...", author: %{name: "Jane"}}
#    ]}

sync_schemas(schema_module, opts \\ [])

@spec sync_schemas(module(), opts()) :: :ok | {:error, term()}

Syncs code-defined schemas to the database.

Reads schema definitions from a module using Plato.SchemaBuilder and creates or updates them in the database, marked as managed_by: "code".

Examples

# In application.ex
Plato.sync_schemas(MyApp.ContentSchemas, otp_app: :my_app)

# In a migration
Plato.sync_schemas(MyApp.ContentSchemas, repo: MyApp.Repo)

Options

  • :repo - The Ecto repo to use (required if :otp_app not provided)
  • :otp_app - The OTP app to read repo config from (required if :repo not provided)

update_content(content_id, attrs, opts \\ [])

@spec update_content(integer(), map(), opts()) ::
  {:ok, content_map()} | {:error, Ecto.Changeset.t() | atom()}

Update content by ID.

Examples

Plato.update_content(1, %{title: "Updated Title"}, otp_app: :my_app)
# => {:ok, %{title: "Updated Title", ...}}