It sat on a platform I rented and never moved. Today it's a folder on my computer, and it updates while I work, not once every five years.
2026.
The old site has no export button. So the first instruction I gave the agent was:
"Download my entire Adobe Portfolio site, all pages, all images, all assets, into a clean organized folder on my computer."

lines in a script that went through 19 project pages and four general ones. The old site hides every image until you scroll to it, so we looked for each one in three different places in the page code.
for img in soup.find_all("img"):
for attr in ("src", "data-src", "data-image"):
src = img.get(attr, "").strip()
if src and not src.startswith("data:"):
image_urls.add(urljoin(base, src))platforms the videos lived on: Facebook, YouTube and Vimeo. Each video came down with a separate tool, and whatever failed was saved as a link.
result = subprocess.run(
[
"python3", "-m", "yt_dlp",
"--no-playlist",
"-o", str(dest_dir / "%(id)s.%(ext)s"),
url,
],videos and prototypes that cannot be downloaded at all: 17 in Adobe’s player on the post production page, and two in Adobe XD. They were saved as links and came into the new site as embedded windows.
elif "adobe.io" in src or "xd.adobe.com" in src:
reference_urls.add(src)Ten minutes in: 19 project folders and 99 files. iCount came back empty, because the old site had locked it with a password, so we built it separately later.
{
"slug": "leadershipaticount",
"title": "Password Protected Page",
"url": "https://www.meravish.com/leadershipaticount",
"media_count": 0
}
for a single GIF in the motion project. That project alone held 22 GIFs, 53MB that every visitor downloads.
26M 539a8e1f-c10c-41ff-836f-3879b7565906_rw_1200.gif
3.5M a4ca336f-fa48-410e-bbf7-98848459e70c_rw_600.gif
3.2M 2c11e7f0-510c-4d6a-9119-740ee2947faf_rw_1200.gif1,044 lines in the script that built the site from the folder: a home page, 18 project pages and a work with me page. Every project asked for something else: iCount was built separately, and a Hebrew tagline was swapped for the description from the list.
def build_project(slug, year, title, desc_short):
if slug == "leadershipaticount":
build_icount_page()
return
...
# If tagline contains Hebrew characters, fall back to the PROJECTS-list desc
if any('\u0590' <= c <= '\u05ff' for c in (tagline or "")):
tagline = desc_shortis the size the old site signed its thumbnails at, and they came out blurry. We tried to upscale them, then gave up and took each project’s original image from the folder.
def hires_thumb_url(url):
"""Upgrade MyPortfolio CDN thumbnail from x32 → x800."""
import re
return re.sub(r'x32\.(png|gif|jpg)', r'x800.\1', url)
...
return False # Always use first_local_media fallback insteadafter the site went up, Netlify suspended it for too much traffic. Vercel got stuck at sign in with version 52 of its tool. Only on the third try, on Cloudflare, did it stay up, and the address moved over.
registrar GoDaddynameservers dora.ns.cloudflare.com odin.ns.cloudflare.comA record Netlify (deleted)$ npx wrangler@latest deploy --name meravishand meravish.com still showed an error page. Netlify was holding my address where I couldn’t see it. Removing the domain wasn’t enough; only deleting my account there released it.
In short, here is how it felt:
Then came obstacles, delays, and months of polish.
So the case study wasn't written after the fact. It came out of what already happened.
One rulebook that every new page reads before it's built.
Six products and sites went live in 2026. The portfolio is what's left behind.
Your work crosses with you.
Every project from your current site, rebuilt as a site you own in a few minutes. Change anything with AI. Your files, your domain, no subscription.
From day one I steered the agent there: paper, aubergine ink, one coral and a hand-drawn line. Promtfolio was born into the same family.
How the drawing engine was built →






Fifteen minutes to explain what you need, and to see whether I can help. No deck, no commitment.