PhotoRestorer is a web app for restoring old family photographs with Gemini image editing. It is designed for historical photos that may be faded, blurred, scratched, sepia, or monochrome, and it can optionally colorize them while trying to preserve the original people, pose, framing, and scene layout.
The app supports two main workflows:
- a local server-folder workflow where you browse a folder of photos and save restored files beside the originals
- a hosted upload workflow where each user uploads their own photos and uses their own Gemini API key
You can work one photo at a time, review the original and restored result side by side, use the overlay compare view, and optionally add same-person reference photos to help recover identity, hair, clothing, and other person details when the target photo is unclear.
PhotoRestorer now has two deployment targets:
family_restore_server.py: local/LAN standalone server for your own server-folder workflowpassenger_wsgi.py+family_restore_hosted_wsgi.py: hosted upload-only app for cPanel/Passenger
Both variants use the same family_restore_gui.html.
Install the Python packages from requirements.txt into a virtual environment:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThe only Python packages currently required are:
google-genaiPillow
Use this when you want to browse folders on your own machine or LAN server and save restored files beside the originals.
Run:
python3 family_restore_server.pyThen open:
http://127.0.0.1:8765/family_restore_gui.html- or the printed LAN URL
Local behavior:
- server-side folder browser
- one folder at a time
- restored files saved beside originals as
_r01,_r02, and so on - settings persisted in
family_restore_prompt_config.json
When the local app opens for the first time:
- Enter your Gemini API key if you are not using a server-wide
GOOGLE_API_KEY. - Click
Browse Server Folders. - Choose the folder that contains the photos you want to work on.
- Select an image from the list.
- Optionally upload one or two clearer same-person reference photos.
- Adjust
Prompt,Extra note,Colorize,Overwrite latest _rNN, and automatic-processing settings. - Click
Restore Selected.
For local use, restored files are written beside the originals as:
<stem>_r01.png<stem>_r02.png- and so on
Automatic processing:
- set
Auto pause secondsto0for manual use - set it above
0to process the folder sequentially with a pause between images
Example of the local restoration workflow with the original, latest restored result, and compare panel visible:
Example of the compare overlay view for checking the restored result against the source image:
Another compare overlay example showing a portrait-style historical restoration:
Use this when the app is hosted for other users. In this mode:
- users upload their own target photos
- users upload their own same-person reference photos
- users provide their own Gemini API key in the browser
- no browsing of your server folders
- uploaded files live only in a temporary server-side session area
- restored results are downloaded individually
When the hosted app opens for the first time:
- Enter your own Gemini API key in the app.
- Click
Upload Target Photosand choose the photo or photos you want to restore. - Select one uploaded image from the list.
- Optionally upload one or two clearer same-person reference photos.
- Adjust
Prompt,Extra note,Colorize,Overwrite latest _rNN, and automatic-processing settings. - Click
Restore Selected. - Use the
Downloadbutton on the restored panel to save the result.
Hosted behavior:
- uploaded target and reference images are tied to the current browser session
- users do not browse server folders
- users bring their own Gemini API key
- restored outputs are downloaded individually rather than written into a server photo folder
These are the values that worked on a cPanel / CloudLinux / LiteSpeed host:
Python version:3.12.12or the exact Python 3 version you intend to keepApplication root:public_html/photorestorerApplication URL:your-domain.example / photorestorerApplication startup file:passenger_wsgi.pyApplication Entry point:application
Important:
- create the app with the final Python version from the start
- do not create it as Python 2.7 and then switch it later
- cPanel may generate its own initial
passenger_wsgi.py; after creation, replace it with passenger_wsgi.py
Upload these files into /home/<cpanel-user>/public_html/photorestorer:
- passenger_wsgi.py
- family_restore_hosted_wsgi.py
- family_restore_server.py
- family_restore_gui.html
- requirements.txt
Do not upload family_restore_prompt_config.json for the hosted app.
- Create the Python app in cPanel with the values above.
- Wait for cPanel to create the app root and virtualenv.
- Upload the files listed above into
public_html/photorestorer. - If cPanel generated a starter
passenger_wsgi.py, replace it with the repo copy. - Install the Python packages from
requirements.txt.
If the cPanel Run Pip Install button is silent or unreliable, use SSH instead:
source /home/<cpanel-user>/virtualenv/public_html/photorestorer/3.12/bin/activate
cd /home/<cpanel-user>/public_html/photorestorer
pip install -r requirements.txt- Start the app from cPanel.
- Open the hosted URL.
On some cPanel / CloudLinux / LiteSpeed hosts, the Python app does not always write the Passenger directives correctly. If the site shows a directory listing instead of the app, make sure /home/<cpanel-user>/public_html/photorestorer/.htaccess contains:
PassengerAppRoot "/home/<cpanel-user>/public_html/photorestorer"
PassengerBaseURI "/photorestorer"
PassengerPython "/home/<cpanel-user>/virtualenv/public_html/photorestorer/3.12/bin/python"
<IfModule LiteSpeed>
</IfModule>Then restart Passenger:
mkdir -p /home/<cpanel-user>/public_html/photorestorer/tmp
touch /home/<cpanel-user>/public_html/photorestorer/tmp/restart.txtIf the hosted app returns 503, the first file to inspect is:
tail -100 /home/<cpanel-user>/public_html/photorestorer/stderr.logTwo failure modes were seen during setup:
- stale Python 2.7 wrapper state after changing Python versions
- missing Passenger directives in
.htaccess, which caused LiteSpeed to serve a directory listing instead of the app
For the hosted app, the recommended setup is:
- leave
GOOGLE_API_KEYunset on the server - each user enters their own Gemini API key in the app
The Gemini API key field is stored only in that user's browser and is sent only with that user's restore requests.
For both local and hosted use:
- the target photo defines the layout, pose, framing, and scene
- same-person reference photos are for identity, hair, clothing, and person detail only
- references should not be used to replace the target photo's composition
- use
Extra notewhen you need to name the people and clarify who is where in the target image
A good pattern for Extra note is:
The target photo contains Mum, Bill (2), Sue (4), and Peter (6). Keep the exact layout and positions from the target image. Use the reference photos only to recover the appearance of these same people.
- Temporary reference uploads, hosted target uploads, and compare previews are stored in the system temp directory, not in this repo.
- Token usage logs are written under
logs/. - The shared UI now uses path-safe API URLs, so it can run under a cPanel subpath like
/photorestorer.


