project-guidelines
Provides project-specific guidelines for Phoenix development including workflow, Phoenix v1.8 conventions, Tailwind CSS v4, asset bundling, and UI/UX best practices. Use when setting up development workflow, working with assets, styling, or ensuring project conventions.
- Category: discovered
- Tags: github, community
- Version: 1.0.0
- Author: walid
- Downloads: 0
- GitHub stars: 1
- Updated: 2025-11-21
Download the latest version (v1.0.0) from this page.
SKILL.md
---
name: project-guidelines
description: Provides project-specific guidelines for Phoenix development including workflow, Phoenix v1.8 conventions, Tailwind CSS v4, asset bundling, and UI/UX best practices. Use when setting up development workflow, working with assets, styling, or ensuring project conventions.
---
# Project Guidelines
This skill provides project-specific guidelines for developing this Phoenix application.
## Development Workflow
### Pre-commit Checks
- Use `mix precommit` alias when done with all changes
- This runs: compile with warnings as errors, unlock unused deps, format, and test
- Fix any pending issues before committing
### HTTP Client
- Use the already included `:req` (`Req`) library for HTTP requests
- **Avoid** `:httpoison`, `:tesla`, and `:httpc`
- Req is included by default and is the preferred HTTP client for Phoenix apps
```elixir
# Use Req for HTTP requests
Req.get!("https://api.example.com/data")
Req.post!("https://api.example.com/users", json: %{name: "Alice"})
```
## Phoenix v1.8 Conventions
### Layout Components
- **Always** begin LiveView templates with `<Layouts.app flash={@flash} ...>` which wraps all inner content
- The `MyAppWeb.Layouts` module is aliased in the `my_app_web.ex` file—no need to alias it again
```heex
<Layouts.app flash={@flash} current_scope={@current_scope}>
<%!-- Your content here --%>
</Layouts.app>
```
### Current Scope Issues
When you encounter errors with no `current_scope` assign:
1. You failed to follow Authenticated Routes guidelines, OR
2. You failed to pass `current_scope` to `<Layouts.app>`
**Fix** by moving routes to proper `live_session` and ensure you pass `current_scope` as needed.
### Flash Messages
- Phoenix v1.8 moved the `<.flash_group>` component to the `Layouts` module
- You are **forbidden** from calling `<.flash_group>` outside of the `layouts.ex` module
### Icons
- Out of the box, `core_components.ex` imports `<.icon name="hero-x-mark" class="w-5 h-5"/>` for hero icons
- **Always** use the `<.icon>` component for icons
- **Never** use `Heroicons` modules or similar
```heex
<.icon name="hero-user" class="w-6 h-6" />
<.icon name="hero-envelope" class="w-5 h-5" />
```
### Form Inputs
- **Always** use the imported `<.input>` component from `core_components.ex` when available
- Using `<.input>` will save steps and prevent errors
```heex
<.input field={@form[:email]} label="Email" type="email" />
<.input field={@form[:password]} label="Password" type="password" />
```
**Class Override Warning**: If you override default input classes with custom values, no default classes are inherited. Your custom classes must fully style the input.
## JS and CSS Guidelines
### Styling Philosophy
**Use Tailwind CSS classes and custom CSS rules** to create polished, responsive, and visually stunning interfaces.
### Tailwind CSS v4
Tailwind CSS v4 **no longer needs a tailwind.config.js** and uses new import syntax in `app.css`:
```css
@import "tailwindcss" source(none);
@source "../css";
@source "../js";
@source "../../lib/my_app_web";
```
**Important**:
- **Always use and maintain this import syntax** in app.css for projects generated with `phx.new`
- **Never** use `@apply` when writing raw CSS in Tailwind v4
### UI Components
- **Always** manually write your own Tailwind-based components
- **Never** use daisyUI for a unique, world-class design
- Build custom components that match your brand and design system
### Asset Bundling
Out of the box **only the app.js and app.css bundles are supported**:
- You **cannot** reference an external vendor'd script `src` or link `href` in the layouts
- You **must** import vendor deps into app.js and app.css to use them
- **Never write inline `<script>custom js</script>` tags within templates**
**Example** (in `assets/js/app.js`):
```javascript
// Import vendor libraries
import Chart from "chart.js/auto"
import Alpine from "alpinejs"
// Make available globally if needed
window.Chart = Chart
window.Alpine = Alpine
Alpine.start()
```
## UI/UX & Design Guidelines
### Design Philosophy
**Produce world-class UI designs** with focus on:
- Usability
- Aesthetics
- Modern design principles
### Micro-interactions
Implement **subtle micro-interactions**:
- Button hover effects
- Smooth transitions
- Loading states
- Focus states
```heex
<button class="
px-4 py-2 bg-blue-600 text-white rounded-lg
transition-all duration-200
hover:bg-blue-700 hover:shadow-lg
active:scale-95
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
">
Click me
</button>
```
### Typography and Layout
Ensure **clean typography, spacing, and layout balance** for a refined, premium look:
- Use consistent spacing scales (Tailwind's spacing is great)
- Maintain visual hierarchy with font sizes and weights
- Use proper line heights for readability
- Ensure adequate contrast ratios
### Page Header Pattern
All pages should follow a consistent page header pattern:
```heex
<!-- Page Header -->
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mb-8">
<div>
<h1 class="text-2xl md:text-3xl font-bold tracking-tight text-base-content">
Page Title
</h1>
<p class="mt-1 text-sm text-base-content/60">
Description text
</p>
</div>
<div class="mt-4 sm:mt-0 flex flex-col sm:flex-row items-stretch sm:items-center gap-3">
<!-- Action buttons -->
</div>
</div>
```
**Key Classes:**
- **Title**: `text-2xl md:text-3xl font-bold tracking-tight text-base-content`
- **Description**: `mt-1 text-sm text-base-content/60`
- **Actions container**: `mt-4 sm:mt-0 flex flex-col sm:flex-row items-stretch sm:items-center gap-3`
**Responsive Behavior:**
- Mobile (<640px): Title and actions stack vertically, actions stretch full width
- Tablet/Desktop (≥640px): Title and actions side by side
### Dark Mode Support
Use DaisyUI semantic color classes for automatic dark mode support:
| Purpose | Use | Avoid |
|---------|-----|-------|
| Primary text | `text-base-content` | `text-gray-900`, `text-black` |
| Secondary text | `text-base-content/60` | `text-gray-600` |
| Muted text | `text-base-content/40` | `text-gray-400` |
| Primary background | `bg-base-100` | `bg-white` |
| Secondary background | `bg-base-200` | `bg-gray-100` |
| Borders | `border-base-300` | `border-gray-200` |
**Status Badge Pattern:**
```elixir
defp status_badge_class(:draft), do: "bg-base-200 text-base-content"
defp status_badge_class(:published), do: "bg-success/20 text-success"
defp status_badge_class(:archived), do: "bg-warning/20 text-warning"
```
### Card Styling
Consistent card pattern across all pages:
```heex
<div class="bg-base-100 rounded-lg shadow-md border border-base-300 p-6 transition-shadow hover:shadow-lg">
<!-- Card content -->
</div>
```
### Delightful Details
Focus on **delightful details**:
- Hover effects on interactive elements
- Loading states for async operations
- Smooth page transitions
- Empty states with helpful guidance
- Success/error feedback with appropriate styling
### Examples
**Card with hover effect**:
```heex
<div class="
group p-6 bg-white rounded-xl shadow-sm
transition-all duration-300
hover:shadow-xl hover:-translate-y-1
">
<h3 class="text-lg font-semibold text-gray-900 group-hover:text-blue-600 transition-colors">
{@title}
</h3>
<p class="mt-2 text-gray-600">{@description}</p>
</div>
```
**Loading state**:
```heex
<div :if={@loading} class="flex items-center justify-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
</div>
```
## Summary
- Run `mix precommit` before committing
- Use Req library for HTTP requests
- Follow Phoenix v1.8 conventions (Layouts.app, icons, inputs)
- Use Tailwind v4 import syntax in app.css
- Never use `@apply` in raw CSS
- Build custom components, avoid daisyUI
- Import vendor deps into app.js/app.css
- Focus on world-class UI with micro-interactions and delightful details
- Use consistent page header pattern across all pages
- Use DaisyUI semantic classes for dark mode support (`text-base-content`, `bg-base-100`, etc.)