Skip to content

pubflow/flowfull-elixir-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Flowfull Elixir Starter

Production-ready Elixir/Phoenix backend template with Flowless integration, featuring WebSocket support and modern async patterns.

πŸš€ Features

Core Capabilities

  1. Bridge Validation - Distributed session validation with Flowless
  2. Auth Middleware - Pipeline-based route protection (required/optional)
  3. WebSocket Channels - Real-time communication with auth integration
  4. Multi-Database - Support for PostgreSQL (including CockroachDB), MySQL, and SQLite
  5. Environment Config - .env file loading with Dotenvy
  6. Ecto ORM - Database operations with optional Repo (starts only if DATABASE_URL set)
  7. Interactive Testing - Built-in WebSocket test page at /ws

Technology Stack

  • Elixir 1.14+ - Functional programming with OTP
  • Phoenix 1.8+ - Modern web framework
  • Bandit - High-performance HTTP/2 server
  • Ecto 3.x - Database wrapper and query DSL
  • Phoenix Channels - WebSocket communication
  • Dotenvy - Environment configuration
  • Req - HTTP client for bridge validation

πŸ“¦ Quick Start

1. Installation

# Clone the repository
git clone <repository-url>
cd flowfull_elixir_starter

# Install dependencies
mix deps.get

# Compile assets (first time only)
mix assets.setup

2. Configuration

# Copy environment template
cp .env.example .env

# Edit .env with your configuration
nano .env

Minimum required configuration:

FLOWLESS_API_URL=https://api.pubflow.com
BRIDGE_VALIDATION_SECRET=your-shared-secret-min-32-chars

Optional configuration (for database):

DATABASE_URL=postgresql://user:pass@localhost:5432/flowfull_dev

3. Database Setup (Optional)

If using a database:

# Create database
mix ecto.create

# Run migrations
mix ecto.migrate

4. Run Development Server

# Start server with hot reload
mix phx.server

# Or start with IEx shell for debugging
iex -S mix phx.server

# Server will be available at:
# - Home: http://localhost:4000
# - Health: http://localhost:4000/api/health
# - WebSocket Test: http://localhost:4000/ws

🌐 API Endpoints

Public Routes (No Authentication)

  • GET / - Home page
  • GET /api/health - Health check
  • GET /api/public - Public content
  • GET /api/content - Mixed content (optional auth)

Protected Routes (Authentication Required)

  • GET /api/secure/me - Current user information
  • GET /api/secure/profile - User profile
  • GET /api/secure/protected - Protected resource

Admin Routes (Admin User Type Required)

  • GET /api/secure/admin/dashboard - Admin dashboard
  • GET /api/secure/admin/users - List all users (DB query)
  • GET /api/secure/admin/users/:id - Get user by ID (DB query)
  • GET /api/secure/users - List all users (alias)
  • GET /api/secure/users/:id - Get user by ID (alias)

πŸ”Œ WebSocket Support

Testing WebSocket

Visit http://localhost:4000/ws for an interactive WebSocket test page.

Features:

  • Connect with or without session authentication
  • Join public channels (no auth required)
  • Join secure channels (auth required)
  • Send custom events
  • View real-time messages

Channel Types

Public Channels (public:*)

  • No authentication required
  • Example: public:lobby
  • Auto-joins on connection in test page

Secure Channels (secure:*)

  • Requires valid session authentication
  • Example: secure:user_room
  • Only accessible with X-Session-Id header or session_id query param

WebSocket Authentication

Pass session ID via query parameter:

const socket = new Phoenix.Socket("/socket", {
  params: {session_id: "your-session-id-here"}
});

Or use the test page at /ws which handles authentication automatically.

πŸ“š Documentation

Comprehensive documentation is available in the /docs directory:

πŸ“– Usage Examples

Public Route (No Authentication)

# In router.ex
scope "/api", MyAppWeb do
  pipe_through :api
  get "/hello", MyController, :hello
end

# In controller
def hello(conn, _params) do
  json(conn, %{message: "Hello, world!"})
end

Protected Route (Authentication Required)

# In router.ex
scope "/api/secure", MyAppWeb do
  pipe_through :api_auth
  get "/profile", MyController, :profile
end

# In controller
def profile(conn, _params) do
  claims = conn.assigns[:auth_claims]
  json(conn, %{
    user_id: claims["user_id"],
    email: claims["email"],
    name: claims["name"]
  })
end

Optional Authentication

# Uses :api pipeline (OptionalMiddleware)
scope "/api", MyAppWeb do
  pipe_through :api
  get "/content", MyController, :content
end

# In controller
def content(conn, _params) do
  claims = conn.assigns[:auth_claims]
  
  if claims do
    json(conn, %{message: "Hello, #{claims["name"]}"})
  else
    json(conn, %{message: "Hello, guest"})
  end
end

Admin-Only Route

scope "/api/secure", MyAppWeb do
  pipe_through :api_auth
  get "/admin/reports", MyController, :admin_reports
end

# In controller
def admin_reports(conn, _params) do
  claims = conn.assigns[:auth_claims] || %{}
  
  if admin?(claims) do
    json(conn, %{reports: []})
  else
    conn
    |> put_status(403)
    |> json(%{error: "forbidden"})
  end
end

defp admin?(%{"user_type" => type}) when type in ["admin", "superadmin"], do: true
defp admin?(_), do: false

Database Operations

alias MyApp.Repo
alias MyApp.Models.User

# Query all users
users = Repo.all(User)

# Get by ID
user = Repo.get(User, "user-id")

# Query with filter
import Ecto.Query
active_users = from(u in User, where: u.active == true) |> Repo.all()

# Insert
%User{id: "new-id", email: "test@example.com"} |> Repo.insert()

# Handle optional DB
try do
  users = Repo.all(User)
  json(conn, users)
rescue
  RuntimeError ->
    conn
    |> put_status(503)
    |> json(%{error: "database not configured"})
end

WebSocket Channel

defmodule MyAppWeb.ChatChannel do
  use MyAppWeb, :channel

  # Public channel
  def join("chat:lobby", _payload, socket) do
    {:ok, socket}
  end

  # Secure channel (auth required)
  def join("chat:private", _payload, socket) do
    if socket.assigns[:auth_claims] do
      {:ok, socket}
    else
      {:error, %{reason: "unauthorized"}}
    end
  end

  def handle_in("new_msg", %{"body" => body}, socket) do
    broadcast!(socket, "new_msg", %{body: body})
    {:noreply, socket}
  end
end

πŸ”§ Development

Code Quality

# Format code
mix format

# Check for compilation warnings
mix compile --warnings-as-errors

# Run precommit checks (format + tests)
mix precommit

Testing

# Run all tests (no database required)
mix test

# Run specific test file
mix test test/flowfull_elixir_starter_web/controllers/page_controller_test.exs

# Run with verbose output
mix test --trace

Note: Tests run without database by default. If you need to test DB-dependent features, ensure DATABASE_URL is not set in test environment or use a SQLite database for testing.

Coverage: This starter template includes basic tests. You can add more comprehensive tests for your application as needed.

πŸ—οΈ Project Structure

flowfull_elixir_starter/
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ flowfull_elixir_starter/
β”‚   β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”‚   β”œβ”€β”€ bridge_validator.ex   # Session validation
β”‚   β”‚   β”‚   β”œβ”€β”€ middleware.ex         # Required auth
β”‚   β”‚   β”‚   └── optional_middleware.ex # Optional auth
β”‚   β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”‚   └── user.ex               # User model
β”‚   β”‚   └── repo.ex                   # Database repo
β”‚   β”œβ”€β”€ flowfull_elixir_starter_web/
β”‚   β”‚   β”œβ”€β”€ channels/
β”‚   β”‚   β”‚   β”œβ”€β”€ public_channel.ex     # Public WS channel
β”‚   β”‚   β”‚   └── secure_channel.ex     # Secure WS channel
β”‚   β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   β”‚   β”œβ”€β”€ page_controller.ex    # Pages (/ws test)
β”‚   β”‚   β”‚   └── sample_controller.ex  # API routes
β”‚   β”‚   β”œβ”€β”€ endpoint.ex               # HTTP endpoint
β”‚   β”‚   β”œβ”€β”€ router.ex                 # Route definitions
β”‚   β”‚   └── user_socket.ex            # WebSocket handler
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ config.exs                    # Compile-time config
β”‚   β”œβ”€β”€ dev.exs                       # Dev config
β”‚   β”œβ”€β”€ test.exs                      # Test config
β”‚   └── runtime.exs                   # Runtime config (Dotenvy)
β”œβ”€β”€ priv/
β”‚   └── repo/
β”‚       └── migrations/               # Database migrations
β”œβ”€β”€ test/                             # Tests
β”œβ”€β”€ docs/                             # Documentation
β”œβ”€β”€ .env.example                      # Environment template
└── mix.exs                           # Project definition

πŸ” Security

Authentication Headers

# Send session ID in header
curl http://localhost:4000/api/secure/profile \
  -H "X-Session-Id: your-session-id-here"

# Or use cookie (alternative)
curl http://localhost:4000/api/secure/profile \
  -H "Cookie: session_id=your-session-id-here"

Note: Header names are automatically normalized to lowercase by Plug (X-Session-Id β†’ x-session-id).

Development Mode

For local development without Flowless:

DEV_ALLOW_BRIDGE_STUB=1

This bypasses real bridge validation and returns mock user data.

πŸš€ Deployment

Environment Variables

Required for production:

FLOWLESS_API_URL=https://your-instance.pubflow.com
BRIDGE_VALIDATION_SECRET=your-production-secret-min-32-chars
DATABASE_URL=postgresql://user:pass@host:5432/db
SECRET_KEY_BASE=your-phoenix-secret-key-base
PORT=4000

Generate Secret Key Base

mix phx.gen.secret

Production Server

# Build release
MIX_ENV=prod mix release

# Run release
_build/prod/rel/flowfull_elixir_starter/bin/flowfull_elixir_starter start

Or use Docker for deployment.

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests and formatting (mix test && mix format)
  5. Submit a pull request

πŸ“„ License

MIT License - see LICENSE file for details

πŸ”— Links

πŸ’¬ Support

For issues and questions:

  • Open an issue on GitHub
  • Check the documentation in /docs directory
  • Contact: support@pubflow.com

Built with ❀️ by the Pubflow Team

About

The king of real-time apps. Power millions of concurrent WebSockets with Phoenix's legendary fault-tolerant architecture.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors