Skip to content
CAI
Software that uses CAICheck a score

thisistonydang/liveview-svelte-pwa

47.3

Weak · 18 September 2026

4k

lines of production code

Elixir

with TypeScript, JavaScript

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a local-first, offline-capable Progressive Web Application built on Phoenix LiveView and Svelte, designed to demonstrate real-time collaboration and data synchronization. It manages user authentication and persists to-do items as Yjs CRDT documents in IndexedDB, syncing them to a PostgreSQL backend via WebSockets. The application features multi-tab synchronization, presence tracking, and a robust UI with theme support, deployed via Fly.io.

How it got here

2023 — Initial scaffolding and PWA foundation

25 changes.

The project established its foundational infrastructure, configuring the Elixir/Svelte stack, Docker deployment, and build pipelines. It implemented core local-first PWA capabilities using Yjs for offline synchronization and added a complete user authentication system with protected routes and real-time presence tracking.

2024 — Client-side infrastructure and offline support

6 changes.

This period focused on enhancing the client-side architecture by migrating stores to TypeScript and introducing utility hooks for service workers and connectivity. It also added Svelte actions for interaction handling and established the backend schema for storing Yjs collaboration documents to support offline capabilities.

Features

Add user document schema for storing Yjs documents

A new Ecto schema, UserDocument, has been introduced to manage the user\_documents table. This schema stores Yjs collaboration documents as base64-encoded strings and establishes a one-to-one relationship with the User account via a unique foreign key constraint on user\_id.

_lib/live\_view\_svelte\_offline\_demo/user\data · high confidence

Added PWA support and blocked all web crawlers

The application now supports Progressive Web App (PWA) features by introducing a service worker (sw.js) that caches assets and serves content offline, along with a web manifest (site.webmanifest) and browser-specific icons (browserconfig.xml, safari-pinned-tab.svg) to enable installation and standalone display. Additionally, robots.txt has been updated to block all web crawlers from indexing the site, preventing unnecessary server wake-ups.

priv/static · high confidence

Added user authentication, document management, and real-time presence capabilities

The demo application now includes a complete user management system (registration, login, email/password updates) via the new Accounts context, alongside a UserData context that handles user-specific document storage and broadcasts updates via Phoenix PubSub. Real-time collaboration is supported by adding Phoenix Presence to the supervision tree, and the application now uses JWT for authentication, sending tokens as JSON rather than query parameters.

_lib/live\_view\_svelte\_offline\demo · high confidence

Authentication system added with protected routes

The application now includes a full authentication system. Users can register, log in, reset passwords, and confirm email addresses via new LiveView pages and controllers. The router has been updated to enforce authentication: the main application route (/app) and user settings are now protected and require a logged-in user, while login and registration routes redirect authenticated users away. A new UserAuth module handles session management, including 'remember me' cookies and LiveView session disconnection on logout.

_lib/live\_view\_svelte\_offline\_demo\web · high confidence

Initial Svelte asset build pipeline and UI configuration

This change introduces the foundational build infrastructure for Svelte components within the application. It adds a new \build.js\ script using esbuild to bundle client and server-side Svelte code, configures TypeScript via \tsconfig.json\ with module resolution and path aliases for components, libraries, and stores, and updates \tailwind.config.js\ to scan Svelte files, define custom animations, add an extra-small screen breakpoint, and integrate the daisyUI plugin for pre-styled UI components. Additionally, global TypeScript declarations are added to support the svelte-dnd-action library.

assets · high confidence

Initial project scaffolding and configuration

This change establishes the foundational configuration and documentation for the LiveView Svelte PWA application. It introduces Credo for Elixir code quality analysis, Prettier for Svelte file formatting, and a .tool-versions file to pin Erlang 26.2.1 and Elixir 1.16.0. A multi-stage Dockerfile is added to build the application with Node.js 22, and a fly.toml configures deployment to Fly.io with 512MB shared VMs. The project also includes a .dockerignore to optimize build contexts, a .gitignore for environment and build artifacts, an MIT license, and a comprehensive README detailing local setup, deployment steps, and the technology stack (Phoenix, LiveSvelte, Yjs).

(repo-wide) · high confidence

Introduce local-first architecture with offline support and multi-tab synchronization

The application now operates as a local-first Progressive Web App, persisting all to-do data in IndexedDB via Yjs CRDTs to ensure full offline functionality and conflict-free synchronization across multiple browser tabs. The UI is now rendered entirely within Svelte components (such as App, TodoApp, and Header) rather than Phoenix LiveView templates, with the Svelte frontend syncing its state to the server in real-time via the live\_svelte socket. This change introduces a new account menu for user settings and logout, a dedicated About page, and robust state management that restores scroll position and client-only UI state (like open menus) from session storage.

assets/svelte · high confidence

New Svelte actions for click-outside detection, focus trapping, and keydown handling

Three new Svelte action helpers have been added to the library to simplify common interaction patterns. The \clickOutside\ action triggers a callback when a click occurs outside the bound element. The \focusTrap\ action confines keyboard navigation (Tab, Shift+Tab, ArrowUp, ArrowDown) to elements marked with a \data-focusindex\ attribute within the bound container, optionally focusing the first element on initialization and allowing a custom callback on Escape. The \onKeydown\ action provides a reusable way to listen for keydown events on an element. All actions support lifecycle updates and cleanup via their standard Svelte action interface.

assets/lib/actions · high confidence

Topbar loading indicator initialization and event wiring

The topbar library now includes an initialization function that configures the topbar's visual style (teal bar color, shadow) and automatically shows or hides it in response to Phoenix page-loading events. This is achieved by listening for custom events dispatched by the application, ensuring the loading indicator appears during page transitions.

assets/lib/topbar · high confidence

Removals

Homepage template removed

The default Phoenix homepage template (home.html.heex) has been deleted from the application. This removes the standard landing page content, including the hero section, branding, and navigation links to guides, source code, and community resources.

_lib/live\_view\_svelte\_offline\_demo\_web/controllers/page\html · high confidence

Removed unused database seed script

The default database seeding script (priv/repo/seeds.exs) has been removed from the application. This file, which previously contained boilerplate instructions for populating the database using the repository, is no longer present, indicating that the default seeding mechanism is no longer supported or required.

priv/repo · high confidence

Behavioural changes

Add Phoenix authentication scaffolding with external email delivery

The accounts context now includes generated authentication modules (User, UserToken, UserNotifier) that handle user registration, password hashing, and session management. Email notifications for account confirmation, password resets, and email updates are no longer sent via the local application mailer; instead, they are dispatched to an external JS backend microservice by generating and signing a JWT token, provided the required environment variables are set.

_lib/live\_view\_svelte\_offline\demo/accounts · high confidence

Add user authentication pages and socket-based presence tracking

The application now includes a full set of user authentication pages (login, registration, password reset, and account confirmation) that utilize a shared \user\_auth\_layout\ and a new \Back\ component for navigation. Additionally, a new \SocketLive\ component manages the WebSocket connection, handling document synchronization and tracking user presence via visibility change events to update the active session count.

_lib/live\_view\_svelte\_offline\_demo\web/live · high confidence

Added Fly.io deployment configuration and release scripts

The application now includes specific configuration for deployment on Fly.io. The rel/env.sh.eex script configures the Erlang runtime for distributed nodes over IPv6 and sets up DNS clustering using Fly's internal DNS. Additionally, new release scripts (migrate, server) and their Windows counterparts have been added to the rel/overlays/bin directory to handle database migrations and start the Phoenix server with the correct environment variables.

rel · high confidence

Centralized asset path definitions

The list of public and private asset paths has been extracted into a dedicated module (assets/lib/assets.ts). This change centralizes the definition of static resources such as favicons, touch icons, screenshots, and the offline route, making it easier to manage and reference these paths across the application.

assets/lib · high confidence

Corrected user session count by tracking unique session IDs

The presence tracking logic has been updated to accurately count active user sessions. Previously, the session count could be skewed by 'zombie' sessions (stale or duplicate entries). The new implementation in the Presence module ensures that only unique session IDs are counted when determining the number of active sessions for a user, providing a more reliable indicator of concurrent usage.

_lib/live\_view\_svelte\_offline\_demo\web/channels · high confidence

Expanded static asset support and LiveSvelte integration in web templates

The application now serves a broader range of static files—including service workers (sw.js, sw.config.js), various favicon and touch-icon assets, Open Graph images, and screenshots—by updating the allowed static paths. Additionally, all HTML templates now automatically import custom components and use LiveSvelte components, enabling the use of LiveSvelte UI elements across the application without manual inclusion in each view.

lib · high confidence

Migrate Phoenix LiveView setup to TypeScript with enhanced offline and reconnection handling

The main application entry point has been migrated from JavaScript to TypeScript (app.js to app.ts), introducing several improvements to the user experience. Service worker registration is now handled via a dedicated hook, and a topbar is initialized for navigation feedback. The application now detects when a user is logged out upon WebSocket connection and redirects accordingly, bypassing service worker caching issues. Additionally, reconnection logic has been strengthened: the app checks for server connectivity before reloading on visibility changes, and patches console logs to detect stale CSRF tokens, automatically reloading the page to fetch fresh tokens. These changes ensure a more robust experience when the app is offline or when network conditions fluctuate.

assets/js · high confidence

Migration of client-side stores to TypeScript

The application's client-side state management in the \assets/stores\ directory has been converted from JavaScript to TypeScript. This change introduces strict type definitions for core data models like \TodoList\ and \TodoItem\, including a type guard (\isTodoItem\) to distinguish between them. It also standardizes the typing for UI state stores (theme, sync status, toast notifications, and client-only flags) and integrates with the \live\_svelte\ library for real-time socket communication. This improves code reliability and developer experience by catching type errors at compile time.

assets/stores · high confidence

New utility hooks for service worker registration, connectivity, and touch detection

This change introduces three new React hooks in the assets/lib/hooks directory to improve service worker handling and device capability detection. useRegisterServiceWorker replaces the previous registerServiceWorker script, providing a modular way to register service workers with ES module support and cache bypass. useIsConnected replaces the previous isConnected function, switching from a HEAD request to a fetch with a query parameter to bypass service worker caching issues, specifically fixing a bug in Safari. Additionally, useHasTouchScreen is added to detect touch screen capabilities using navigator properties, matchMedia, and user-agent fallbacks.

assets/lib/hooks · high confidence

Restructured web controllers and added custom error pages

The application's web layer has been reorganized to support distinct pages and improved error handling. The previous \PageController\ has been removed and replaced with dedicated controllers for the home page (\HomeController\), the main application (\AppController\), and an offline fallback (\OfflineController\). Additionally, custom error pages have been implemented for 404 and 500 errors, displaying user-friendly messages via an \ErrorLayout\ component instead of plain text, and a new \UserSessionController\ handles user authentication flows.

_lib/live\_view\_svelte\_offline\_demo\web/controllers · high confidence

Simplified layout structure and added conditional UI components

The application's layout system has been refactored to remove the previous boilerplate header and main wrapper from app.html.heex, leaving only the flash group and inner content. The root template (root.html.heex) has been significantly simplified to remove standard HTML boilerplate (doctype, head, body tags) and instead delegates to a root\_html component. Additionally, conditional UI elements have been introduced: a hidden logout link is rendered when a user is logged in, and a DataClearer component is rendered when no user is authenticated.

_lib/live\_view\_svelte\_offline\_demo\web/components/layouts · high confidence

Switched asset bundler from esbuild to Node.js and enabled local network access

The application no longer uses esbuild for asset compilation; instead, it delegates to a custom Node.js script (build.js) in development, and the esbuild configuration has been commented out. In development mode, the HTTP server now binds to all interfaces (0.0.0.0) rather than just localhost, allowing access from other machines on the local network. Additionally, the system now configures JWT signing via the JWT\_PRIVATE\_KEY environment variable at runtime, warning if the key is missing, and test configurations have been updated to simplify password hashing complexity.

config · high confidence

UI overhaul with theme support and sticky header

The application's visual design has been updated to use semantic theme colors (success, error, accent) instead of hardcoded zinc/rose palettes, ensuring consistent styling across flash messages, forms, buttons, and inputs. A new sticky header component has been introduced, featuring a backdrop-blur effect and dynamic border styling on scroll, while the root HTML layout now includes a script to apply the user's preferred light or dark theme immediately to avoid flash of unstyled content. Additionally, the layout structure has been refined with adjusted margins, a new user authentication layout wrapper, and improved focus styles for accessibility.

_lib/live\_view\_svelte\_offline\_demo\web/components · high confidence

Updated database schema for authentication, user states, and documents

The database schema has been updated with new migrations to support user authentication and data management. A new migration creates the \users\ and \users\_tokens\ tables to handle authentication, including email verification and token-based sessions. Additionally, a \user\_states\ table was introduced to store per-user state maps, and a \user\_documents\ table was added to store user-specific text documents. However, the \user\_states\ table has since been dropped in a subsequent migration, indicating a change in how user state is managed or persisted.

priv/repo/migrations · high confidence

Test coverage

Added Faker library to test environment; Added and updated controller tests for authentication and error handling; Added test coverage for accounts and user data contexts; Added test coverage for user authentication and account management LiveViews; Added tests for user authentication logic.

Dependencies

Initial project setup with Svelte, LiveView, and dev tooling

The application is initialized with a full stack including Phoenix LiveView (0.20.3) and Svelte (4.2.7) via the live\_svelte integration (0.13.0). Frontend dependencies include UI libraries like daisyui (4.4.17), lucide-svelte (0.365.0), and svelte-dnd-action (0.9.48), along with build tools like esbuild (0.16.17) and TypeScript (5.3.3). Backend dependencies add JWT handling (joken 2.6.0), HTTP requests (req 0.4.8), and password hashing (bcrypt\_elixir 3.1.0). Development tooling is introduced with credo (1.7.4), dialyxir (1.4.3), sobelow (0.13.0), and faker (0.17.0). The build process shifts from esbuild to npm for asset compilation.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 47.

Lenses

  • Code Health 95
  • Architecture 94
  • Maturity 59
  • Readiness 22
  • Security 76
  • Accessibility 71

Changes since last survey

  • 300 commits — 289 feature/other, 11 fixes

By area

  • assets/svelte — 182 commits
  • assets/lib — 34 commits
  • (root) — 22 commits
  • priv/static — 17 commits
  • assets/js — 14 commits
  • lib/live_view_svelte_offline_demo — 8 commits
  • lib/live_view_svelte_offline_demo_web — 8 commits
  • assets/stores — 7 commits
  • assets/package-lock.json — 5 commits
  • assets/tailwind.config.js — 1 commit
  • assets/tsconfig.json — 1 commit
  • priv/repo — 1 commit

Notable commits

  • fix: Bump sw version. Fixes SW not registering in Firefox.
  • fix: Bump sw version. Fixes detecting inaccurate connection status on Safari
  • fix: Use query param instead of HEAD request to bypass SW. Fixes bug with Safari.
  • fix: Use query param instead of HEAD request to bypass SW. Fixes bug with Safari.
  • fix: fix badge gap
  • fix: fix dnd bug
  • fix: fix dnd scroll bug by updating svelte-dnd-action
  • fix: fix email delivery logic when env variables are not set
  • fix: fix type error
  • fix: revert to page reload to force socket reconnection
  • fix: update error layout now that encoding issue is fixed
  • change: Add demo video to README
  • change: Block all crawlers, not just the app routes
  • change: Reduce Fly costs: 512MB machines, no idle machine, robots.txt
  • change: add .env.example
  • change: add LICENSE.md
  • change: add ShareButton
  • change: add ShareSvgIcon
  • change: add StateManagement component
  • change: add comment
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

thisistonydang/liveview-svelte-pwa was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 18 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit f1772b604625d6fb8ba62d1c87ca93e3f37feed1 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-5d04157a340d.