Skip to content
CAI
Software that uses CAICheck a score

freeCodeCamp/devdocs

50.1

Adequate · 22 September 2026

38.5k

lines of production code

Ruby

with JavaScript

5

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

DevDocs is a self-hosted, offline-capable documentation browser that aggregates and indexes technical reference materials for a wide variety of programming languages and frameworks. It provides a local server with a modern, responsive web interface featuring full-text search, keyboard navigation, and theme support. The system manages documentation downloads, updates, and caching via a CLI, ensuring users can access documentation without an internet connection.

How it got here

2013 — Initial project scaffolding and architecture

13 changes.

This period established the foundational structure of the DevDocs application, introducing the core Ruby backend, documentation engine, and comprehensive CLI tooling. It simultaneously modernized the frontend by migrating to ES modules, implementing CSS variables for theming, and adding offline support via service workers. The work also included setting up initial test coverage, Docker support, and styling for a wide array of new documentation sources.

2024–2026 — JavaScript modernization and feature expansion

14 changes.

The project undertook a comprehensive migration of its client-side codebase from CoffeeScript to modern ES modules with TypeScript type checking, significantly improving maintainability and type safety. This refactoring extended across core services, models, views, and templates, introducing behavioral updates such as localStorage persistence and enhanced search capabilities. Concurrently, new UI features for notifications and improved keyboard navigation were added, alongside the introduction of fish shell support for development tasks.

Features

Add fish shell support for DevDocs tasks

Users can now run DevDocs documentation tasks directly from the fish shell using the new \devdocs\ function, which wraps Thor commands (e.g., \devdocs generate\ becomes \thor docs:generate\). The update includes comprehensive shell completions for all documentation subcommands, options, and documentation slugs, along with a cached list of available documentation sources to speed up tab-completion.

fish · high confidence

Add page-specific stylesheets for dozens of new documentation sources

The documentation UI now includes dedicated SCSS stylesheets for a wide range of new frameworks, languages, and tools, ensuring their content renders with correct typography, layout, and semantic coloring. New styles have been added for Angular, AngularJS, Apache, Async, Bash, Bootstrap, CakePHP, Celery, Chef, Clojure, Codeception, CoffeeScript, Cordova, C++ Reference, Crystal, Cypress, D, D3.js, Dart, Dojo, Drupal, Elisp, Elixir, Ember, Erlang, Express, FastAPI, Fluture, Git, GitHub, GNU Make, Gnuplot, Go, Graphite, Groovy, GTK, Hapi, HAProxy, Haskell, Jasmine, Jekyll, Joi, jq, jQuery, Julia, Knockout, Kotlin, kubectl, Kubernetes, Laravel, Liquid, Lit, LÖVE, Lua, MapLibre GL JS, MariaDB, MDN, Meteor, MkDocs, Modernizr, Moment.js, Nginx, Node.js, npm, Nushell, Octave, OpenJDK, OpenLayers, OpenTofu, Perl, Phalcon, Phaser, PHP, PHPUnit, PostgreSQL, Pug, Pygame, Python, Qt, RabbitMQ, Ramda, RDoc, React, React Native, ReactiveX, Redis, RethinkDB, RFC, Ruby/RDoc, Rust, RxJS, and more. These files define specific visual treatments—such as callout boxes, code labels, navigation structures, and responsive adjustments—tailored to the unique HTML structures generated by each documentation scraper.

assets/stylesheets/pages · high confidence

Initial release of the DevDocs application shell and documentation engine

This change introduces the core application structure for DevDocs, including the Sinatra-based server (lib/app.rb) and the documentation management system (lib/docs.rb). For users, this establishes the foundation for browsing and searching technical documentation, featuring HTTPS enforcement, Content Security Policy configuration, asset pipeline integration for styles and scripts, and a system for managing documentation aliases (e.g., mapping 'rails' to 'ror'). It also sets up the infrastructure for serving static assets, handling redirects, and generating documentation manifests.

lib · high confidence

Initial repository structure and Docker support for DevDocs

The project is now initialized with a complete set of configuration files, including Dockerfiles for standard and Alpine Linux environments, a Procfile for Heroku deployment, and a .ruby-version file specifying Ruby 4.0.6. The application requires Node.js 26.8.2 and uses a TypeScript configuration (tsconfig.json) to type-check JavaScript assets. Documentation is managed via a new README.md, and the legacy wiki Home.md has been removed.

(repo-wide) · high confidence

Introduction of offline support via service worker and import maps

The application now supports offline usage by replacing the legacy AppCache with a service worker that caches core assets and dynamically stores documentation index files as they are fetched. The view templates have been updated to load JavaScript modules via an import map, enabling modern module loading while providing a fallback for older browsers. Additionally, the layout includes a noscript message for users with JavaScript disabled and integrates a web app manifest for mobile installation.

views · high confidence

New Thor CLI tasks for assets, console, docs, sprites, tests, and updates

The application now includes a set of new Thor command-line tasks in lib/tasks to manage development and maintenance workflows. The \assets\ task allows compiling and cleaning static assets while keeping previous builds for safety. The \console\ task provides a Pry REPL with helpers to run tests or enter the Docs module. The \docs\ task expands documentation management with commands to list, generate, download, package, clean, and upload documentation, including support for versioned docs and rclone. The \sprites\ task automatically generates WebP icon spritesheets with dark-mode contrast fixes. The \test\ task simplifies running test suites (all, docs, app) and generating coverage reports. Finally, the \updates\ task checks for outdated documentation scrapers and can upload reports to GitHub issues.

lib/tasks · high confidence

New notification views for changelog, updates, and tips

Added new JavaScript view classes in the misc directory to handle transient UI notifications. The News view displays unread changelog entries, the Updates view lists new document releases (including disabled docs with active counterparts), and the Tip view shows one-time hints. These views extend the existing Notif base class, which manages stacking, auto-hiding, and dismissal, while the Notice view provides a persistent alert bar for status messages like disabled documentation.

assets/javascripts/views/misc · high confidence

Architecture

Refactored stylesheet architecture to use modular SCSS partials

The main application stylesheet has been restructured to replace the previous monolithic import style with explicit, on-demand imports of modular SCSS partials. This change decouples the styling logic, allowing components (such as the header, sidebar, and settings) and specific documentation pages (like Angular, Python, and Rust) to be included individually rather than loading all styles globally. This improves maintainability and potentially reduces the final CSS payload by only including styles for the features and documentation sets actually in use.

assets/stylesheets · high confidence

Behavioural changes

Add custom 404 and 500 error pages

The application now serves dedicated, styled error pages for 404 (Page not found) and 500 (Internal server error) responses. These static HTML files provide user-friendly messages and a link back to the home page, replacing any previous default or generic error handling behavior.

public · high confidence

App boot sequence and core services rewritten in modern JavaScript

The application's core JavaScript files (app, config, db, router, searcher, settings, shortcuts, update\_checker, serviceworker, offline\_backup) have been converted from CoffeeScript to modern ES modules with TypeScript type checking. This introduces several behavioral changes: settings are now stored in localStorage instead of cookies, the offline index cache uses IndexedDB instead of localStorage, and the app loads assets via an import map. The boot sequence now uses async/await for version migration, and the service worker is properly initialized with super() calls. Additionally, the app now supports loading the latest documentation versions by default, and icon spritesheets are generated as WebP.

assets/javascripts/app · high confidence

Base View class refactored to extend Events and enforce strict element binding

The base View class in the JavaScript views module has been rewritten to explicitly extend the Events class, ensuring proper inheritance of event handling capabilities. The constructor now strictly validates that the provided element is an HTMLElement before assignment, preventing runtime errors when invalid nodes are passed. Additionally, the view's lifecycle methods for managing element setup, class toggling, and child element resolution have been refined to support a more robust static configuration system, allowing subclasses to declare properties like tagName, className, and event bindings that are automatically applied to the view's root element.

assets/javascripts/views · high confidence

CoffeeScript views converted to JavaScript with TypeScript checks and new offline persistence options

The content view files (content, entry, offline, root, settings, static, and type pages) have been converted from CoffeeScript to JavaScript with TypeScript type checking (JSDoc). This migration includes several behavioral updates: the offline page now supports requesting persistent storage and reports when such requests are denied or blocked; the settings page exposes a new 'noDocSpecificIcon' preference to disable document-specific favicons; and the entry page now adds copy buttons to code blocks and handles MathML polyfilling. Additionally, scroll positions are now cached per history entry and restored on navigation, and the app skips rendering the offline page when the view is deactivated.

assets/javascripts/views/content · high confidence

Collections converted to typed JavaScript modules

The collection classes in the application (Collection, Docs, Entries, Types) have been converted from CoffeeScript to JavaScript and are now loaded as ES modules. This change introduces TypeScript type checking via JSDoc annotations, improving code reliability and maintainability for the data structures that manage models like Docs, Entries, and Types.

assets/javascripts/collections · high confidence

Documentation models converted to typed JavaScript with enhanced search aliasing

The documentation models (Doc, Entry, Type, Model) have been converted from CoffeeScript to typed JavaScript (ES modules with JSDoc). This change introduces a new search aliasing mechanism in the Entry model, where the \applyAliases\ method expands searchable strings with configured aliases (e.g., from \config.docs\_aliases\) to ensure that both the original name and its alias are found during search. The Doc model now manages entry and type resets more explicitly, and the Entry model's \addAlias\ method ensures that aliased document names remain searchable by preserving the original name in the text array.

assets/javascripts/models · high confidence

Introduction of dark theme and CSS variable-based styling

The global stylesheet has been refactored to use CSS custom properties (variables) instead of SASS variables, enabling a new dark theme alongside the existing light theme. This change introduces separate variable definitions for light and dark modes, allowing the UI to dynamically switch color schemes while maintaining consistent styling for components like boxes, notes, and external links. The base styles now support theme toggling via HTML classes, and the print stylesheet has been updated to ensure proper output regardless of the active theme.

assets/stylesheets/global · high confidence

Migrate page templates from CoffeeScript to JavaScript

The page templates (About, Help, News, Offline, Root, Settings, and Type) have been converted from CoffeeScript (.coffee) to JavaScript (.js), with the News template now using a .js.erb extension to handle server-side data injection. This migration includes adding TypeScript type annotations (via // @ts-check and JSDoc) to the templates and their corresponding declaration files (.d.ts), ensuring type safety for the rendered HTML strings and data structures used across the application's UI pages.

assets/javascripts/templates/pages · high confidence

Migrated JavaScript libraries from CoffeeScript to ES modules with TypeScript types

The core client-side libraries (ajax, events, favicon, page router, settings, and utilities) have been converted from CoffeeScript to modern ES modules with JSDoc type annotations. This migration introduces several behavioral changes: settings are now persisted in localStorage instead of cookies, requiring a one-time migration for existing users; the router disables the browser's automatic scroll restoration to prevent conflicts with the app's own scroll management; and the favicon system now supports an optional 'noDocSpecificIcon' setting to disable document-specific icons. Additionally, the ajax helper now uses Object.entries for parameter serialization, and the page router fixes history state ID bookkeeping to ensure correct back/forward navigation.

assets/javascripts/lib · high confidence

Migrated page view components from CoffeeScript to JavaScript

The page view components (BasePage, HiddenPage, JqueryPage, RdocPage, SqlitePage, and SupportTablesPage) have been converted from CoffeeScript to JavaScript. This migration includes adding TypeScript type annotations, updating import paths to use ES modules, and refining the code structure (such as using \requestAnimationFrame\ for syntax highlighting and fixing constructor inheritance). The functional behavior of these views remains the same, but the underlying implementation is now native JavaScript.

assets/javascripts/views/pages · high confidence

Migrated template rendering from CoffeeScript to typed JavaScript modules

The application's template system has been rewritten from CoffeeScript to JavaScript with TypeScript type checking. This change introduces a centralized template registry that dynamically maps template names to their implementations, allowing views to render content by name. The new structure includes dedicated modules for error handling, notices, notifications, sidebar navigation, and path breadcrumbs, improving maintainability and type safety while preserving the existing user-facing rendering behavior.

assets/javascripts/templates · high confidence

Migration to ES modules with import maps and stricter browser requirements

The application JavaScript has been refactored from a legacy script bundle into ES modules, with the entry point in application.js importing the app and tracking modules. To resolve module paths, the app now relies on an import map that pins modules to content-digested URLs, enabling immutable, individually cacheable assets. This architectural shift introduces a new browser baseline: browsers that support ES modules but lack import map support (such as older Safari versions) will no longer load the app; instead, unsupported.js detects this gap and displays a specific error message listing the supported browsers (Firefox, Chrome, Opera, Safari 16.4+, Edge 89+, iOS 16.4+). Additionally, a new debug.js module provides console-based timing instrumentation for the boot sequence and search operations, and tracking.js now loads analytics only after explicit user consent in production.

assets/javascripts · high confidence

Redesign of core UI components with CSS variables

The application's visual presentation has been updated with a new design system that replaces SASS variables with CSS custom properties (variables) for colors, spacing, and layout dimensions. This change introduces a new maximum content width for improved readability on large screens, refines the sidebar and header styling, and adds specific mobile layout overrides to ensure proper display on smaller devices. Users will see a refreshed interface with consistent theming and better responsive behavior.

assets/stylesheets/components · high confidence

Search view refactored to ES modules with TypeScript types and modernized event handling

The search interface components (search.js and search\_scope.js) have been converted from CoffeeScript to ES modules with JSDoc type annotations, improving maintainability and type safety. Key behavioral updates include using the modern KeyboardEvent.key property instead of the deprecated which property for key handling, and implementing scoped external search shortcuts (Google, Stack Overflow, DuckDuckGo) that respect the current search scope. The search scope feature now properly handles doc scoping via URL hash, allowing users to narrow searches to specific documents with tag-based UI feedback.

assets/javascripts/views/search · high confidence

The sidebar list views have been converted from CoffeeScript to TypeScript and restructured into modular components (ListFocus, ListFold, ListSelect, PaginatedList). This change introduces refined keyboard navigation behavior: pressing the left arrow key now collapses the currently focused row, while the right arrow key expands it. Additionally, the focus cursor now starts from the selected row when no specific focus is set, and moving focus past the end of a page automatically triggers pagination to load the next page. The paginated list implementation has also been updated to use \requestAnimationFrame\ for smoother focus transitions.

assets/javascripts/views/list · high confidence

The sidebar view components (DocList, DocPicker, EntryList, Results, Sidebar, SidebarHover, TypeList) have been converted from CoffeeScript to JavaScript and are now loaded as ES modules via an import map. This migration includes adding TypeScript type annotations (JSDoc) to the view classes, models, and collections, and refactoring the code to use modern JavaScript features such as optional chaining and requestAnimationFrame without fallbacks. The changes ensure stricter type checking and better maintainability for the sidebar's navigation, search results, and document picker interfaces.

assets/javascripts/views/layout, assets/javascripts/views/sidebar · high confidence

Test coverage

Initial test suite for backend app and frontend assets

Added a comprehensive test suite covering the Ruby backend application and the JavaScript frontend assets. The backend tests verify HTTP routing, HTTPS redirection, HSTS headers, static page rendering, and documentation URL handling. The frontend tests validate the module graph initialization, document caching and version migration logic, search ranking and hashing, keyboard shortcuts, and settings storage migration from cookies to localStorage.

test · high confidence

Dependencies

Updated vendor libraries: Prism.js, Raven.js, and added MathML polyfill

The vendored JavaScript libraries have been updated to newer versions: Prism.js is upgraded to 1.30.0 (supporting syntax highlighting for many languages including Bash, C, C\#, C++, CMake, Dart, Diff, Django, DOT, Elixir, Erlang, GDScript, Go, Groovy, Java, JSON, Julia, Kotlin, LaTeX, Lua, Markdown, MATLAB, Nginx, Nim, Nix, OCaml, Perl, PHP, Python, QML, R, JSX, Ruby, Rust, SCSS, Scala, Shell-session, SQL, TCL, TypeScript, YAML, and Zig), and Raven.js is updated to 3.20.1 for improved JavaScript error tracking. Additionally, a new MathML polyfill (mathml.js) has been added to detect MathML support and provide fallbacks when needed.

assets/javascripts/vendor · high confidence

Upgrade to Ruby 4.0.6, Rails 8.1, and TypeScript 7

The application's dependency stack has been significantly updated. The Ruby runtime is upgraded to version 4.0.6, and the core framework dependency has moved to ActiveSupport 8.1.3 (part of the Rails 8.1 suite). On the frontend, the project now uses TypeScript 7.0.2 for type-checking JavaScript assets. Other notable dependency updates include Nokogiri 1.19.2, Rack 3.2.6, and Puma 8.0.2.

(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

Score

  • CAI 60 → 50 (-9.9)
  • Rubric changed (rubric-2026.08.19 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 62 → 60 (-2.2)
  • Architecture 100 → 43 (-56.9)
  • Maturity 65 → 62 (-3.0)
  • Readiness 54 → 71 (+16.7)
  • Security 73 → 71 (-2.4)
  • Accessibility 62 → 49 (-12.2)

Resolved (62)

  • Change coupling clique: settings.js, settings_tmpl.js, settings_page.js (assets/javascripts/app/settings.js)
  • Change coupling: license.js ↔ about_tmpl.js (assets/javascripts/lib/license.js)
  • Coverage not included — suite not readable by the collector
  • Dependency hygiene not measured — dependency manifest found but not parsed for hygiene
  • Duplicated block (10 lines × 2) (lib/docs/filters/bootstrap/entries_v3.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/cakephp/clean_html.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/electron/clean_html.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/flow/clean_html.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/scikit_image/entries.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/terraform/clean_html.rb)
  • Duplicated block (10 lines × 4) (lib/docs/filters/eigen3/clean_html.rb)
  • Duplicated block (11 lines × 2) (lib/docs/filters/bottle/entries.rb)
  • Duplicated block (11 lines × 2) (lib/docs/filters/prettier/clean_html.rb)
  • Duplicated block (12 lines × 2) (lib/docs/filters/cakephp/clean_html.rb)
  • Duplicated block (12 lines × 2) (lib/docs/filters/godot/clean_html_v2.rb)
  • Duplicated block (12 lines × 2) (lib/docs/filters/laravel/clean_html.rb)
  • Duplicated block (12 lines × 2) (lib/docs/filters/scala/entries_v2.rb)
  • Duplicated block (14 lines × 2) (lib/docs/filters/angular/clean_html.rb)
  • Duplicated block (14 lines × 2) (lib/docs/filters/bootstrap/clean_html_v3.rb)
  • Duplicated block (14 lines × 2) (lib/docs/filters/prettier/clean_html.rb)
  • …and 42 more

New (123)

  • App.initErrorTracking (cognitive 22) (assets/javascripts/app/app.js)
  • App.migrateDocs (cognitive 19) (assets/javascripts/app/app.js)
  • Change coupling: settings_tmpl.js ↔ settings_page.js (assets/javascripts/templates/pages/settings_tmpl.js)
  • ClassTooLong: DB (assets/javascripts/app/db.js)
  • DB.onUpgradeNeeded (cognitive 16) (assets/javascripts/app/db.js)
  • DocPicker.onDOMFocus (cognitive 31) (assets/javascripts/views/sidebar/doc_picker.js)
  • Documentation: no installation or build instructions (README.md)
  • Duplicated block (10 lines × 2) (lib/docs/filters/bootstrap/entries_v3.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/cakephp/clean_html.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/electron/clean_html.rb)
  • Duplicated block (10 lines × 2) (lib/docs/filters/laravel/clean_html.rb)
  • Duplicated block (10 lines × 3) (lib/docs/filters/man/clean_html.rb)
  • Duplicated block (10 lines × 4) (lib/docs/filters/flask/entries.rb)
  • Duplicated block (11 lines × 2) (lib/docs/filters/bottle/entries.rb)
  • Duplicated block (11 lines × 2) (lib/docs/filters/cakephp/clean_html.rb)
  • Duplicated block (11 lines × 2) (lib/docs/filters/hapi/clean_html.rb)
  • Duplicated block (13 lines × 2) (lib/docs/filters/scala/entries_v2.rb)
  • Duplicated block (13–15 lines × 2) (lib/docs/filters/prettier/clean_html.rb)
  • Duplicated block (15 lines × 2) (lib/docs/filters/flow/clean_html.rb)
  • Duplicated block (15 lines × 3) (lib/docs/filters/angular/clean_html.rb)
  • …and 103 more

Changes since last survey

  • 248 commits — 235 feature/other, 13 fixes

By area

  • lib/docs — 83 commits
  • assets/javascripts — 80 commits
  • (repo) — 23 commits
  • docs/file-scrapers.md — 20 commits
  • (root) — 19 commits
  • .github/workflows — 3 commits
  • assets/stylesheets — 3 commits
  • docs/maintainers.md — 2 commits
  • fish/completions — 2 commits
  • fish/functions — 2 commits
  • public/icons — 2 commits
  • test/files — 2 commits
  • .devcontainer/devcontainer.json — 1 commit
  • docs/adding-docs.md — 1 commit
  • docs/filter-reference.md — 1 commit
  • lib/app.rb — 1 commit
  • lib/tasks — 1 commit
  • test/assets — 1 commit
  • views/service-worker.js.erb — 1 commit

Notable commits

  • fix: Fix crash on documentations without a type
  • fix: Fix defects in the offline persistence option
  • fix: Fix history state ID bookkeeping in page.js
  • fix: Fix scoped external search shortcuts
  • fix: Fix silent failures of Alt+O / Alt+C shortcuts
  • fix: Merge branch 'main' into fix/alt-shortcuts-silent-failure
  • fix: Merge pull request #2721 from ryann-g/fix/alt-shortcuts-silent-failure
  • fix: Merge pull request #2725 from olitreadwell/chore/fix-docs-typos-and-links
  • fix: Merge pull request #2729 from dajiaohuang/fix/2728-scoped-external-search
  • fix: Merge pull request #2739 from freeCodeCamp/fix/client-storage
  • fix: fix: clean Deno scraper output
  • fix: haskell: fix the attribution links of the libraries
  • fix: polars: fix get_latest_version
  • change: Add Development Container configuration
  • change: Add Valibot documentation (1.4.2)
  • change: Add a TypeScript 7 typecheck for the JavaScript assets
  • change: Add a preference to use the latest version of a documentation
  • change: Add a scraper base for the MDN documentations built from git
  • change: Add docs:outdated task delegating to updates:check
  • change: Add export and import of offline documentation
  • …and 228 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

freeCodeCamp/devdocs 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 22 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 6033032b848e5dbb7a21a0f735471445d46254a7 — 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-be726e82e277.