{"id":477,"date":"2025-10-29T17:07:17","date_gmt":"2025-10-29T17:07:17","guid":{"rendered":"https:\/\/jennifertanghe.com\/?p=477"},"modified":"2025-10-29T20:20:40","modified_gmt":"2025-10-29T20:20:40","slug":"how-i-brought-my-old-websites-back-to-life-with-ai-and-a-bit-of-docker","status":"publish","type":"post","link":"https:\/\/jennifertanghe.com\/how-i-brought-my-old-websites-back-to-life-with-ai-and-a-bit-of-docker\/","title":{"rendered":"How I Brought My Old Websites Back to Life with AI (and a Bit of Docker)"},"content":{"rendered":"\n\n<p>Last weekend, while normal people were out having coffee or strolling through the market, I decided to open the drawers of my digital past.<br>Old projects sleeping on hard drives: <strong>PHP 3<\/strong>, <strong>PHP 4<\/strong>, ancient <strong>MySQL<\/strong>, even some Flash here and there.<\/p>\n\n\n\n<p>A kind of treasure hunt, developer-style. Or maybe Alice in Wonderland, but with corrupted MySQL tables instead of white rabbits.<br>Inside: my first scripts, my first interfaces, my first bugs. And a few surprises.<\/p>\n\n\n\n<p>I didn\u2019t know yet that I was about to spend the whole weekend running code from the early 2000s\u2026 with a little help from an<strong> AI<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. The Archives: A Chaos of Folders and Memories<\/h2>\n\n\n\n<p>It all started out of curiosity. I\u2019d been digging through archive.org to find my old sites, and then I thought: I\u2019m pretty sure I still have all that stuff somewhere, on old burned CDs or ancient external drives.<br>So I started digging, and stumbled upon an old <code>public_html<\/code> folder, then another, then a <code>site_old<\/code> with <code>.php3<\/code>, <code>.inc<\/code> files, and some <strong>SQL<\/strong> dumps.<br>Some projects didn\u2019t even have a database anymore, just code calling ghost tables.<\/p>\n\n\n\n<p>I reopened everything with <strong>ChatGPT<\/strong>, line by line, trying to understand how I had built it.<br>The <strong>AI<\/strong> started &#8220;reading&#8221; my old scripts like an archaeologist decoding hieroglyphics:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>&#8220;Here you probably had a <code>cartes<\/code> table with these fields: <code>id<\/code>, <code>message<\/code>, <code>image<\/code>, <code>email<\/code>\u2026&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p>And together, we rebuilt lost SQL schemas from <strong>PHP<\/strong> code.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-revival_site_2003.webp\" alt=\"\" class=\"wp-image-473\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-revival_site_2003.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-revival_site_2003-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-revival_site_2003-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-revival_site_2003-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">2. Docker: My Web Time Machine<\/h2>\n\n\n\n<p>The next idea was to isolate everything.<br>No way I was going to install prehistoric versions of <strong>PHP<\/strong> or <strong>MySQL<\/strong> on my machine.<\/p>\n\n\n\n<p>So we used Docker to spin up custom environments:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>An <strong>Apache<\/strong>\/PHP 3 or 4 container, recompiled from source<\/li>\n\n\n\n<li>A <strong>MySQL 4.1<\/strong> or 5.0 container<\/li>\n\n\n\n<li>A <strong>phpMyAdmin<\/strong> to check that everything was still readable<\/li>\n\n\n\n<li>And a local <strong>Docker<\/strong> network to tie it all together<\/li>\n<\/ul>\n\n\n\n<p>Each site had its own folder and its own <code>docker-compose.yml<\/code>.<br>That let me browse to <code>http:\/\/site2002.local<\/code> like I\u2019d traveled twenty years back in time.<br>And every time a site finally loaded without errors, I\u2019d get that little rush of adrenaline:<\/p>\n\n\n\n<p><em>&#8220;Oh wow, I actually coded this!&#8221;<\/em><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003.webp\" alt=\"\" class=\"wp-image-476\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">3. Rebuilding with No Blueprint\u2014Just the Code<\/h2>\n\n\n\n<p>Some projects had nothing left to work with.<br>We had to rebuild the tables from scraps: a leftover <code>INSERT<\/code> in a script, an implicit join in a <code>SELECT<\/code>, a <code>$row['message']<\/code> field betraying the original structure.<\/p>\n\n\n\n<p>Bit by bit, the pieces came together: the <strong>PHP<\/strong> code, the rebuilt database, the missing images found in an old <code>uploads\/<\/code> folder.<\/p>\n\n\n\n<p>And suddenly, the site would open again like a time capsule.<br>What I had coded in my twenties, awkwardly, still held up.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. The Surprise: FlyCMS, My Homemade CMS from the Spaghetti Code Era<\/h2>\n\n\n\n<p>And then, there was <em>the<\/em> surprise. While digging through a folder I thought was empty, I stumbled on <strong>FlyCMS<\/strong>.<\/p>\n\n\n\n<p>My very own content management system, coded back in 2003-2004.<\/p>\n\n\n\n<p>I had completely forgotten about it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-code.webp\" alt=\"\" class=\"wp-image-474\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-code.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-code-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-code-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-code-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">What I Discovered<\/h3>\n\n\n\n<p>Reopening the files, I realized I was already pretty organized in my code, even though PHP 3 and 4 were peak <strong>spaghetti code<\/strong> era.<\/p>\n\n\n\n<p>But above all, I discovered that I was obsessed with documentation.<\/p>\n\n\n\n<p>This <strong>CMS<\/strong>, which I was the only one using, had full documentation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Step-by-step installation<\/li>\n\n\n\n<li>Detailed config with screenshots<\/li>\n\n\n\n<li>Instructions for creating pages, managing the page tree, editing templates<\/li>\n\n\n\n<li>Even a \u201cIf it doesn\u2019t work, check folder permissions\u201d section<\/li>\n<\/ul>\n\n\n\n<p>I found it hilarious. And honestly, kind of touching.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-doc.webp\" alt=\"\" class=\"wp-image-475\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-doc.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-doc-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-doc-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flycms-2004-doc-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">The Architecture (Surprisingly Modern)<\/h3>\n\n\n\n<p>Reading through the code, I realized I had already built:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>A templating system<\/strong> with override: I could use the dynamic PHP\/DB\/templates system or override any page with a static HTML file<\/li>\n\n\n\n<li><strong>Multilanguage support<\/strong>: everything was ready to translate the admin interface<\/li>\n\n\n\n<li><strong>A page tree system<\/strong> with customizable order<\/li>\n\n\n\n<li><strong>Modules<\/strong> that could be enabled or disabled<\/li>\n\n\n\n<li><strong>Clean separation<\/strong> between config, templates, CSS, and content<\/li>\n<\/ul>\n\n\n\n<p>For 2003, with <strong>PHP 4<\/strong>, that wasn\u2019t bad at all.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Killer Detail<\/h3>\n\n\n\n<p>In the docs, I had written:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201cFlyCMS is a content management tool for easily creating websites. It works with a page tree and template system. <strong>It was slapped together in 3 days, so I totally deserve a beer!<\/strong>\u201d<\/p>\n<\/blockquote>\n\n\n\n<p>And to explain how to find the full server path:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>\u201cDon\u2019t know what to put here?<br>Create a file called test.php<br><strong>Putzy<\/strong> (yes, spelled like that) this code in it: <code>&lt;?php echo realpath('test.php'); ?&gt;<\/code>\u201d<\/p>\n<\/blockquote>\n\n\n\n<p>Apparently, I\u2019ve <em>always<\/em> been like this \ud83d\ude04<\/p>\n\n\n\n\n<h3 class=\"wp-block-heading\">Thanks, Past Me<\/h3>\n\n\n\n<p>Reading that documentation, with its <code>.gif<\/code> screenshots, detailed walkthroughs and little jokes, I had a weird emotional moment.<\/p>\n\n\n\n<p>The Jennifer from 2003 had taken the time to document everything.<br>For herself, but also for a future user.<\/p>\n\n\n\n<p>And 22 years later, that future user was me.<br>Thank you, past me. Seriously.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. The Flash Projects Were Something Else<\/h2>\n\n\n\n<p>The wildest moment was finding my old <strong>Flash<\/strong> projects.<br>One in particular was a little tool I had called <strong>&#8220;Dessine?&#8221;<\/strong> (&#8220;Draw?&#8221;): you\u2019d make a drawing by coloring squares in the browser, add a message, and it would create an <strong>e-card<\/strong> stored in the database, with a unique link to send to someone.<\/p>\n\n\n\n<p>When I reopened the <code>.<strong>swf<\/strong><\/code>, I laughed at first.<br>Then I realized it was real code: the Flash file sent POST requests to a <code>save.php<\/code> that saved the image and message.<br>Everything was still there in the folder.<\/p>\n\n\n\n<p>Except\u2026 <strong>Flash<\/strong> itself was gone.<\/p>\n\n\n\n<p>So we used <strong>Ruffle<\/strong>, a modern Flash emulator in WebAssembly.<br>With a few tweaks in the Docker backend (PHP 4 + MySQL + the original <code>save.php<\/code>), <strong>Dessine?<\/strong> came back to life.<\/p>\n\n\n\n<p>The SWF runs in the browser, images get saved again, and the unique links lead to real view pages.<br>Twenty years later, the e-cards still work.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/dessine-2001.webp\" alt=\"\" class=\"wp-image-471\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/dessine-2001.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/dessine-2001-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/dessine-2001-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/dessine-2001-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">6. The Role of AI<\/h2>\n\n\n\n<p>I would never have started all this without a patient assistant to help me decipher my own relics.<\/p>\n\n\n\n<p><strong>ChatGPT<\/strong> helped me:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Decode old <strong>PHP<\/strong> scripts and recover data structures<\/li>\n\n\n\n<li>Fix encoding issues (<code>\u00c3\u00a9<\/code>)<\/li>\n\n\n\n<li>Set up the right <strong>Docker<\/strong> versions<\/li>\n\n\n\n<li>Recompile an old <strong>PHP<\/strong> to load missing extensions<\/li>\n\n\n\n<li>And even emulate <strong>Flash<\/strong> without <strong>Flash Player<\/strong><\/li>\n<\/ul>\n\n\n\n<p>But most importantly, it forced me to read my old code like a story, to understand what I was thinking when I wrote it.<br>And that part was unexpected.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"900\" src=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-flycms-2004.webp\" alt=\"\" class=\"wp-image-472\" srcset=\"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-flycms-2004.webp 1200w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-flycms-2004-300x225.webp 300w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-flycms-2004-1024x768.webp 1024w, https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/docker-flycms-2004-768x576.webp 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">7. What I\u2019m Taking Away from This<\/h2>\n\n\n\n<p>Bringing those sites back wasn\u2019t just a technical exercise.<br>It was a deep dive into my journey as a developer.<\/p>\n\n\n\n<p>Each Docker container became a little time bubble where I could revisit my beginnings, my mistakes, my little discoveries.<\/p>\n\n\n\n<p>And I got to see that 2003 Jennifer, who \u201cslapped together a CMS in 3 days\u201d but still documented every step with care, was already on the right path.<br>She didn\u2019t know it yet, but she was already building things that would last.<br>Even if they were going to sleep on a hard drive for 22 years.<\/p>\n\n\n\n<p>Now I\u2019ve started archiving those old sites and experimental projects on GitHub\u2014because let\u2019s be honest, those CDs and hard drives aren\u2019t going to last forever\u2026<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>What I learned by recreating all this with the help of an AI is that <strong>no line of code is truly lost<\/strong>.<br>Everything can be rebuilt, everything can be understood, if you take the time to listen to what the code is telling you.<\/p>\n\n\n\n<p>Docker gave me the infrastructure.<br>AI gave me the memory.<br>And I gave life back to a piece of my own story.<\/p>\n\n\n\n<p><em>PS: If you also have old projects lying around early 2000s websites you\u2019d love to bring back to life, or if you\u2019re just curious how we did things \u201cback then\u201d\u2026 <a href=\"\/contact\/\" rel=\"noopener noreferrer\">let\u2019s talk<\/a>. I\u2019d love to hear your stories.<\/em><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Last weekend, I decided to dig through my digital past and bring my old websites back to life, from PHP 3 to forgotten Flash experiments. With the help of Docker and a curious AI, I revived broken scripts, rebuilt missing databases, and rediscovered a CMS I coded (and documented!) twenty years ago. A nostalgic journey through code, chaos, and a few surprises. <a class=\"read-more\" href=\"https:\/\/jennifertanghe.com\/how-i-brought-my-old-websites-back-to-life-with-ai-and-a-bit-of-docker\/\">Leggi tutto<\/a><\/p>\n","protected":false},"author":1,"featured_media":476,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jtseo_title":"","_jtseo_description":"Freelance full-stack architect and creative consultant. Viterbo, Italy","_jtseo_keywords":"","_jtseo_canonical":"","_jtseo_robots":"index,follow","_jtseo_og_title":"","_jtseo_og_description":"","_jtseo_og_image_id":0,"_jtseo_twitter_image_id":0,"_jtseo_og_type":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[433,432,431],"tags":[],"class_list":["post-477","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-nostalgia","category-personal-projects","category-web-dev"],"jetpack_featured_media_url":"https:\/\/jennifertanghe.com\/wp-content\/uploads\/2025\/10\/flyingcow-2003.webp","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/posts\/477","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/comments?post=477"}],"version-history":[{"count":4,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/posts\/477\/revisions"}],"predecessor-version":[{"id":482,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/posts\/477\/revisions\/482"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/media\/476"}],"wp:attachment":[{"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/media?parent=477"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/categories?post=477"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jennifertanghe.com\/wp-json\/wp\/v2\/tags?post=477"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}