Photography Studio SaaS for Image Proofing, Download, and Gallery Management β powered by WordPress
Aperture Pro is a modern, productionβgrade WordPress plugin built for photography studios that need a secure, elegant, and scalable way to deliver proofs, collect approvals, and provide final downloads. It blends a polished client experience with a robust operational backend designed for reliability, observability, and longβterm maintainability.
- Watermarked, lowβresolution proof images
- Image selection, commenting, and approval workflows
- Signed, shortβlived proof URLs
- Mobileβfriendly, accessible client portal
- Download tokens bound to project, client email, and session
- Optional OTP verification
- Rateβlimited and singleβuse token options
- Signed URLs for local and cloud storage
- Clientβside chunked uploader with exponential backoff + jitter
- Local session persistence for resume
- Serverβside chunk assembly with watchdog cleanup
- Progress polling and resumability
- Providerβagnostic
UploaderInterfacefor all storage backends - Streamβfirst uploads with automatic chunking or multipart fallback
- Centralized retry strategy with exponential backoff
- Explicit
UploadRequest/UploadResultDTOs - Providerβspecific optimizations without Storage API changes
- Local storage with pathβhiding and signed URL proxying
- S3 + CloudFront with multipart uploads
- Cloudinary and ImageKit adapters
- Extensible
StorageInterfaceandStorageFactory - Batch existence checks + batch URL signing
- Payment Abstraction Layer supporting multiple providers
- Provider drivers (Stripe, PayPal, Square, Authorize.net, Amazon Pay)
- Secure webhook verification
- Normalized payment events via DTOs
- Automatic project status updates via workflow engine
- Admin βPayment Summaryβ card + timeline
- Idempotent project lifecycle transitions
- Proof approval β editing β delivery state management
- Paymentβdriven state updates
- Eventβdriven email and notification hooks
- Hardened against retries and webhook replay
- Modern SaaSβstyle settings and Command Center
- Tooltips, inline help, and validation
- API key + webhook secret test actions
- Theme variable overrides
- Encrypted API keys and secrets at rest
- Centralized logging
- Health Dashboard with modular cards
- Queue depth and performance metrics
- Queued admin email notifications
- Watchdog for stuck uploads, proofs, and storage issues
Aperture Pro follows a strict event-driven workflow to ensure data integrity and a smooth client experience.
- Project Creation: Admin creates a project. The system initializes a Proof Gallery and generates a secure Magic Link.
- High-Res Upload: Photographer uploads high-resolution images via the admin panel.
- Uploads are chunked client-side and streamed to the server to bypass PHP memory limits.
- Chunks are assembled, validated (MIME/Size), and pushed to the configured Storage Provider (S3, Local, etc.).
- Metadata is stored in the
ap_imagestable.
- Proof Generation: A background job (driven by WP-Cron and
ProofQueue) automatically picks up new images.- It downloads the original, resizes it, applies a watermark ("PROOF COPY"), and uploads the low-res variant.
- This ensures the original high-res file is never exposed directly to the client browser.
- Access: The client receives an email with the Magic Link, which logs them into the Client Portal (session-based).
- Selection & Approval:
- Clients view the watermarked proofs.
- They can "Heart" (Select) images and leave comments.
- Finally, they click "Approve Proofs," which locks the gallery and transitions the project status to
editing.
- Refinement: The photographer sees the approved selection in the admin dashboard to perform final edits (retouching).
- Payment: The client pays for the package/session via the integrated payment gateway (Stripe/PayPal).
- Webhooks notify the Payment Abstraction Layer, which normalizes the event.
Workflow::onPaymentReceivedis triggered.
- Delivery:
- Upon confirmed payment (or manual trigger), the system generates a secure, time-bound Download Token.
- An email is sent to the client with a link to download their final gallery.
- Downloads are streamed through a signed URL proxy to protect the actual storage location.
aperture-pro/
β
βββ aperture-pro.php
βββ index.php
βββ README.md
βββ CHANGELOG.md
βββ composer.json
βββ package.json
β
βββ inc/
β βββ autoloader.php
β βββ helpers.php
β
βββ src/
β βββ Admin/
β βββ Auth/
β βββ ClientPortal/
β βββ Config/
β βββ Download/
β βββ Email/
β βββ Health/
β βββ Helpers/
β βββ Installer/
β βββ Payments/
β β βββ DTO/
β β βββ Providers/
β β βββ PaymentProviderInterface.php
β β βββ PaymentProviderFactory.php
β βββ Proof/
β βββ REST/
β βββ Services/
β βββ Storage/
β β βββ Upload/
β β β βββ UploaderInterface.php
β β β βββ UploadRequest.php
β β β βββ UploadResult.php
β β β βββ S3Uploader.php
β β β βββ CloudinaryUploader.php
β β β βββ ImageKitUploader.php
β β βββ StorageFactory.php
β βββ Workflow/
β βββ Loader.php
β
βββ assets/
β βββ css/
β βββ js/
β βββ images/
β
βββ tests/
βββ verify_uploaders.php
βββ verify_payment_abstraction.php
βββ benchmark_js_chunking.js
βββ phpunit.xml
aperture-pro-theme/
β
βββ style.css
βββ theme.json
βββ screenshot.png
β
βββ functions.php
βββ index.php
β
βββ inc/
β βββ enqueue.php
β βββ template-tags.php
β βββ helpers.php
β
βββ parts/
β βββ header.html
β βββ footer.html
β βββ navigation.html
β
βββ templates/
β βββ front-page.html
β βββ single.html
β βββ page.html
β
βββ assets/
β βββ css/
β β βββ header.css
β β βββ navigation.css
β β βββ layout.css
β β
β βββ js/
β β βββ theme.js
β β βββ interactions.js
β β
β βββ images/
β
βββ tests/
βββ verify_theme_load.php
Follow these steps to get your studio up and running immediately after installing the plugin.
- Upload the
aperture-profolder to your/wp-content/plugins/directory. - Log in to WordPress Admin and navigate to Plugins.
- Click Activate under "Aperture Pro".
- Optional: If you are using the companion theme, upload and activate
aperture-pro-themeunder Appearance β Themes.
Go to Aperture Pro β Settings β Storage.
- Local Storage: Simplest for getting started. Files are stored on your server.
- S3 / Cloud Storage (Recommended): For production scalability.
- Select your provider (AWS S3, DigitalOcean Spaces, Wasabi, etc.).
- Enter your Region, Bucket Name, Access Key, and Secret Key.
- Click Test Connection to verify permissions.
Go to Aperture Pro β Settings β Payments.
- Select your provider (e.g., Stripe, PayPal).
- Enter your API Keys (Publishable/Secret).
- Webhook Setup:
- Copy the Webhook Endpoint URL displayed on the settings page (e.g.,
https://site.com/wp-json/aperture/v1/webhooks/payment/stripe). - Add this endpoint in your Payment Provider's dashboard.
- Copy the Webhook Secret from the provider and paste it back into Aperture Pro settings.
- Copy the Webhook Endpoint URL displayed on the settings page (e.g.,
Go to Aperture Pro β Settings β Email.
- Configure the Sender Name and Sender Email.
- Ensure your WordPress install can send emails (use an SMTP plugin like WP Mail SMTP for reliability).
- Test by sending a magic link to yourself.
- Navigate to Aperture Pro β Projects β Add New.
- Enter a Client Name and Email.
- Set the Project Title (e.g., "Smith Family Session").
- Upload your first batch of images in the Uploads tab.
- Wait a moment for the Proof Queue to generate watermarked copies (check the Health dashboard if needed).
- Copy the Magic Link and open it in an Incognito window to see what your client sees.
- Local β simplest; uses server disk
- S3 + CloudFront β recommended for large ZIP deliveries
- Cloudinary / ImageKit β optimized for imageβheavy proof galleries
- Set a verified sender address for OTP + notifications
- Configure your provider to POST to:
https://your-site.com/wp-json/aperture/v1/webhooks/payment/{provider} - Add your webhook secret
- Validate via the builtβin test tool
- Enable OTP for secure downloads
- Clients receive a shortβlived code via email
POST /aperture/v1/uploads/start
POST /aperture/v1/uploads/{upload_id}/chunk
GET /aperture/v1/uploads/{upload_id}/progress
GET /aperture/v1/projects/{project_id}/proofs
POST /aperture/v1/proofs/{gallery_id}/select
POST /aperture/v1/proofs/{gallery_id}/comment
POST /aperture/v1/proofs/{gallery_id}/approve
POST /aperture/v1/projects/{project_id}/regenerate-download-token
GET /aperture/v1/download/{token}
POST /aperture/v1/download/{token}/request-otp
POST /aperture/v1/download/verify-otp
POST /aperture/v1/webhooks/payment/{provider}
GET /aperture/v1/projects/{id}/payment-summary
GET /aperture/v1/projects/{id}/payment-timeline
POST /aperture/v1/projects/{id}/retry-payment
- Encryption at rest for API keys + secrets
- Signed URLs for proofs + downloads
- Optional OTP verification
- Rate limiting for downloads and sensitive endpoints
- Session + email binding for download tokens
- REST middleware for request hygiene and abuse prevention
client-portal.jsβ uploader, proofs, OTP, downloads- SPA components for marketing and admin dashboards
- Unified uploaders with retry + streaming
- Proof generation queue with batch enqueueing
- Payment Abstraction Layer
- Workflow engine with idempotent transitions
- REST controllers with middleware stack
- Email queue + transactional delivery
- Add new storage providers via
UploaderInterface+StorageInterface - Add new payment providers via
PaymentProviderInterface - Add new admin cards via SPA component registry
- Proofs not generating β check Imagick/GD
- Webhook failures β verify signature header
- Upload issues β check PHP limits and storage credentials
- Download errors β verify token + OTP
Contributions welcome. Highβimpact areas:
- Additional payment providers
- Background ZIP generation
- Redisβbacked rate limiting
- Upload progress telemetry
- Endβtoβend upload/download tests
MIT License β see LICENSE for details.