A modern, secure web application to transfer curated photos from Google Photos directly to Wikimedia Commons using official APIs. It provides a clean, visual curation interface to rename files, add multilingual descriptions, assign categories, and publish uploads asynchronously in chunks.
graph TD
A[Google Photos Picker API] -->|User Selects Images| B[React Frontend]
B -->|Submit Upload Form| C[FastAPI Backend]
C -->|Authenticate request| D[Google Photos CDN]
C -->|Stream high-res bytes| E[Wikimedia Commons API]
- Uses the Google Photos Picker API (OAuth scope:
.../auth/photospicker.mediaitems.readonly). - Uses a Session-based Picker Flow: The application never gains broad access to the user's entire library. It only accesses items explicitly selected and returned by the picker popup.
- Multilingual Description & Caption: Edit descriptions in languages supported by Wikimedia.
- Auto-populated Date: Extracted from the original image EXIF data (
createTimeretrieved from Google Photos metadata). - Category Autocomplete: Directly integrates with the MediaWiki OpenSearch API to search and validate categories.
- Smart Filename Suggestions: Suggests standard, descriptive names for Wikimedia Commons.
- Streams photo bytes in memory using async HTTP generators (
httpx.AsyncClient.stream). - Zero temporary disk storage: Bytes are downloaded and chunk-uploaded to MediaWiki concurrently to prevent memory leaks and protect user privacy.
- Bypasses Soft Warnings: Finalizes stashed uploads with
ignorewarnings: 1to bypass minor filename or duplicate alerts. - Progress Tracking: Real-time progress bar powered by background worker polling.
- Frontend: React 19, TypeScript, Vite, TailwindCSS (Vanilla variables styling)
- Backend: FastAPI, Python 3.12+, SQL Alchemy, SQLite (sessions persistence), HTTPX (asynchronous stream processing)
├── backend/
│ ├── app/
│ │ ├── models/ # Database session models
│ │ ├── routers/ # Endpoints: auth, picker, upload
│ │ └── services/ # Client wrappers for MediaWiki & Google Photos
│ └── run.py # FastAPI Server Entrypoint
├── frontend/
│ ├── src/
│ │ ├── components/ # Picker, MetadataEditor, Dashboard
│ │ └── utils/ # API Client wrappers
│ └── index.html
├── run.sh # Entrypoint shell script to boot frontend + backend
└── LICENSE
- Python 3.10+
- Node.js 18+
- Google Cloud Console Credentials (with Photos Picker API enabled)
- Wikimedia Client Credentials (with OAuth 2.0 configured)
- Clone the repository.
- Copy
.env.exampleto.envand fill in your Client IDs and Secrets:cp .env.example .env
- Run the development environment launcher:
./run.sh
- Access the web app at
http://localhost:5173.
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for the full text.