A desktop app for artists to practice drawing using spaced repetition (FSRS). Crop a reference image, draw it in timed phases, self-rate your skill/difficulty, and the FSRS algorithm schedules which subject to practice next.
# Clone or download the repository
# Install dependencies
pip install -r requirements.txt
# Run
python main.pyThe app stores its data in UserData/ (database, settings, rounds, checkpoints, custom decks/sessions). The library scans Data/subjects/ plus any linked external folders you configure in Settings.
I recommend adding large libaries or archives of images to the custom folders menu in settings.
The app has 5 study modes, selectable from the session type dropdown on the main page.
The classic spaced-repetition drawing practice. Each round: crop a reference image β timed drawing β mid-round mental correction β second timed drawing β final self-rating. FSRS picks the next subject based on due cards.
Flow: Crop β Draw Phase 1 (timed) β Mid-Rate (overlay + skill/difficulty) β Draw Phase 2 (timed) β Final Rate β next round or break
In phase 0, you crop an image to the region you're interested in drawing from reference. This affects the region you see in the draw phase. you can also insert a reference point to make sure you got the position right. The reference point can be moved with the reference point tool.

In this phase, you draw out the gesture and some basic forms. You can use the various tools and tool settings in this mode to help you draw. I don't recommend making any layers in this mode, however, for simplicity.
This is intended to be a "first draft" of your drawing where you lay the groundwork for the final draft. This phase is timed.

In this phase, you rate how well you did and how difficult it was. you can also overlay the original to see how close you got. Be honest. Don't skip this phase. Be mindful of your mistakes so you can correct them during the second draw phase. The information you put here will be saved for later use in the statistics page.

In this phase, you make corrections based on what you noticed in the mid-rate phase and finish the drawing. In phase 2, the first phase's version is saved as a semi-transparent layer underneath the final layer. Layers can be managed in the floating "layer" window. This phase is timed.

This phase is the same as mid-rate, only it includes a final "notes" box where you can type any notes for your future self about the piece. It also has a button to progress to the next round, saving the image.

Other modes have altered versions of these phases.
These are neuroscience-based tweaks that allow you to do a round a little differently. You can adjust how often they appear in the settings menu.
- Optional vertical flip modifier (configurable random chance)
- Optional blind draw modifier (canvas hidden, cursor visible)
- Optional tracing mode (adds reference layer at 20% opacity in Phase 2)
- 30-minute session blocks with 5-minute breaks (configurable)
Three-tier progressive Gaussian blur unblur. Reference starts fully blurred and progressively sharpens as you draw β stroke by stroke β revealing the image in real-time. Each draw phase reveals more of the image as you draw.
Flow: Crop β Preparing Blur (background precomputation) β Gesture Drawing (blurβmedium) β Blur Review β Form Drawing (mediumβslight) β Mid-Rate β Final Drawing (slightβoriginal) β Final Rate
- Three configurable blur radii: Very, Medium, Slight (must be strictly descending)
- Customizable falloff curve for the reveal gradient (cubic-bezier editor)
- Configurable unblur padding (reveal radius beyond brush stroke)
- Gesture/Form/Final phase durations derived from the gesture base time
Panel-by-panel manga study on a rectangular, full-resolution canvas. Study entire manga chapters page by page with persistent per-page completion tracking. Manga have to be downloaded from another source . I recommend Suwayomi, personally.
- Chapter folders have to be sorted alphabetically. I use PowerRename to add leading zeroes to chapter numbers occasionally to fix sorting problems with incorrect sorting.
You can import manga into the manga picker and set a custom thumbnail. The intention behind manga mode is to let you have fun by drawing your favorite manga! Manga has to come from an external source, of course.
Flow: MangaPicker (select series/chapter/pages) β Crop (full-resolution, unrestricted aspect) β Draw Phase 1 β Mid-Rate β Draw Phase 2 β Final Rate β next page
Same as regular draw mode. crop a panel you want and add a reference point.

In manga mode's draw phase, the cropped region you selected becomes a reference layer under the main drawing. Reference layers can't be drawn on. The full page is also a layer below.
I recommend hiding the references once you get a mental image of them, unless you're delibreately doing a tracing run.

- 4-layer canvas: Full Page (reference), Cropped Panel (reference), Drawing, Reference Point (protected, move-only)
- Canvas resizes to cropped panel dimensions (up to 4096px or configurable max)
- Movable crop bounds guides on canvas + reference pane, with toggle and settings
- Per-page completion tracking with green checkmark dots and progress bars
- Manga CRUD: add folders from linked roots, rename, change thumbnail, refresh
Open-ended, untimed drawing from book pages (PDF files or image folders). No FSRS scheduling β just browse pages and draw at your own pace with versioned, auto-saved drawings.
Flow: BookPicker (select book/page) β Drawing (untimed, all tools) β page navigation (prev/next/scrubbing) β auto-save β exit
- PDF support via QPdfDocument with page caching
- Per-page versioned drawing manifests (v2) with atomic save and preview images
- Auto-save every 60 seconds
- Page scrubbing: drag a scrollbar to preview pages; current page commits on release
- Per-page drawing count tracking
- Warm paper background (#f4f0e6) for a natural drawing feel
Manually curate a list of images for a focused practice session. Drag images into a custom order and choose between FSRS scheduling (picks the most-due subject among your chosen images) or strict panel order.
Flow: CustomSessionPicker (browse + select images, drag-reorder) β Start β same round flow as Standard mode, but no random modifiers, no block budget, no breaks
- ImageBrowser with multi-select, name/date sorting, folder/tag/deck filtering
- Drag-reordered chosen image list
- Preset manager: Save/Load/Delete named custom sessions
- Study order: "FSRS (dynamic, constrained to chosen images)" or "Panel (strict order)"
The default view and heart of the app. Three states:
- Idle Page: Shows paused sessions panel, session type combo (Normal/Blur/Custom/Manga/Book), mode-specific configuration UI, subject count status, and Start Session button
- Crop Page: Source image with draggable crop box, reference point placement, skip/hide image buttons
- Draw Page: PhaseBar at top, ReferencePane on left, DrawingCanvas on right, Toolbar, LayerPanel, CursorOverlay, budget label
Grid of completed round cards. Sort by date, skill, difficulty, or subject. Filter by folder, tags (AND/OR), session, or custom deck. Multi-select delete. Cards show final/mid drawing swap on hover, stats, tags.

Grid of session history cards with thumbnails, mode, status, round count, and dates. Double-click to filter the gallery to that session. Delete individual sessions.

Browse all reference images with folder tree navigation and tag/deck management. Tag or untag images, assign to custom decks, hide images (adds Hidden tag, excludes from scheduling), or soft-delete images. Open images in system Explorer.

Data visualization with folder/tag/deck filters and a metric selector (Skill / Difficulty).
- Histogram: Bar chart of rating distribution
- Improvement Over Time: Line chart with rolling 5-round average
- Per-Subject Averages: Sortable table (rounds, avg skill, avg difficulty, drawing time, last practiced)

The 960x960 (or rectangular for manga) multi-layer drawing canvas.
- Pencil tool: Pressure-sensitive (size and opacity modulated by cubic-bezier curves), with configurable stroke taper and density
- Eraser tool: Circle or square shape, three sizes (S/M/L), pressure-sensitive
- Transform tool: Uniform (proportional scale/rotate/translate) or Free (independent corner/edge movement); undo support
- Reference Point tool: Move-only protected marker layer visible during all phases
- View navigation: Alt+drag to pan, Shift+Alt+drag to zoom, Shift+drag to rotate (CSP-style)
- Layer Panel: Floating draggable panel with add/delete/reorder layers, per-layer visibility checkbox and opacity slider, idle hover opacity
- Grid guides: Configurable grid with box size, divisions, color, and opacity, toggled via hotkey
- Dirty-rect partial repaints for performance
Cubic-bezier curves map pen pressure (0β1) to brush size and opacity. Three draggable handles: min (pinned at X=0), max (pinned at X=1), and a freely movable control point. Multiple named presets with CRUD management.
Full-screen tablet-friendly drawing interface. Toggle via nav bar button or configurable hotkey.
- Hides desktop toolbars, gives equal width to reference pane and canvas
- TabletToolbarOverlay: Whole-window two-tier curve palette with shaped input region
- Visual Start/Mid/End control point editor
- Configurable button size and font size
- Idle opacity 45%, fade to 100% on interaction
- Editable quadratic bezier layout curve
- Persisted floating position
- Touchscreen pan/pinch/rotate navigation in reference pane
- Pen contact suppresses hover for cleaner drawing
- Escape exits toolbar edit mode
Non-destructive drawing grid overlaid on the canvas. Configurable box size (px), number of minor divisions per major cell, hex color, and opacity. Toggled via configurable hotkey (default Alt+G). Rendered on both canvas and reference pane.
Circle or square shape. Three sizes (S/M/L) with configurable per-size pixel diameters (2β200px). Configurable global hotkey (default Ctrl) in hold or toggle mode. Pressure-sensitive when supported.
Scales Windows master volume with drawing activity via cubic-bezier ramps. A 5-state state machine runs on a 100ms timer:
IDLE β DRAW_DELAY (5s) β RAMP_UP (30s) β HOLD_MAX β RAMP_DOWN (60s)
- Captures baseline volume on engage, restores on disengage
- Configurable min/max volume, ramp durations, draw/stop delays
- Two customizable cubic-bezier ramp curves (up/down)
- Engages on session start, disengages on session end
Named, reusable image collections stored as JSON files in UserData/custom_decks/. CRUD operations: create, rename, delete, add/remove images, union images across decks. Filter Gallery and Stats by deck. Auto-prune on image deletion.
Per-image and per-round tagging. Protected built-in tags: Favorites and Hidden (cannot be deleted). Hidden images are excluded from scheduling. Tag filter available in Image Browser, Gallery, and Stats (AND/OR toggle).
Atomic, versioned full-state checkpoints saved to UserData/session_checkpoints/. Captures canvas layers, blur renderer state, round state, crop selector, rating widgets, overlay, and reference view. Paused sessions appear on the idle page with Resume and End Early options. Mode-filtered so each session type shows only its own paused sessions.
Freezes timers and disables phase-changing controls while allowing view navigation. Kept in memory (not checkpointed to disk). Resumes by extending all deadlines by pause duration.
- Blind Draw: Canvas hidden while drawing (random modifier %)
- Vertical Flip: Reference image flipped during crop (random modifier %)
- Linked Folders: Add external subject directories in Settings; scanned alongside
Data/subjects/ - Hidden Images: Tag images as Hidden to exclude from scheduling; can unhide via Library
- Fullscreen Mode: Toggle via nav button or Alt+Return/Enter
- Thumbnail Service: Shared 4-worker loader with 2,000-entry LRU, persistent WebP cache, deduplication, stale cancellation, 2GB disk limit
Access via the "Settings" nav button. 61 configurable fields organized into sections:
| Section | Settings |
|---|---|
| Phase Timings | Draw Phase 1/2 seconds, session block/b break minutes |
| Blur Settings | Gesture base seconds, 3 blur radii, unblur padding, falloff curve |
| Overlay | Overlay opacity %, layer panel idle opacity % |
| Tablet | Enabled toggle, palette X/Y ratio, toolbar curve points, button/font sizes |
| Modifiers | Vertical flip %, blind draw %, tracing % |
| Brush Sizes | Pencil S/M/L (1β120px), Eraser S/M/L (2β200px), default active sizes |
| Pencil | Pressure curve presets (via pencil settings dialog) |
| Grid Guides | Enabled, box size, divisions, color, opacity, hotkey |
| Reference Point | Point color |
| Manga | Crop bounds color + opacity, max canvas dimension |
| FSRS | Desired retention, 3 grade thresholds (Again/Hard/Good/Easy) |
| Eraser | Hotkey (QKeySequenceEdit), hold/toggle mode |
| Transform | Uniform or Free mode |
| Linked Folders | Add/Remove external subject directories |
| Music Reward | Enable, min/max%, ramp durations, delays, ramp curves |
| Debug | Show skip buttons |
15 SQLite tables in UserData/drawing_srs.db:
| Table | Purpose |
|---|---|
subjects |
FSRS card state per subject folder |
sessions |
Session lifecycle: mode, title, status, metadata |
rounds |
Full round data: crops, ratings, timings, metadata |
tags |
Global tag definitions (Favorites + Hidden protected) |
image_tags |
Per-image tag associations |
round_tags |
Per-round tag associations |
manga |
Registered manga series |
manga_chapters |
Chapters with ordered page lists |
manga_progress |
Per-page completion state |
books |
Registered books (PDF or image folders) |
book_pages |
Per-book page entries with cached renders |
book_drawings |
Per-page versioned drawing manifests |
library_images |
Persistent image catalog with invalidation metadata |
library_order_cache |
Persistent sort order by scope + mode |
library_thumbnails |
Thumbnail cache with source-change invalidation |
| Package | Version | Usage |
|---|---|---|
| PySide6 | β₯6.7 | Qt GUI framework (widgets, charts, input, stylesheets) |
| Pillow | β₯10.0 | Image I/O, cropping, flipping, Gaussian blur, alpha bounds |
| fsrs | β₯6.0 | Free Spaced Repetition Scheduler algorithm |
| pycaw | β₯20230407 | Windows audio control (music reward); conditional import |
main.py # Entry point
app/
core/ # Business logic (no Qt) β 14 files
config.py # Settings (61 fields), paths, JSON persistence
models.py # 8 domain dataclasses
database.py # 15-table SQLite CRUD + schema migration
image_source.py # Persistent catalog-backed image scanner
scheduler.py # FSRS wrapper for subject scheduling
round_modes.py # 5 mode specs (Standard/Tracing/Blur/Manga/Book)
custom_session.py / custom_deck.py # JSON-based presets and image collections
session_checkpoint.py # Atomic versioned session checkpoints
pressure_curve.py / falloff_curve.py # Cubic-bezier curve models
media_volume.py # pycaw volume wrapper
manga.py # Manga repository (scan, track progress)
book.py # Book repository (PDF/folder, versioned drawings)
ui/ # PySide6 widgets β 34 files (dark.qss + 33 .py)
session_view.py # 10-phase round state machine for all modes
canvas_widget.py # Multi-layer drawing canvas
main_window.py # Top-level window with 10 nav buttons
plus 30 other widgets and dialogs
tests/ # 13 test files
Data/subjects/ # Reference image library
UserData/ # Runtime data (gitignored): DB, settings, rounds, etc.




