feat: add automated Printify mockup generation & POD sample content
Printify Integration: - Add Printify API client module with full HTTP wrapper - Add mockup generator with dynamic "cover" scaling algorithm - Create Mix task (mix generate_mockups) for automated mockup generation - Support --cleanup flag to delete products after downloading mockups - Calculate optimal scale factor based on artwork/placeholder aspect ratios - Handle landscape artwork on portrait print areas without white space Sample Content (16 products across 5 POD categories): - Art Prints: Mountain Sunrise, Ocean Waves, Wildflower Meadow, Geometric Abstract, Botanical Illustration - Apparel: Forest Silhouette T-Shirt, Forest Light Hoodie - Tote Bags: Wildflower Meadow, Sunset Gradient - Homewares: Fern Leaf Mug, Ocean Waves Cushion, Night Sky Blanket - Stationery: Autumn Leaves Notebook, Monstera Leaf Notebook - Accessories: Monstera Leaf Phone Case, Blue Waves Laptop Sleeve Preview Data Updates: - Replace generic e-commerce products with POD-focused items - Update categories to POD-relevant: Art Prints, Apparel, Homewares, Stationery, Accessories - Update cart drawer items to match new product range - Refresh testimonials with POD-appropriate reviews Theme Content Updates: - Update hero section for "Wildprint Studio" brand identity - Rewrite about page narrative with humble, British, personal tone - Update search hints to nature/POD relevant terms - Add mockups directory to static paths 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
201
lib/mix/tasks/generate_mockups.ex
Normal file
201
lib/mix/tasks/generate_mockups.ex
Normal file
@@ -0,0 +1,201 @@
|
||||
defmodule Mix.Tasks.GenerateMockups do
|
||||
@moduledoc """
|
||||
Generates product mockups using the Printify API.
|
||||
|
||||
This task automates the creation of product mockups for the SimpleshopTheme
|
||||
sample content. It downloads artwork from Unsplash, uploads it to Printify,
|
||||
creates products, and downloads the generated mockups.
|
||||
|
||||
## Requirements
|
||||
|
||||
- A Printify account with API access
|
||||
- The PRINTIFY_API_TOKEN environment variable must be set
|
||||
|
||||
## Usage
|
||||
|
||||
# Generate mockups (keeps products in Printify)
|
||||
mix generate_mockups
|
||||
|
||||
# Generate mockups and delete products afterwards
|
||||
mix generate_mockups --cleanup
|
||||
|
||||
# Search for available blueprints
|
||||
mix generate_mockups --search "poster"
|
||||
|
||||
# List all blueprints
|
||||
mix generate_mockups --list-blueprints
|
||||
|
||||
## Output
|
||||
|
||||
Mockup images are saved to: priv/static/mockups/
|
||||
"""
|
||||
|
||||
use Mix.Task
|
||||
|
||||
alias SimpleshopTheme.Printify.MockupGenerator
|
||||
|
||||
@shortdoc "Generates product mockups using Printify API"
|
||||
|
||||
@impl Mix.Task
|
||||
def run(args) do
|
||||
# Start required applications
|
||||
Mix.Task.run("app.start")
|
||||
|
||||
{opts, _, _} =
|
||||
OptionParser.parse(args,
|
||||
switches: [
|
||||
cleanup: :boolean,
|
||||
search: :string,
|
||||
list_blueprints: :boolean,
|
||||
help: :boolean
|
||||
],
|
||||
aliases: [
|
||||
c: :cleanup,
|
||||
s: :search,
|
||||
l: :list_blueprints,
|
||||
h: :help
|
||||
]
|
||||
)
|
||||
|
||||
cond do
|
||||
opts[:help] ->
|
||||
print_help()
|
||||
|
||||
opts[:list_blueprints] ->
|
||||
list_blueprints()
|
||||
|
||||
opts[:search] ->
|
||||
search_blueprints(opts[:search])
|
||||
|
||||
true ->
|
||||
generate_mockups(opts)
|
||||
end
|
||||
end
|
||||
|
||||
defp print_help do
|
||||
Mix.shell().info("""
|
||||
|
||||
Printify Mockup Generator
|
||||
=========================
|
||||
|
||||
Generates product mockups using the Printify API.
|
||||
|
||||
Usage:
|
||||
mix generate_mockups [options]
|
||||
|
||||
Options:
|
||||
--cleanup, -c Delete created products from Printify after downloading mockups
|
||||
--search, -s TERM Search for blueprints by name
|
||||
--list-blueprints List all available blueprint IDs and names
|
||||
--help, -h Show this help message
|
||||
|
||||
Environment:
|
||||
PRINTIFY_API_TOKEN Required. Your Printify API token.
|
||||
|
||||
Examples:
|
||||
# Generate all mockups
|
||||
export PRINTIFY_API_TOKEN="your-token"
|
||||
mix generate_mockups
|
||||
|
||||
# Generate and cleanup
|
||||
mix generate_mockups --cleanup
|
||||
|
||||
# Find blueprint IDs
|
||||
mix generate_mockups --search "poster"
|
||||
""")
|
||||
end
|
||||
|
||||
defp list_blueprints do
|
||||
Mix.shell().info("Fetching blueprints from Printify...")
|
||||
|
||||
case MockupGenerator.list_blueprints() do
|
||||
blueprints when is_list(blueprints) ->
|
||||
Mix.shell().info("\nAvailable Blueprints:\n")
|
||||
|
||||
blueprints
|
||||
|> Enum.each(fn {id, title} ->
|
||||
Mix.shell().info(" #{id}: #{title}")
|
||||
end)
|
||||
|
||||
Mix.shell().info("\nTotal: #{length(blueprints)} blueprints")
|
||||
|
||||
{:error, reason} ->
|
||||
Mix.shell().error("Error fetching blueprints: #{inspect(reason)}")
|
||||
end
|
||||
end
|
||||
|
||||
defp search_blueprints(term) do
|
||||
Mix.shell().info("Searching for blueprints matching '#{term}'...")
|
||||
|
||||
case MockupGenerator.search_blueprints(term) do
|
||||
results when is_list(results) ->
|
||||
if length(results) == 0 do
|
||||
Mix.shell().info("No blueprints found matching '#{term}'")
|
||||
else
|
||||
Mix.shell().info("\nMatching Blueprints:\n")
|
||||
|
||||
results
|
||||
|> Enum.each(fn {id, title} ->
|
||||
Mix.shell().info(" #{id}: #{title}")
|
||||
end)
|
||||
|
||||
Mix.shell().info("\nFound: #{length(results)} blueprints")
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
Mix.shell().error("Error searching blueprints: #{inspect(reason)}")
|
||||
end
|
||||
end
|
||||
|
||||
defp generate_mockups(opts) do
|
||||
cleanup = Keyword.get(opts, :cleanup, false)
|
||||
|
||||
Mix.shell().info("""
|
||||
|
||||
╔═══════════════════════════════════════════╗
|
||||
║ Printify Mockup Generator ║
|
||||
╠═══════════════════════════════════════════╣
|
||||
║ Cleanup mode: #{if cleanup, do: "ON ", else: "OFF"} ║
|
||||
╚═══════════════════════════════════════════╝
|
||||
|
||||
""")
|
||||
|
||||
# Verify API token is set
|
||||
case System.get_env("PRINTIFY_API_TOKEN") do
|
||||
nil ->
|
||||
Mix.shell().error("""
|
||||
Error: PRINTIFY_API_TOKEN environment variable is not set.
|
||||
|
||||
To get your API token:
|
||||
1. Log in to Printify
|
||||
2. Go to Settings > API tokens
|
||||
3. Create a new token with required permissions
|
||||
|
||||
Then run:
|
||||
export PRINTIFY_API_TOKEN="your-token"
|
||||
mix generate_mockups
|
||||
""")
|
||||
|
||||
_token ->
|
||||
results = MockupGenerator.generate_all(cleanup: cleanup)
|
||||
|
||||
# Summary
|
||||
successful = Enum.count(results, &match?({:ok, _, _, _}, &1))
|
||||
failed = Enum.count(results, &match?({:error, _, _}, &1))
|
||||
|
||||
Mix.shell().info("""
|
||||
|
||||
═══════════════════════════════════════════
|
||||
Summary
|
||||
═══════════════════════════════════════════
|
||||
Successful: #{successful}
|
||||
Failed: #{failed}
|
||||
═══════════════════════════════════════════
|
||||
""")
|
||||
|
||||
if failed > 0 do
|
||||
Mix.shell().error("Some products failed to generate. Check the output above for details.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user