<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oddbit Studios</title>
    <description>The latest articles on DEV Community by Oddbit Studios (@oddbitstudios).</description>
    <link>https://dev.to/oddbitstudios</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3837919%2Fb18fcece-bf98-4685-bf6a-fafa31e23a85.png</url>
      <title>DEV Community: Oddbit Studios</title>
      <link>https://dev.to/oddbitstudios</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oddbitstudios"/>
    <language>en</language>
    <item>
      <title>How I Built a Local-First Movie Library Manager in Python</title>
      <dc:creator>Oddbit Studios</dc:creator>
      <pubDate>Sun, 22 Mar 2026 04:31:56 +0000</pubDate>
      <link>https://dev.to/oddbitstudios/how-i-built-a-local-first-movie-library-manager-in-python-39f8</link>
      <guid>https://dev.to/oddbitstudios/how-i-built-a-local-first-movie-library-manager-in-python-39f8</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I have a problem that a lot of people who've been collecting digital media for years will recognize — I had nearly 1,000 movie files spread across multiple drives and absolutely no idea what I actually owned. Was I about to buy a movie I already had? Did I have three copies of the same file hiding in different folders? No idea.&lt;/p&gt;

&lt;p&gt;I looked at the existing options. Plex and Jellyfin are great but they're full media servers — I didn't need transcoding or streaming, I just needed a catalog. Spreadsheets work but they're manual. MediaElch was close but not quite what I wanted.&lt;/p&gt;

&lt;p&gt;So I built Film Forge.&lt;/p&gt;




&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;Film Forge is a desktop application for Windows built in Python and Tkinter. Here's the core workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add folders&lt;/strong&gt; — point it at any directory containing video files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start Scan&lt;/strong&gt; — it recursively finds every video file (.mp4, .mkv, .avi, .mov, and more)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch Details&lt;/strong&gt; — pulls metadata from the OMDb API for every movie found&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Browse your library&lt;/strong&gt; — search, filter, rate, and track everything from the Database tab&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything is stored in a local SQLite database. No cloud. No accounts. No subscriptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Desktop app:  Python 3.13, Tkinter, SQLite, Pillow, pandas, openpyxl
Web server:   Flask, Flask-CORS, Gunicorn
Metadata:     OMDb API
Deployment:   Railway, GitHub
Packaging:    PyInstaller, Inno Setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose Tkinter because it's built into Python and requires no additional UI framework. It's not the flashiest toolkit but it gets the job done and keeps the dependency list short.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Web Interface
&lt;/h2&gt;

&lt;p&gt;One of the features I'm most proud of is the built-in Flask web server. From the Settings tab you can start a local web server and browse your entire movie library from any browser on your network.&lt;/p&gt;

&lt;p&gt;Each movie card shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Poster art from OMDb&lt;/li&gt;
&lt;li&gt;Title, year, runtime, MPAA rating, genre, cast&lt;/li&gt;
&lt;li&gt;Full plot summary&lt;/li&gt;
&lt;li&gt;5-star personal rating (click to set)&lt;/li&gt;
&lt;li&gt;Watched / Unwatch button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The web interface also exposes a REST JSON API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET  /api/movies              # Paginated, filterable movie list
GET  /api/movies/&amp;lt;imdb_id&amp;gt;    # Single movie detail
POST /api/set_rating          # Set 1-5 star rating
POST /api/set_watched         # Mark watched/unwatched
GET  /api/docs                # API documentation
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Railway Deployment
&lt;/h2&gt;

&lt;p&gt;For public access, Film Forge supports one-click sync to GitHub and auto-redeploy to Railway. The web server component is a standalone Flask app that reads from a SQLite database file. Point a custom domain at your Railway deployment and your collection is accessible from anywhere.&lt;/p&gt;




&lt;h2&gt;
  
  
  Packaging for Windows
&lt;/h2&gt;

&lt;p&gt;Building the Windows installer was an interesting challenge. The process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;PyInstaller&lt;/strong&gt; — bundles the Python app and all dependencies into a single &lt;code&gt;.exe&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inno Setup&lt;/strong&gt; — wraps the EXE into a polished one-click installer with Start Menu shortcuts, desktop icon, and a bundled PDF user manual
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; PyInstaller &lt;span class="nt"&gt;--onefile&lt;/span&gt; &lt;span class="nt"&gt;--windowed&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"FilmForge"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Film_Forge.ico"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--hidden-import&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;film_forge_db &lt;span class="se"&gt;\&lt;/span&gt;
  Film_Forge_3_7_7.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final installer is about 26MB and includes the full application and user manual.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tkinter is underrated&lt;/strong&gt; — it gets a bad reputation but for a desktop utility app it's perfectly capable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite is incredibly powerful&lt;/strong&gt; for this use case — a single file database that handles 1,000+ movies without breaking a sweat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyInstaller hidden imports&lt;/strong&gt; will catch you off guard — always test in a clean environment before distributing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inno Setup&lt;/strong&gt; is still the gold standard for Windows installers — free, powerful, and well documented&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Android app (WebView wrapper to start, native later)&lt;/li&gt;
&lt;li&gt;Automatic metadata refresh on a schedule&lt;/li&gt;
&lt;li&gt;TV show support&lt;/li&gt;
&lt;li&gt;Better duplicate resolution UI&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Download: &lt;a href="https://github.com/oddbitstudios/Film-Forge/releases" rel="noopener noreferrer"&gt;github.com/oddbitstudios/Film-Forge/releases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/oddbitstudios/Film-Forge" rel="noopener noreferrer"&gt;github.com/oddbitstudios/Film-Forge&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Support my effort: &lt;a href="https://buymeacoffee.com/oddbitstudios" rel="noopener noreferrer"&gt;buymeacoffee.com/oddbitstudios&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built by Oddbit Studios — independent software, crafted with odd precision.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
