skills/landing_page-controllers/SKILL.md
Guide to Phoenix Controller structure in landing_page_backend using FallbackController, tuple responses, and permission plugs.
npx skillsauth add vuluu2k/skills landing_page-controllersInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Phoenix Controller conventions for Landing Page Backend.
| Topic | Description | Reference | |-------|-------------|-----------| | FallbackController | Centralized response handling via tuples | core-fallback | | Permission Plugs | Action-level permission guards | core-fallback | | Ecto.Multi in Controllers | Transactional operations across multiple steps | core-fallback |
defmodule LandingPageWeb.V1.OrganizationController do
use LandingPageWeb, :controller
alias Ecto.Multi
alias LandingPage.{Tools, Organizations, Repo}
alias LandingPage.Organizations.{Organization, OrganizationMember}
# Permission plugs — chỉ áp dụng cho specific actions
plug LandingPageWeb.Plug.PermissionCheck,
[role: :organization_admin, type: :organization]
when action in [:bulk_update_rights, :update_invite_code]
plug LandingPageWeb.Plug.SubscriptionPlug
when action in [:create_organization]
action_fallback LandingPageWeb.FallbackController
def create_organization(conn, %{"name" => name}) do
account = conn.assigns.account
invite_code = Tools.randomizer(3) <> "-" <> Tools.randomizer(1) <> "-" <> Tools.randomizer(2)
multi = Multi.new()
|> Multi.run(:organization, fn _, _ ->
Organizations.create_organization(%{
name: name, owner_id: account.id,
settings: %{sync: %{sync_draft_to_pos: true}},
invite_code: invite_code
})
end)
|> Multi.run(:organization_members, fn _, %{organization: org} ->
Organizations.create_organization_members(org.id, account.id,
Enum.OrganizationPermission.value(:organization_owner))
end)
case Repo.transaction(multi) do
{:ok, result} ->
org = Repo.preload(result.organization, :owner)
{:success, :with_data, "organization", Organization.json(org)}
_ ->
{:failed, :with_reason, "Create Organization Failed! ERROR CODE: CO0001"}
end
end
def list_organizations(conn, params) do
account = conn.assigns.account
case Organizations.get_organizations(account.id, params) do
{:ok, orgs} ->
{:success, :with_data, "organizations", Enum.map(orgs, &Organization.json/1)}
_ ->
{:failed, :with_reason, "Failed to get organizations"}
end
end
end
development
Vue 3 Composition API — <script setup>, reactivity (shallowRef/ref), props without destructure, computed, watch, provide/inject, and composables. Use when the project uses modern Vue 3 Composition API style.
development
Vue 3 Options API — data, props, computed, methods, watch, emits, provide/inject, lifecycle hooks, and mixins. Use when the project uses Options API style (Vue 2 legacy or explicit Vue 3 Options API preference).
tools
Best practices for mixing Ant Design Vue components with Tailwind CSS utility classes. Use this skill to keep styling consistent without custom CSS files.
development
Pinia state management for Vue 3 using Composition API (Setup Stores) — TypeScript-first, storeToRefs for reactivity, focused stores, and API calls in composables. Use when the project uses Vue 3 Composition API / <script setup>.