Technical documentation for Renewed Renaissance Saleor platform
Saleor 3.20
PostgreSQL 16
Redis 7.2
Celery
Nginx Alpine
Docker Compose
Saleor Dashboard 3.20
Cloudflare Tunnel
https://www.renewed-renaissance.com/graphql/
Main GraphQL endpoint for all queries and mutations
https://www.renewed-renaissance.com/graphql/
GraphQL Playground (interactive documentation)
https://www.renewed-renaissance.com/health/
API health check endpoint
https://www.renewed-renaissance.com/static/
Static files (CSS, JS, fonts)
https://www.renewed-renaissance.com/media/
Product images and uploaded media
git clone https://bitbucket.org/wilsonify/renewed-renaissance-saleor.git cd renewed-renaissance-saleor
# Copy environment template cp deploy/01_dev/.env.example deploy/01_dev/.env # Edit configuration nano deploy/01_dev/.env
cd deploy/01_dev docker-compose up -d
docker-compose exec api python manage.py migrate
docker-compose exec api python manage.py createsuperuser --noinput
http://localhost:8000http://localhost:9000
| Environment | Directory | Ports | URL |
|---|---|---|---|
| Development | deploy/01_dev/ |
8000, 9000 | localhost |
| Staging | deploy/02_stage/ |
9080, 9081 | stage.renewed-renaissance.com |
| Production | deploy/03_prod/ |
8080, 8081 | www.renewed-renaissance.com |
cd deploy/02_stage # Start services docker-compose up -d # Run migrations docker-compose exec api python manage.py migrate # Create superuser (if needed) docker-compose exec api python manage.py createsuperuser --noinput # Restart nginx to pick up new container IPs docker-compose restart nginx
cd deploy/03_prod # Pull latest images docker-compose pull # Start services with force recreate docker-compose up -d --force-recreate # Run migrations docker-compose exec api python manage.py migrate # Collect static files docker-compose exec api python manage.py collectstatic --noinput
Products are defined as Markdown files in src/saleor-product-manager/products/:
--- name: "Elegant Bloom - Hand-Printed Dahlia Print" sku: "ELE/PRI/6IN" price: 180.00 category: "Art Prints" description: "A stunning hand-printed dahlia artwork..." trackInventory: true stockQuantity: 10 tags: - art - prints - dahlia --- # Elegant Bloom Additional markdown content for product description...
| Endpoint | Method | Description |
|---|---|---|
/api/sync |
POST | Sync products from Markdown to Saleor |
/api/products |
GET | List all product definitions |
/api/validate |
POST | Validate product definitions |
# Development (port 3001)
curl -X POST http://localhost:3001/api/sync \
-H "Content-Type: application/json" \
-d '{
"environment": "dev",
"productsDir": "/app/products",
"dryRun": false
}'
# Staging (port 3002)
curl -X POST http://localhost:3002/api/sync \
-H "Content-Type: application/json" \
-d '{
"environment": "stage",
"productsDir": "/app/products",
"dryRun": false
}'
{
"created": [],
"updated": [
"Elegant Bloom - Hand-Printed Dahlia Print",
"Eternal Flight - Handcrafted Origami Crane Print",
"Ethereal Drift - Handcrafted Jellyfish Print"
],
"skipped": [],
"deleted": [],
"errors": [],
"dryRun": false
}
query ListProducts {
products(first: 10, channel: "default-channel") {
edges {
node {
id
name
slug
description
thumbnail {
url
}
variants {
id
name
sku
pricing {
price {
gross {
amount
currency
}
}
}
}
}
}
}
}
query GetProduct($slug: String!) {
product(slug: $slug, channel: "default-channel") {
id
name
description
category {
name
}
images {
url
alt
}
variants {
id
name
sku
quantityAvailable
}
}
}
# Variables
{
"slug": "vintage-pocket-watch"
}
mutation CreateCheckout($input: CheckoutCreateInput!) {
checkoutCreate(input: $input) {
checkout {
id
token
totalPrice {
gross {
amount
currency
}
}
lines {
id
quantity
variant {
name
}
}
}
errors {
field
message
}
}
}
# Variables
{
"input": {
"channel": "default-channel",
"email": "customer@example.com",
"lines": [
{
"quantity": 1,
"variantId": "UHJvZHVjdFZhcmlhbnQ6MQ=="
}
]
}
}
mutation AddToCheckout($checkoutId: ID!, $lines: [CheckoutLineInput!]!) {
checkoutLinesAdd(
checkoutId: $checkoutId
lines: $lines
) {
checkout {
id
lines {
quantity
variant {
name
}
}
}
errors {
field
message
}
}
}
# Variables
{
"checkoutId": "Q2hlY2tvdXQ6MQ==",
"lines": [
{
"quantity": 2,
"variantId": "UHJvZHVjdFZhcmlhbnQ6Mg=="
}
]
}
mutation TokenAuth($email: String!, $password: String!) {
tokenCreate(email: $email, password: $password) {
token
refreshToken
csrfToken
user {
id
email
firstName
lastName
}
errors {
field
message
}
}
}
# Variables
{
"email": "your-email@example.com",
"password": "your-password"
}
# Add to request headers
{
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
mutation RefreshToken($refreshToken: String!) {
tokenRefresh(refreshToken: $refreshToken) {
token
errors {
field
message
}
}
}
# Start all services docker-compose up -d # Stop all services docker-compose down # Restart specific service docker-compose restart api # View logs docker-compose logs -f api # View all service status docker-compose ps # Force recreate (reload env vars) docker-compose up -d --force-recreate api worker
# Run migrations docker-compose exec api python manage.py migrate # Create migrations docker-compose exec api python manage.py makemigrations # Database shell docker-compose exec db psql -U saleor saleor # Backup database docker-compose exec db pg_dump -U saleor saleor > backup.sql # Restore database cat backup.sql | docker-compose exec -T db psql -U saleor saleor
# Django shell docker-compose exec api python manage.py shell # Create superuser docker-compose exec api python manage.py createsuperuser # Collect static files docker-compose exec api python manage.py collectstatic --noinput # Run tests docker-compose exec api pytest # Check for issues docker-compose exec api python manage.py check
| Variable | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgres://user:pass@db:5432/saleor |
REDIS_URL |
Redis connection string | redis://:pass@redis:6379/0 |
SECRET_KEY |
Django secret key (50+ chars) | Generated random string |
ALLOWED_HOSTS |
Comma-separated domains | www.renewed-renaissance.com,localhost |
ALLOWED_CLIENT_HOSTS |
Allowed GraphQL clients | www.renewed-renaissance.com,localhost |
| Variable | Description | Default |
|---|---|---|
DEBUG |
Enable debug mode | False |
SENTRY_DSN |
Error tracking URL | None |
EMAIL_URL |
SMTP configuration | smtp://localhost:1025 |
DEFAULT_FROM_EMAIL |
Sender email address | noreply@example.com |
RSA_PRIVATE_KEY |
JWT signing key | Auto-generated in DEBUG |
# All tests docker-compose exec api pytest # Specific test file docker-compose exec api pytest tests/test_products.py # With coverage docker-compose exec api pytest --cov=saleor # Verbose output docker-compose exec api pytest -v
https://www.renewed-renaissance.com/graphql/ to use the GraphQL Playground.# All services docker-compose logs -f # Specific service docker-compose logs -f api docker-compose logs -f nginx docker-compose logs -f worker # Last 100 lines docker-compose logs --tail=100 api # Since specific time docker-compose logs --since 2025-11-27T10:00:00 api
# Check all container statuses docker-compose ps # Inspect specific container docker inspect saleor-api-prod # Resource usage docker stats
name: Deploy to Staging
on:
push:
branches: [staging]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to staging
run: |
ssh user@server 'cd /path/to/deploy/02_stage && \
docker-compose pull && \
docker-compose up -d --force-recreate && \
docker-compose exec -T api python manage.py migrate'
docker-compose ps apidocker-compose logs apidocker-compose restart nginxpython manage.py migrate --fakepython manage.py migrate app_name migration_namepython manage.py collectstatic# In .env file DEBUG=True ENABLE_DEBUG_TOOLBAR=True # Restart API docker-compose restart api