
Analyze the chaos of managing a 160-unit apartment complex on WhatsApp and how Proplex streamlines tenant issue reporting, provides reliable technician cues, and creates auditable trails.
Install Elixir 1.19.5 and Phoenix 1.8.5, then verify versions in the terminal. Configure Postgres for data persistence with Docker in production and optional pgcli for terminal access.
Navigate to the working directory, generate a new phoenix app named proplex with mix phx new, install dependencies, and open the project in VS Code for the next lecture.
Navigate the mix Phoenix.new project structure, from build and assets to lib with proplex and proplex_web, and to config, env files, runtime.exs, and gitignore guidelines.
Phoenix router out of the box routes, view them with mix phx.routes, and compare dead views and live views for real-time interactivity without writing a dedicated JavaScript front-end.
Remove default landing elements in a Phoenix Elixir app, customize the home page using layouts.app and tailwind, and streamline routing, flash messages, and styling.
Build and validate a user schema with a username field in a Phoenix Elixir app, implement a registration change set, username validation, and unique constraints while securing passwords.
Update the registration page to require username alongside email, implement live view form with debounced validation, and handle user registration with email confirmation and navigation flows.
Create a reusable password input with show/hide toggle in Phoenix LiveView, and implement a check email page with mount logic to show the submitted email after registration.
Refine the login flow in a Phoenix LiveView app by updating login.ex and the navbar to show the username after login and redirect to the homepage.
Enable logout via the Phoenix Auth generator and implement reset password token verification by decoding a url safe token, hashing it, and querying the user with Ecto.
Create a reset password live view that extracts the reset token, renders the new password form, debounces validation, and updates the password with redirects on success.
Implement the forgot password and reset password flows with live view routes, update login and forgot password views, and test password reset via email, completing the authentication workflow.
Define roles schema in authorization module using Ecto schema and changesets, mapping name, description, and property_id, with a many-to-many link to permissions via role_permissions and has many user roles.
Create the permissions schema and user role associations, fix folder misalignment, implement permission changesets with resource and action, and establish user_role with belongs to relations and unique constraints.
Define and assign roles to users within the authorization context, implementing getRoleByName and hasRole, creating userRole via repo.insert, and exposing listRoles and listPermissions.
Amend the user schema to support multiple roles via hasMany through userRoles, then auto-assign the tenant role on user registration, seed permissions and roles (tenant, technician, admin), and run migrations.
Create the profiles table with a one-to-one relationship to users and a unique on user_id; add fields including first name, last name, gender, bio, avatar, and reputation defaulting to 100.
Implement an atomic user registration flow by wrapping user creation, empty profile setup, and default tenant role assignment in an ecto.multi transaction, ensuring rollback on any failure.
Build a profile show LiveView in a Phoenix LiveView app, rendering user data including avatar, display name, occupation, location, bio, reputation, rating, and reports, with formatting helpers.
Enable logged-in users to update their profile by building change sets for validation, applying edits, and saving via the repository, then wiring an authenticated live view route and permission checks.
Build a profile edit live view in the Elixir Phoenix LiveView course, featuring a multi-field profile form (name, gender, occupation, bio, contact details) and navigation back to the user profile.
Implement mount to preload the current user profile, build a form from a changeset, and handle validation and updates in a Phoenix LiveView.
Enhance the profile show live view by adding an edit button and displaying gender with occupation. Implement gender formatting and ownership checks, fix route order issue, and verify edits save.
Improve live view performance by adding debouncing to form fields with phx debounce 400 and replacing redirects with push navigate in forgot and reset password flows, preventing extra http roundtrips.
Upload avatars locally with validation and image processing using Phoenix's allow upload, stream chunks via WebSocket, and prepare for scalable storage with S3; amend mix.exe to add a libvips-based image library.
Explain avatar upload handling in a Phoenix LiveView app, including live previews, resizing and compressing to JPEG, saving to uploads/avatars, and managing old avatars and errors.
Address rate limiting and avatar display by preloading user profiles for the navbar avatar, and add a cancel button on the edit profile page to return to the profile show.
Implement a hammer-based rate limiter backed by ETS. Enforce 15-minute and 1-hour windows with per-email and per-IP limits, and wire before the web endpoint; consider redis for multi-node use.
Add a private helper to apply rate limiting on avatar saves, wrap the save flow with the rate check, and enforce a per-user one-hour quota with a friendly retry message.
Enforce rate limiting on the forgot password flow in a Phoenix LiveView app by capturing the client IP, checking limits, sending reset emails, and displaying retry guidance.
Configure Elixir's logger in config.exs, expand metadata to include event, user info, limiter, retry after, and auth and role data, then verify development logs.
Enhance logging by adding logger.info and logger.warning calls for user registration, login by magic link, and role management, including user ID, email, events, and metadata.
Add structured logging to password reset and auth flows in a Phoenix LiveView app, using logger.info to log password reset requests, user status, and IP address for audit.
Create the apartments feature by adding a migration to create the apartments table with building name, unit number, and floor, plus utc datetime timestamps and a composite unique index.
Create apartment and tenancy schemas, add a one-to-many relationship from users to tenancies, define building name, unit number, and floor validations, with soft delete and trimming for live view guards.
Define the tenancy schema with user and apartment associations, add start and end dates with end-after-start validation, and enable drag-and-drop avatar uploads via phx drop target.
Learn to implement start tenancy and end tenancy workflows in Elixir Phoenix LiveView, including pre-checks for archived apartments, audit logging, and active tenancy queries with preloaded apartment data.
Define a function to return the currently active tenancy for an apartment or nil if vacant using pattern matching and repo.one. Seed data with seeds.exe from the seeds directory.
Create a read-only my apartment live view for a logged-in tenant to see their current unit or an empty state, powered by Phoenix LiveView with preloaded tenancy data.
Edit the router to add a live view route for my apartment, enforce authentication and apartments view own permission, then test tenancy creation via IEX and commit the change.
Create the issues table with title, description, priority, status (default reported), resolved_on, and soft delete; add reporter, apartment, and assigned technician foreign keys, plus indexes, then migrate.
Define an issues schema in Elixir with title, description, priority, status, timestamps, and associations to reporter, apartment, and assigned technician, change sets for report, assign, start, resolve, and soft delete.
Amend user and apartment schemas to add has many relations to issues and tenancies, using custom foreign keys reporter_id and assigned_technician_id, then commit the add issues tables feature.
Build an issues context for real estate, add logger metadata keys in config.exs, and implement report issue and assign technician with tenancy checks, changesets, and event logging.
Move issues from reported to in progress and from in progress to resolved in Elixir Phoenix LiveView course, implement soft delete with timestamp, and log events via changesets and updates.
Create an issues list that filters status, priority, and unassigned, includes deleted, preloads reporter and technician, and orders newest first, with change sets and attribute normalization for the user interface.
Create a tenant maintenance issue live view with a report form, including title, description, and priority, conditional on an active tenancy.
Build a Phoenix LiveView for real estate, mounting with a socket, fetching the active apartment for the current scope user, and enabling live form validation and issue reporting.
Protect the /issues/new live route by grouping routes in a live session with onMount hooks that enforce user authentication and the issues create permission.
create an index live view to display a user’s reported issues, including an empty state and clickable issue cards with status and priority badges and assignee details.
Create the issues detail page in a phoenix live view by duplicating the index. Render the issue title, description, apartment, timestamps, status, priority badges, and a reporter-only soft delete option.
master the mount function in a Phoenix LiveView to fetch an issue, handle reporter and admin viewers, and implement delete with permission checks and navigation.
Add routes for issues and implement index and show live views, update the navigation with my issues, and set post-save redirect to the issues list with authentication.
Build a technician assignments view with phoenix liveview, supporting an empty state or a list of issues with badges, then route /issues/assigned to a shared show page.
Update root.html to conditionally display my assignments for users with view assigned and issues permissions, and seed roles to test admin, technician, and tenant workflows.
Add list_users_with_role to the authorization module to fetch all user IDs for role by joining userRole with role, filtering by role.name, and using a subquery for results in admin UI.
Implement admin assign or reassign form in a Phoenix LiveView app, render technician options, and update the UI when the assignment changes.
Extend the admin UI by building the apartments context with left joins to tenancy and user, apply filters for active and archived units, and configure admin live routing and permissions.
Create the admin index page to display every unit across all buildings with current occupants. Implement a filter bar and building dropdown to refine results by occupancy and building status.
Builds an admin live view for real estate listings using Elixir Phoenix LiveView, loading building names and apartments on mount with default filters, and implements interactive filtering and reset actions.
Add create and edit apartment functionality on the admin index, including a new apartment button in the header, and routes for new and edit apartment forms.
Create and edit apartments in a Phoenix LiveView admin UI by building a dynamic admin form with building name, unit, floor, status badges, and archive workflow for real estate management.
Demonstrates mounting and loading apartment records in an Elixir Phoenix LiveView admin UI, handling create, update, archive, unarchive, validation, and flash messages and navigation.
Add an admin apartments link in the admin ui by updating root.html.heex to route to /admin/apartments with proper authorization for the current user, enabling tenancy management and viewing apartment history.
What if you could learn modern web development by building something real?
For three years, I lived in a 160-unit apartment complex run on a single WhatsApp account. Maintenance reports buried under marketplace ads. Technicians who ghosted calls. Neighbors complaining about each other in a group chat everyone reads — including the people they're complaining about. I eventually moved out, and built Proplex: the property management platform I wished my landlord had.
This course is the complete walkthrough of how it's built, end to end — every architectural decision explained on the way.
What You'll Build
A multi-tenant SaaS with three roles (tenants, technicians, admins) sharing one Phoenix LiveView app:
Invite-based tenant onboarding with atomic multi-step transactions
Issue tracking with state machines, soft delete, and an audit trail
Real-time chat per issue — typing indicators, emoji reactions, edit/delete, read receipts
Anonymous misconduct reporting with admin moderation and an escalation cascade
Custom dynamic role-based access control
In-app notification center + email broadcasts via Oban background jobs (no Redis required)
Marketing splash + role-aware personalized dashboard
What You'll Learn
Elixir + OTP fundamentals — pattern matching, processes, "let it crash" philosophy
Phoenix LiveView 1.1 — server-rendered HTML diffed over WebSocket; no separate frontend framework
Phoenix.PubSub + Phoenix.Presence — real-time fan-out and online tracking
Ecto deep dive — changesets, multi-step transactions, partial indexes, cursor pagination
Custom RBAC vs off-the-shelf auth — when to roll your own
Oban background jobs without Redis — bulk insert, scheduled cron, retry semantics
Tailwind v4 + daisyUI for fast, themed UI without tailwind.config.js
Production patterns — soft delete, audit trail, optimistic UI, schemaless changesets, structured logging
Who This Course Is For
Developers comfortable with any backend language, ready to apply Elixir to a real, multi-feature SaaS — not a tutorial example
Engineers from Rails / Django / Node curious about what LiveView changes day-to-day
Founders evaluating Phoenix as a single-deployment alternative to a JavaScript frontend + REST API stack
Anyone tired of courses that stop at "TODO list with auth"
Prerequisites
One year of web development experience in any backend language
Basic Elixir familiarity (or willingness to learn it alongside)
Comfort with SQL and the command line
macOS or Linux recommended (Windows works via WSL2)
What Makes This Course Different
Every architectural decision is explained, not just executed. When we add a partial index, you'll know why, not just that. When we choose Oban over Quantum, you'll understand the tradeoff. When we soft-delete instead of hard-delete, the reasoning is on the table. The codebase is heavily commented — and those comments explain the why, not the what.
By the end, you won't just have followed along. You'll have shipped a SaaS that could actually go to market, and the architectural instincts to build the next one on your own.
Enroll today and let's build something real.