Skip to content
CAI
Software that uses CAICheck a score

gskinnerTeam/flutter-folio

46.3

Weak · 5 August 2026

12.3k

lines of production code

Dart

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

Flutter Folio is a cross-platform scrapbooking application that enables users to create, edit, and manage digital folios and scrapboards. The system supports rich media interactions, including image and file selection, on mobile and desktop platforms, while enforcing read-only or restricted editing modes on mobile devices. It features a responsive UI that adapts to touch or mouse input, manages window states, and persists user data through Firebase and local storage.

Features

Add Flutter Driver-based performance benchmarks

A new benchmarking suite has been introduced to measure the app's performance using Flutter Driver. The changes include \app.dart\ which sets up the application with a mock Firebase service to isolate performance metrics, and \app\_benchmark.dart\ which defines automated tests for scrolling, navigation, and UI interactions. These tests capture timeline data to help track performance regressions or improvements over time.

benchmark · high confidence

Add debug-mode log viewer to splash screen

The splash page now includes a log viewer that can be accessed by tapping the screen in debug mode. This allows developers to view application logs directly from the splash screen, improving debugging capabilities during development.

lib/views · high confidence

Add native window title management and Linux title bar support

The native window utilities now support setting the application title via a new setTitle method, allowing the app to dynamically update the window title. Additionally, Linux platforms are now handled in the title bar wrapping logic, introducing a LinuxTitleBar component for native title bars on that platform, whereas previously Linux was effectively ignored or returned an empty container.

_lib/\_utils/native\_window\utils · high confidence

Introduces reusable UI components and refactors existing widgets for better consistency and functionality

Adds new reusable widgets: a Toaster for displaying brief notifications, a UiText for selectable text regions, and a StyledLoadSpinner for loading states. Refactors existing components to use a shared DecoratedContainer for consistent styling, updates image asset paths to the new 'assets/images/' structure, and migrates context menus to use an external package. Additionally, adds maxLength validation to text inputs, enables autofocus for specific fields, and improves touch-mode support for scrollbars and card headers.

_lib/styled\widgets · medium confidence

Redesigned authentication page with responsive layout and device previews

The authentication experience has been refactored to include a responsive layout that adapts to screen size. On wider screens, the auth form is displayed alongside device mockups (mobile, tablet, desktop) that scale on hover. On narrower or portrait-oriented screens, the layout switches to a vertical stack, hiding the device previews when space is limited. The form itself has been extracted into a dedicated \AuthForm\ component, improving code organization and enabling the new flexible layout.

_lib/views/auth\page · high confidence

Removals

Removed experimental spike code and modernized widget constructors

Removed multiple experimental spike files including Firebase, context menu, router, state management, and UI prototypes from the lib/\_spikes directory. Additionally, updated widget constructors in the remaining spike files to use const constructors and const constructors for child widgets, aligning with modern Flutter practices.

_lib/\spikes · high confidence

Removed legacy popover implementation

The legacy popover system has been removed from the application. This includes the deletion of the PopOverController widget, the PopOverRegion widget, and the associated notification classes (ShowPopOverNotification, SizePopoverNotification, ClosePopoverNotification). Users will no longer see popovers rendered via this specific internal widget hierarchy.

_lib/\widgets/popover · high confidence

Behavioural changes

3 commits (0 fixes) modifying source-assets

A change to existing behaviour in source-assets — 3 commits, 3 files.

source-assets · medium confidence · unverified

Added iOS camera, microphone, and photo library usage descriptions

The iOS app now includes permission descriptions for accessing the camera, microphone, and photo library. These entries in Info.plist explain why the app needs these permissions, specifically noting they are used to pick images and capture audio for 'scrapboards'.

ios/Runner · high confidence

Allow multiple instances of the application to run simultaneously

On Linux, the application is now launched with the G\_APPLICATION\_NON\_UNIQUE flag. This change allows multiple instances of the app to run concurrently, rather than restricting the application to a single running instance.

linux · high confidence

Android app configuration and build updates

The Android module now includes a new MainActivity class and declares storage and camera permissions in the manifest, enabling image picker functionality on mobile devices. Additionally, the project's Gradle wrapper has been updated from version 5.6.2 to 6.3.

android · high confidence

Editor page refactoring and mobile editing restrictions

The editor page has been reorganized, moving files from the 'scrapboard\_editor\_page' directory to 'editor\_page' and renaming the main widget from 'BookEditorPage' to 'EditorPage'. A new 'EmptyEditorView' is displayed when no pages are present. Crucially, the app now disables editing capabilities for mobile users and in read-only modes, replacing the previous logic that allowed editing on phones. Additionally, text boxes now display a 'Type something...' prompt when empty, and the debounce timer for text updates has been reduced from 500ms to 150ms.

_lib/views/editor\page · high confidence

File read operations now return null for missing or unreadable files

The \read\ method in the file utility classes (\IoFileWriter\ and \WebFileWriter\) now returns a nullable string (\String?\) instead of a non-null \String\. This change allows the application to distinguish between a file not existing or being empty (returning \null\) and successfully reading content. In the IO implementation, this prevents errors when files are missing on first launch, and in the web implementation, it safely handles cases where shared preferences may not yet be initialized or contain the key.

_lib/\_utils/universal\file · high confidence

Firebase service methods now return nullable types to handle missing data

The Firebase service layer has been updated to return nullable types (e.g., \Future\<AppUser?\>\, \Future\<Map\<String, dynamic\>?\) for all read operations, including \getUser\, \getBook\, \getAllBooks\, \getPage\, \getAllPages\, \getDoc\, \getCollection\, and their stream equivalents. This change ensures that null is returned when data is not found or an error occurs, rather than throwing an exception or returning an empty structure. Additionally, the \signIn\ method now returns \null\ on failure, and the \isSignedIn\ state is explicitly tracked via \\_isSignedIn\ to reflect the current authentication status accurately.

lib/services/firebase · high confidence

Global error logging and structured utility classes

The application now initializes a global error logger in the entry point to capture all unhandled exceptions, including those from native extensions. Utility classes for timing (cooldown, debouncer, throttler) have been reorganized into a new 'timed' directory, and the codebase has been updated to use nullable types for timers and callbacks to improve null safety. Additionally, the theme system has been refactored to support visual density adjustments based on touch mode, and the app scaffold now uses an external package for anchored popups and a custom decorated container for window borders.

lib · medium confidence

Improved dialog layout and text handling

Dialogs now use a custom UiText widget for better text selection and styling control. The delete dialog's button layout has been adjusted to support right-to-left text direction on Windows, and the base dialog widget now allows optional background color and padding to be customized.

_lib/styled\widgets/dialogs · high confidence

Migrate animated widgets to null safety and modernize constructors

The animated widgets in lib/\_widgets/animated have been migrated to null safety, updating constructors to use the 'required' keyword and 'Key?' for keys. Several optional parameters (such as 'begin' and 'curve') are now explicitly nullable (e.g., 'Offset?', 'Curve?'). Additionally, the 'AutoFade' widget now safely checks for 'mounted' status before starting its animation, and 'OpeningContainer' uses null-aware operators for offset access.

_lib/\widgets/animated · high confidence

Migrate desktop window management to desktop\_window and add image saving capability

The app now supports saving images to disk on desktop platforms, implemented via the new SaveImageToDiskCommand. Window management has been migrated from the window\_size package to desktop\_window, updating how window sizes and frames are saved and restored. Additionally, the menu bar refresh logic has been disabled (commented out) in the RefreshMenuBarCommand, and logging has been standardized to use a dedicated logger instead of print statements across multiple commands.

lib/commands/app · high confidence

Migrated book cover components to home page and modernized widget patterns

The book cover components (book\_cover.dart, book\_cover\_large.dart, book\_cover\_small.dart) have been moved from the 'books\_home' directory to 'home\_page'. The widgets were refactored from StatefulWidget to StatelessWidget, and the code was updated to use const constructors and const arguments for performance and correctness. Additionally, the large cover view now uses LayoutBuilder for responsive sizing, replaces manual text spans with a UiText widget, and integrates a context menu for the 'View Folio' button.

_lib/views/home\_page/book\cover · high confidence

Redesign title bar with touch mode toggle and new profile button

The app title bar now includes a toggle for 'Touch Mode', which adjusts the visual density and hit area of the button to suit finger or mouse interaction. The previous profile button implementation has been replaced with a new 'RoundedProfileBtn' component that supports both hover/click popups and bottom sheets on mobile. The title bar layout has been consolidated into a single adaptive widget that handles both desktop and mobile states, removing the separate desktop and mobile specific files.

_lib/views/app\_title\bar · high confidence

Refactor button padding and touch-mode handling

The button widgets have been updated to remove the automatic padding adjustments that were previously applied based on a global 'touch mode' setting. Instead, the RawBtn and its derivatives now rely on Flutter's built-in visual density for sizing, with an explicit 'ignoreDensity' option available for specific cases. Additionally, the share button's popup trigger has been migrated from a custom PopOverRegion to the AnchoredPopups package.

_lib/styled\widgets/buttons · high confidence

Refactor context menus to use external package

The internal context menu widgets have been refactored to use an external \context\_menus\ package. This replaces the previous internal implementation (e.g., \BaseContextMenu\, \ContextMenuBtn\, \ContextMenuCard\) with a new \ContextMenuOverlay\ and \ContextMenuButtonConfig\-based structure. Users will see updated styling for context menus, including support for icons and hover states on menu items, and the removal of redundant internal classes in favor of the external library's components.

_lib/styled\_widgets/context\menus · high confidence

Refactor editor page menu to support touch mode and modernize widget structure

The DraggablePagesMenu and DraggablePageTitleBtn components have been moved to the editor\_page directory and updated to adapt to the user's interaction mode. The menu now dynamically adjusts tile heights (56px for touch mode, 42px for mouse mode) to improve touch targets. The title button now wraps its content in a MouseRegion to provide appropriate cursor feedback. Additionally, the context menu implementation has been refactored to use a structured button configuration rather than simple labels and actions, and the selected page outline now uses a dedicated DecoratedContainer widget.

_lib/views/editor\_page/draggable\_page\menu · high confidence

Refactor image picking to return structured PickedImage objects

The image picking command now returns a new PickedImage class containing either a file path or an Asset, replacing the previous behavior of returning a list of raw strings. On desktop and web, it uses the file\_selector package to get file paths. On mobile, it distinguishes between camera and gallery selection, returning Asset objects from multi\_image\_picker for gallery picks and paths from image\_picker for camera shots, providing a consistent interface for callers.

lib/commands · medium confidence

Refactor model state management and data structures

The app's internal state management has been refactored to improve null safety and data handling. In the app model, window position is now tracked as a simple Size rather than a full Rect, and the save/load methods have been updated to handle missing files gracefully. In the books model, all list and object properties have been made nullable to prevent null-reference errors, and list mutations now use a safe copy helper to avoid modifying shared references. These changes make the application more robust against missing data and improve type safety.

lib/models · medium confidence

Refactor routing logic and update view imports

The routing layer was updated to use nullable types for route parameters and replaced debug print statements with a centralized log function. Additionally, the router now imports the new HomePage and EditorPage components, replacing the previous BooksHomePage and BookEditorPage imports, reflecting a structural change in the application's navigation hierarchy.

lib/routing · high confidence

Refactor scrap pile picker to use external context menu package and modernize widget structure

The scrap pile picker now uses an external \context\_menus\ package for handling context menus, replacing the previous internal \context\_menu\_overlay\ and \ContextMenuRegion\ implementation. This change updates the widget hierarchy to use \SelectableScrapBtn\ and \GridBtn\ (now a StatefulWidget with mouse hover tracking), and switches to \DecoratedContainer\ for selection indicators. Additionally, the title bar and view components are updated to use \UiText\ for better text selection support, and the code is refactored to use null-safety and modern Dart/Flutter patterns (e.g., \required\ parameters, \const\ constructors).

_lib/views/scrap\_pile\picker · medium confidence

Refactor scrapboard editor layout and enforce minimum box dimensions

The scrapboard editor's file structure has been reorganized, moving components from lib/views/scrapboard\_editor\_page to lib/views/editor\_page/scrapboard. This refactor includes updating the minimum and maximum dimensions for editable boxes, increasing the upper limit from 1200 to 2000 pixels, and adjusting the default board size constants. Additionally, the codebase has been updated to use null-safe types, replacing @required annotations with the required keyword, and simplifying widget constructions by using a custom DecoratedContainer.

_lib/views/editor\page/scrapboard · high confidence

Refactor widgets to use new DecoratedContainer and update nullable types

The widget library was updated to use a new \DecoratedContainer\ component, which consolidates border, shadow, and pointer-interaction logic, replacing previous patterns in \RoundedBorder\ and \GradientContainer\. Additionally, the codebase was migrated to null safety, converting many widget properties from nullable to required or explicitly nullable types, and removed the \SingleEmojiPaint\ widget.

_lib/\widgets · high confidence

Refactored utility classes and added a new logger

The utility layer in lib/\_utils was refactored to improve null-safety and modernize the codebase. A new logger was introduced to centralize error and debug output, while the old utils.dart file was removed. Several utility classes were updated to handle nullable types more safely, including context\_utils, data\_utils, file\_utils, input\_utils, and string\_utils. Device detection was restructured into a new DeviceOS and DeviceScreen classes for better form factor and platform identification. Keyboard interaction logic was updated to use modern Set-based checks and improved multi-select behavior.

_lib/\utils · high confidence

Refinements to Linux, macOS, and Windows title bar wrappers

The Linux title bar components now use SVG icons for window controls, with the \flutter\_svg\ package imported and the SVG string constants uncommented and active. Additionally, the \WindowButtonColors\ and \VoidCallback\ parameters in the Linux title bar buttons are now marked as \required\, and the \Key\ parameters are made nullable (\Key?\). On macOS, the title bar state now uses \late\ for the height future and improves the \FutureBuilder\ logic to handle the initial state more robustly. On Windows, the title bar's alignment is changed from \Alignment.centerRight\ to \Alignment.topRight\ to better position the window control buttons.

_lib/\_utils/native\_window\_utils/titlebar\wrappers · medium confidence

Removed obsolete book and editor views

Deleted several unused or legacy UI components: the book cover notification classes, the mobile covers flow list, the sortable book list with its header and row widgets, the bottom sheet for creating a new folio, and the empty-state view for the scrapboard editor. These removals streamline the codebase by eliminating dead code and unused views.

_lib/views/books\_home, lib/views/scrapboard\_editor\page · high confidence

Replace shortid with UUID for generating unique identifiers

The books commands now use the \uuid\ package to generate document IDs instead of the \shortid\ package. This change updates the \CreateFolioCommand\, \CreatePageCommand\, \CreatePlacedScrapCommand\, and \UploadImageScrapsCommand\ to use \Uuid().v1()\ for generating unique identifiers, ensuring consistent ID generation across the application.

lib/commands/books · high confidence

Rework user profile editing with improved form controls and layout

The user profile editing interface has been refactored into a new 'UserProfileForm' component, introducing several UX improvements. The form now includes auto-focus on the first name input and enforces a 30-character limit on first and last name fields. The layout has been adjusted to include a version number display and a more responsive image upload button. Additionally, the logout button has been assigned a specific key for testing purposes.

_lib/views/user\_profile\card · high confidence

Reworked editor page panels with new collapsible structure and improved UI

The editor page panels have been reorganized into a new collapsible structure, with the info and pages panels now supporting collapsible states. The content picker panels have been updated to use a new anchored popups package for better context menu handling, and the scrap popup editor panels have been refactored to use a new DecoratedContainer widget for consistent styling. Additionally, the panels now support visual density for touch mode, and the UI has been updated to use the new UiText component for easier selectable text control.

_lib/views/editor\page/panels · high confidence

Reworked home page layout and navigation for mobile and desktop

The home page now uses distinct navigation components for different screen sizes: a bottom-aligned tab menu on small screens and a top-aligned toggle menu on larger screens. The empty state now displays a more descriptive welcome message and a direct call-to-action to create a new Folio. Additionally, the codebase was reorganized by moving home page views into a dedicated \home\_page\ directory, and the mobile-specific flow list was extracted into its own file.

_lib/views/home\page · high confidence

Update animation and state mixins for null safety

The animation and state mixins in lib/\_widgets/mixins have been updated to support null safety. This includes changing uninitialized fields to use the 'late' keyword and ensuring constructor arguments are properly typed. Additionally, the 'load' method in LoadingStateMixin now accepts a function type parameter instead of a nullable Future, improving type safety.

_lib/\widgets/mixins · medium confidence

Update snap package definition for Flutter Folio

The snap package definition has been updated to reflect the application's new identity as 'Flutter Folio' (previously 'flutter-travel-app'). This includes renaming the app, updating the version to 1.1.4, and modifying the desktop entry to display the correct name and icon. Additionally, the 'home' plug has been added to the snap configuration, granting the application access to the user's home directory on Linux.

snap · medium confidence

Update web app title and description

The web application's title and manifest metadata have been updated. The browser tab title and the PWA manifest name/short name are now "Flutter Folio" (previously "flutter\_folio"). Additionally, the web app description has been expanded to explain that Flutter Folio is a scrapbooking app designed to showcase Flutter’s cross-platform capabilities.

web · high confidence

Updated Linux plugin registrations to reflect Flutter 2.10 changes

The Linux build configuration has been updated to register the new plugin set required by Flutter 2.10. Specifically, the \file\_chooser\ and \menubar\ plugins have been replaced with \bitsdojo\_window\_linux\, \desktop\_window\, and \file\_selector\_linux\. This change aligns the Linux platform with the latest Flutter framework updates and ensures correct plugin initialization on Linux.

linux/flutter · high confidence

Updated data models to use nullable types and default values

The \AppUser\ and \ScrapBookData\ data models have been updated to use nullable types (e.g., \String?\) and default values (e.g., \@Default("")\) for optional fields. This change, driven by a \freezed\ upgrade, improves null-safety handling in the \lib/data\ layer, ensuring that missing or null JSON values are gracefully handled with sensible defaults rather than causing runtime errors.

lib/data · high confidence

Updated iOS build manifest to fix build issues

The iOS build system's internal manifest file has been updated to resolve build failures. This change updates the build graph and task definitions for the Runner target, ensuring that the iOS project compiles and links correctly.

ios/build · high confidence

Updated macOS app configuration and security settings

The macOS app window default size has been increased to 1280x720 pixels. The app is now categorized as a 'lifestyle' app in the Mac App Store. Additionally, the release build entitlements have been tightened by removing the 'allow-jit' and 'network.server' permissions, while retaining user-selected file read access and network client access.

macos/Runner · high confidence

Updated macOS build configuration and plugin dependencies

The macOS build target has been raised from 10.11 to 11.1, requiring macOS 11.1 or later. The project file was updated to replace the \file\_chooser\ and \menubar\ plugins with \desktop\_window\ and \file\_selector\_macos\, and the bundle identifier was set to \com.gskinner.flutterFolio\.

macos/Runner.xcodeproj · medium confidence

Updated macOS plugin registrations for window and file selection

The macOS Flutter plugin registry has been updated to reflect changes in the underlying packages. The 'window\_size' plugin has been replaced with 'desktop\_window', and the 'file\_chooser' plugin has been replaced with 'file\_selector\_macos'. Additionally, the 'menubar' plugin has been removed from the registration list.

macos/Flutter, windows · medium confidence

iOS build configuration updated with CocoaPods integration and new database URL

The iOS project configuration has been updated to integrate CocoaPods, adding build phases to check and embed Pods frameworks, and including the Pods group and framework references in the project structure. Additionally, a new DATABASE\_URL key has been added to GoogleService-Info.plist, and the bundle identifier has been changed to com.gskinner.flutterFolio.

ios/Runner.xcodeproj · medium confidence

Dependencies

Updated Flutter and platform dependencies

The project has been updated to support Flutter 2.10 and the Null Safety (NNBD) language version, requiring a minimum Android SDK 19 and iOS 10.3. Key library upgrades include Firebase (6.33.0 → 7.3.0 on iOS, 7.3.0 → 8.0.0 on macOS), \firedart\ (git → v0.9.0), and \window\_size\ (git → \desktop\_window\ package). Additionally, the \menubar\ and \file\_chooser\ plugins were replaced with \desktop\_window\ and \file\_selector\_macos\ respectively.

(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 46 → 46 (+0.5)
  • Rubric changed (rubric-2026.08.18 → rubric-2026.08.19) — scores are not directly comparable.

Lenses

  • Code Health 98 → 98 (+0.0)
  • Architecture 100 → 100 (+0.0)
  • Maturity 34 → 34 (+0.0)
  • Readiness 24 → 24 (+0.0)
  • Security 85 → 88 (+3.3)
  • Domain Modelling 100 → 100 (+0.0)

Resolved (2)

  • Secret: gcp-api-key (web/index.html)
  • The 'Performance profiling' section gives only a one-line install command (pub global activate benchmarkhor) with no explanation of what benchmarks run or how to interpret the output. (benchmark/README.md)

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

Survey your own repository

gskinnerTeam/flutter-folio 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 5 August 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit be0cfa2fa54a234d0e91beebda0f88f3c485a850 — the exact code this score is about.
  • Scored under rubric-2026.08.19 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer latest.