Register AdSense, artwork review, comment captcha, lazy collections, and upload review props, and document the matching env vars and CLI commands.
498 lines
16 KiB
Bash
498 lines
16 KiB
Bash
APP_NAME=Laravel
|
|
APP_ENV=local
|
|
APP_KEY=
|
|
APP_DEBUG=true
|
|
APP_URL=http://localhost
|
|
|
|
# Maximum secondary artwork categories in addition to the primary category.
|
|
CATEGORIES_MAX_SECONDARY=5
|
|
|
|
# Artwork original downloads: PHP fallback unless nginx X-Accel is configured.
|
|
# Leave false until the internal location exists and has been verified.
|
|
DOWNLOAD_ACCEL_ENABLED=false
|
|
DOWNLOAD_ACCEL_PATH=/internal/originals
|
|
|
|
SECURITY_REPORT_ENABLED=true
|
|
SECURITY_REPORT_NOTIFY_EMAIL=
|
|
SECURITY_REPORT_SCAN_NPM=true
|
|
SECURITY_REPORT_SCAN_COMPOSER=true
|
|
SECURITY_REPORT_STORE_RAW=true
|
|
SECURITY_REPORT_MAX_RAW_KB=512
|
|
SECURITY_REPORT_FAIL_ON_HIGH=false
|
|
SECURITY_REPORT_FAIL_ON_CRITICAL=false
|
|
|
|
APP_LOCALE=en
|
|
APP_FALLBACK_LOCALE=en
|
|
APP_FAKER_LOCALE=en_US
|
|
|
|
APP_MAINTENANCE_DRIVER=file
|
|
# APP_MAINTENANCE_STORE=database
|
|
|
|
# PHP_CLI_SERVER_WORKERS=4
|
|
|
|
BCRYPT_ROUNDS=12
|
|
|
|
LOG_CHANNEL=stack
|
|
LOG_STACK=single
|
|
LOG_DEPRECATIONS_CHANNEL=null
|
|
LOG_LEVEL=debug
|
|
|
|
# M12 — slow Laravel HTTP log (threshold only; disable for zero overhead)
|
|
HTTP_SLOW_REQUEST_LOG_ENABLED=false
|
|
HTTP_SLOW_REQUEST_MS=750
|
|
HTTP_SLOW_REQUEST_LOG_DAYS=14
|
|
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=3306
|
|
DB_DATABASE=skinbase26
|
|
DB_USERNAME=root
|
|
DB_PASSWORD=
|
|
|
|
# Legacy database connection (projekti_old_skinbase)
|
|
LEGACY_DB_CONNECTION=mysql
|
|
LEGACY_DB_HOST=127.0.0.1
|
|
LEGACY_DB_PORT=3306
|
|
LEGACY_DB_DATABASE=projekti_old_skinbase
|
|
LEGACY_DB_USERNAME=root
|
|
LEGACY_DB_PASSWORD=
|
|
|
|
SESSION_DRIVER=database
|
|
SESSION_LIFETIME=120
|
|
SESSION_ENCRYPT=false
|
|
SESSION_PATH=/
|
|
SESSION_DOMAIN=null
|
|
|
|
# Skinbase conditional public sessions
|
|
SKINBASE_CONDITIONAL_SESSIONS_ENABLED=true
|
|
SKINBASE_SKIP_ANONYMOUS_PUBLIC_GET_SESSIONS=true
|
|
SKINBASE_SKIP_BOT_PUBLIC_GET_SESSIONS=true
|
|
|
|
# Debug only; do not enable permanently in production
|
|
SKINBASE_SESSION_DEBUG_HEADER=false
|
|
|
|
BROADCAST_CONNECTION=reverb
|
|
FILESYSTEM_DISK=local
|
|
QUEUE_CONNECTION=redis
|
|
|
|
# Comment spam protection: observe records scores without changing visibility.
|
|
COMMENT_SPAM_ENABLED=true
|
|
COMMENT_SPAM_MODE=enforce
|
|
COMMENT_SPAM_AI_ENABLED=true
|
|
COMMENT_SPAM_AI_PROVIDER=together
|
|
# Supported: Prism-ML/Ternary-Bonsai-27B or meta-llama/Llama-3.2-3B-Instruct-Turbo
|
|
COMMENT_SPAM_AI_MODEL=meta-llama/Llama-3.2-3B-Instruct-Turbo
|
|
COMMENT_SPAM_AI_TIMEOUT=5
|
|
TOGETHER_API_KEY=
|
|
TOGETHER_API_BASE_URL=https://api.together.xyz/v1
|
|
COMMENT_SPAM_LOCAL_SAFE_MAX=29
|
|
COMMENT_SPAM_LOCAL_SPAM_MIN=70
|
|
COMMENT_SPAM_AI_SPAM_MIN=70
|
|
COMMENT_SPAM_SIGNATURE_CACHE_MINUTES=1440
|
|
COMMENT_TURNSTILE_ENABLED=false
|
|
COMMENT_TURNSTILE_SITE_KEY=
|
|
COMMENT_TURNSTILE_SECRET_KEY=
|
|
COMMENT_TURNSTILE_RISK_THRESHOLD=40
|
|
COMMENT_TURNSTILE_FAIL_OPEN=false
|
|
# Must exceed Horizon supervisor-default timeout (960s). Production used 90s
|
|
# and nightly RecComputeSimilar* jobs failed with MaxAttemptsExceeded.
|
|
REDIS_QUEUE_RETRY_AFTER=1080
|
|
|
|
# Collection maintenance / forum AI jobs have no Horizon consumer.
|
|
# Leave false until a dedicated supervisor exists (M7).
|
|
COLLECTIONS_V5_DISPATCH_ENABLED=false
|
|
FORUM_QUEUE_DISPATCH_ENABLED=false
|
|
ONLINE_VISITOR_INDEX_READ_LIMIT=2000
|
|
ONLINE_VISITOR_INDEX_PRUNE_ENABLED=false
|
|
ONLINE_VISITOR_INDEX_PRUNE_SCAN_COUNT=500
|
|
ONLINE_VISITOR_INDEX_PRUNE_MAX_BATCHES=200
|
|
ONLINE_VISITOR_INDEX_PRUNE_SLEEP_MS=25
|
|
# RankBuildScopeListsJob unique lock (seconds). Must exceed queue wait + 300s timeout.
|
|
RANK_SCOPE_JOB_UNIQUE_FOR=21600
|
|
|
|
# Hourly artwork metric snapshots (heat / rising / monthly leaderboards).
|
|
# Production currently holds ~7 days because the scheduler passed --keep-days=7.
|
|
# Monthly leaderboards and Studio 30d views need 30 days of hourly history.
|
|
ARTWORK_METRIC_HOURLY_RETENTION_DAYS=30
|
|
ARTWORK_METRIC_HOURLY_PRUNE_CHUNK=5000
|
|
ARTWORK_METRIC_HOURLY_PRUNE_SLEEP_MS=50
|
|
|
|
MESSAGING_REALTIME=true
|
|
MESSAGING_BROADCAST_QUEUE=broadcasts
|
|
MESSAGING_TYPING_TTL=8
|
|
MESSAGING_TYPING_CACHE_STORE=redis
|
|
MESSAGING_PRESENCE_TTL=90
|
|
MESSAGING_CONVERSATION_PRESENCE_TTL=45
|
|
MESSAGING_PRESENCE_CACHE_STORE=redis
|
|
MESSAGING_RECOVERY_MAX_MESSAGES=100
|
|
MESSAGING_OFFLINE_FALLBACK_ONLY=true
|
|
|
|
HORIZON_NAME=skinbase-nova
|
|
HORIZON_PATH=horizon
|
|
HORIZON_PREFIX=skinbase_nova_horizon:
|
|
|
|
REVERB_APP_ID=skinbase-local
|
|
REVERB_APP_KEY=skinbase-local-key
|
|
REVERB_APP_SECRET=skinbase-local-secret
|
|
REVERB_HOST=127.0.0.1
|
|
REVERB_PORT=8080
|
|
REVERB_SCHEME=http
|
|
REVERB_SERVER_HOST=0.0.0.0
|
|
REVERB_SERVER_PORT=8080
|
|
REVERB_SERVER_PATH=
|
|
REVERB_SCALING_ENABLED=false
|
|
|
|
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
|
|
VITE_REVERB_HOST="${REVERB_HOST}"
|
|
VITE_REVERB_PORT="${REVERB_PORT}"
|
|
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
|
|
|
|
# Upload UI feature flag (legacy upload remains default unless explicitly enabled)
|
|
SKINBASE_UPLOADS_V2=false
|
|
|
|
# Upload transport tuning
|
|
UPLOAD_CHUNK_MAX_BYTES=5242880
|
|
UPLOAD_CHUNK_REQUEST_TIMEOUT_MS=45000
|
|
UPLOAD_RATE_CHUNK_USER=180
|
|
UPLOAD_RATE_CHUNK_IP=360
|
|
|
|
# New accounts without this many moderator/legacy published artworks go to review.
|
|
# Queued uploads and trusted_auto publishes do not count, so a new user's 6th upload stays hidden.
|
|
UPLOAD_MIN_APPROVED_UPLOADS=5
|
|
UPLOAD_MIN_ACCOUNT_AGE_DAYS=7
|
|
UPLOAD_MAX_UNTRUSTED_LEVEL=1
|
|
UPLOAD_BOT_RISK_REVIEW_THRESHOLD=40
|
|
|
|
# Draft abuse prevention controls
|
|
SKINBASE_MAX_DRAFTS=10
|
|
SKINBASE_MAX_DRAFT_STORAGE_MB=1024
|
|
SKINBASE_DUPLICATE_HASH_POLICY=block
|
|
|
|
# Vision / AI auto-tagging (local defaults)
|
|
VISION_ENABLED=true
|
|
VISION_QUEUE=default
|
|
VISION_IMAGE_VARIANT=md
|
|
VISION_GATEWAY_URL=
|
|
VISION_GATEWAY_TIMEOUT=10
|
|
VISION_GATEWAY_CONNECT_TIMEOUT=3
|
|
VISION_VECTOR_GATEWAY_ENABLED=true
|
|
VISION_VECTOR_GATEWAY_URL=
|
|
VISION_VECTOR_GATEWAY_API_KEY=
|
|
VISION_VECTOR_GATEWAY_COLLECTION=images
|
|
VISION_VECTOR_GATEWAY_TIMEOUT=20
|
|
VISION_VECTOR_GATEWAY_CONNECT_TIMEOUT=5
|
|
VISION_VECTOR_GATEWAY_RETRIES=1
|
|
VISION_VECTOR_GATEWAY_RETRY_DELAY_MS=250
|
|
VISION_VECTOR_GATEWAY_UPSERT_ENDPOINT=/vectors/upsert
|
|
VISION_VECTOR_GATEWAY_SEARCH_ENDPOINT=/vectors/search
|
|
VISION_VECTOR_GATEWAY_SEARCH_FILE_ENDPOINT=/vectors/search/file
|
|
VISION_VECTOR_GATEWAY_SEARCH_TIMEOUT=6
|
|
VISION_VECTOR_GATEWAY_SEARCH_CONNECT_TIMEOUT=2
|
|
VISION_VECTOR_GATEWAY_SEARCH_RETRIES=0
|
|
VISION_VECTOR_GATEWAY_CIRCUIT_SECONDS=30
|
|
VISION_VECTOR_GATEWAY_DELETE_ENDPOINT=/vectors/delete
|
|
VISION_VECTOR_GATEWAY_COLLECTIONS_ENDPOINT=/vectors/collections
|
|
|
|
# CLIP service (set base URL to enable CLIP calls)
|
|
CLIP_BASE_URL=
|
|
CLIP_ANALYZE_ENDPOINT=/analyze
|
|
CLIP_TIMEOUT_SECONDS=8
|
|
CLIP_CONNECT_TIMEOUT_SECONDS=2
|
|
CLIP_HTTP_RETRIES=1
|
|
CLIP_HTTP_RETRY_DELAY_MS=200
|
|
CLIP_EMBED_ENDPOINT=/embed
|
|
CLIP_EMBED_TIMEOUT_SECONDS=8
|
|
CLIP_EMBED_CONNECT_TIMEOUT_SECONDS=2
|
|
CLIP_EMBED_HTTP_RETRIES=1
|
|
CLIP_EMBED_HTTP_RETRY_DELAY_MS=200
|
|
|
|
# Similar artworks / embedding pipeline
|
|
RECOMMENDATIONS_QUEUE=${VISION_QUEUE}
|
|
RECOMMENDATIONS_EMBEDDING_ENABLED=true
|
|
RECOMMENDATIONS_EMBEDDING_MODEL=clip
|
|
RECOMMENDATIONS_EMBEDDING_MODEL_VERSION=v1
|
|
RECOMMENDATIONS_ALGO_VERSION=clip-cosine-v1
|
|
RECOMMENDATIONS_AB_ALGO_VERSIONS=clip-cosine-v1
|
|
RECOMMENDATIONS_MIN_DIM=64
|
|
RECOMMENDATIONS_MAX_DIM=4096
|
|
RECOMMENDATIONS_BACKFILL_BATCH=200
|
|
SIMILARITY_VECTOR_ENABLED=false
|
|
SIMILARITY_VECTOR_ADAPTER=pgvector
|
|
|
|
# Personalized discovery foundation (Phase 8)
|
|
DISCOVERY_QUEUE=${RECOMMENDATIONS_QUEUE}
|
|
DISCOVERY_PROFILE_VERSION=profile-v1
|
|
DISCOVERY_EVENT_VERSION=event-v1
|
|
DISCOVERY_ALGO_VERSION=${RECOMMENDATIONS_ALGO_VERSION}
|
|
DISCOVERY_CACHE_VERSION=cache-v1
|
|
DISCOVERY_DECAY_HALF_LIFE_HOURS=72
|
|
DISCOVERY_WEIGHT_VIEW=1
|
|
DISCOVERY_WEIGHT_CLICK=2
|
|
DISCOVERY_WEIGHT_FAVORITE=4
|
|
DISCOVERY_WEIGHT_DOWNLOAD=3
|
|
DISCOVERY_CACHE_TTL_MINUTES=60
|
|
DISCOVERY_V3_ENABLED=false
|
|
DISCOVERY_V3_CACHE_VERSION=cache-v3
|
|
DISCOVERY_V3_CACHE_TTL_MINUTES=5
|
|
DISCOVERY_V3_VECTOR_SIMILARITY_WEIGHT=0.8
|
|
DISCOVERY_V3_VECTOR_BASE_SCORE=0.75
|
|
DISCOVERY_V3_MAX_SEED_ARTWORKS=3
|
|
DISCOVERY_V3_VECTOR_CANDIDATE_POOL=60
|
|
DISCOVERY_V3_SECTION_SIMILAR_STYLE_LIMIT=3
|
|
DISCOVERY_V3_SECTION_YOU_MAY_ALSO_LIKE_LIMIT=6
|
|
DISCOVERY_V3_SECTION_VISUALLY_RELATED_LIMIT=6
|
|
DISCOVERY_RANKING_WEIGHTS_VERSION=rank-w-v1
|
|
DISCOVERY_RANKING_W1=0.65
|
|
DISCOVERY_RANKING_W2=0.20
|
|
DISCOVERY_RANKING_W3=0.10
|
|
DISCOVERY_RANKING_W4=0.05
|
|
DISCOVERY_RANKING_WEIGHTS_VERSION_CLIP_COSINE_V1=rank-w-v1
|
|
DISCOVERY_RANKING_W1_CLIP_COSINE_V1=0.65
|
|
DISCOVERY_RANKING_W2_CLIP_COSINE_V1=0.20
|
|
DISCOVERY_RANKING_W3_CLIP_COSINE_V1=0.10
|
|
DISCOVERY_RANKING_W4_CLIP_COSINE_V1=0.05
|
|
DISCOVERY_RANKING_WEIGHTS_VERSION_CLIP_COSINE_V2=rank-w-v2-prod-1
|
|
DISCOVERY_RANKING_W1_CLIP_COSINE_V2=0.52
|
|
DISCOVERY_RANKING_W2_CLIP_COSINE_V2=0.23
|
|
DISCOVERY_RANKING_W3_CLIP_COSINE_V2=0.15
|
|
DISCOVERY_RANKING_W4_CLIP_COSINE_V2=0.10
|
|
DISCOVERY_ROLLOUT_ENABLED=false
|
|
DISCOVERY_ROLLOUT_BASELINE_ALGO_VERSION=clip-cosine-v1
|
|
DISCOVERY_ROLLOUT_CANDIDATE_ALGO_VERSION=clip-cosine-v2
|
|
DISCOVERY_ROLLOUT_ACTIVE_GATE=g10
|
|
DISCOVERY_ROLLOUT_GATE_10_PERCENT=10
|
|
DISCOVERY_ROLLOUT_GATE_50_PERCENT=50
|
|
DISCOVERY_ROLLOUT_GATE_100_PERCENT=100
|
|
DISCOVERY_FORCE_ALGO_VERSION=
|
|
DISCOVERY_ROLLOUT_WARN_CTR_DROP_PCT=3
|
|
DISCOVERY_ROLLOUT_ROLLBACK_CTR_DROP_PCT=5
|
|
DISCOVERY_ROLLOUT_WARN_LONG_DWELL_DROP_PCT=4
|
|
DISCOVERY_ROLLOUT_ROLLBACK_LONG_DWELL_DROP_PCT=8
|
|
DISCOVERY_ROLLOUT_WARN_DIVERSITY_CONCENTRATION_RISE_PCT=10
|
|
DISCOVERY_ROLLOUT_ROLLBACK_DIVERSITY_CONCENTRATION_RISE_PCT=15
|
|
DISCOVERY_EVAL_WEIGHT_CTR=0.45
|
|
DISCOVERY_EVAL_WEIGHT_SAVE_RATE=0.35
|
|
DISCOVERY_EVAL_WEIGHT_LONG_DWELL=0.25
|
|
DISCOVERY_EVAL_WEIGHT_BOUNCE_PENALTY=0.15
|
|
DISCOVERY_EVAL_SAVE_RATE_INFORMATIONAL=true
|
|
|
|
# YOLO service (optional)
|
|
YOLO_ENABLED=true
|
|
YOLO_BASE_URL=
|
|
YOLO_ANALYZE_ENDPOINT=/analyze
|
|
YOLO_TIMEOUT_SECONDS=8
|
|
YOLO_CONNECT_TIMEOUT_SECONDS=2
|
|
YOLO_HTTP_RETRIES=1
|
|
YOLO_HTTP_RETRY_DELAY_MS=200
|
|
YOLO_PHOTOGRAPHY_ONLY=true
|
|
|
|
# Academy feature flags
|
|
SKINBASE_ACADEMY_ENABLED=true
|
|
SKINBASE_ACADEMY_PAYMENTS_ENABLED=false
|
|
ACADEMY_BILLING_ENABLED=false
|
|
ACADEMY_STRIPE_SUBSCRIPTION_NAME=academy
|
|
|
|
# Stripe / Cashier
|
|
STRIPE_KEY=pk_test_xxx
|
|
STRIPE_SECRET=sk_test_xxx
|
|
STRIPE_WEBHOOK_SECRET=whsec_xxx
|
|
CASHIER_CURRENCY=eur
|
|
CASHIER_CURRENCY_LOCALE=sl_SI
|
|
|
|
# Academy billing price IDs
|
|
ACADEMY_CREATOR_MONTHLY_PRICE_ID=price_xxx
|
|
ACADEMY_PRO_MONTHLY_PRICE_ID=price_xxx
|
|
|
|
# Stripe expects real price object IDs that start with price_, not product IDs like prod_...
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Production examples (uncomment and adjust)
|
|
# -----------------------------------------------------------------------------
|
|
# VISION_ENABLED=true
|
|
# VISION_QUEUE=vision
|
|
# VISION_IMAGE_VARIANT=md
|
|
# VISION_GATEWAY_URL=https://vision.internal
|
|
# VISION_GATEWAY_TIMEOUT=8
|
|
# VISION_GATEWAY_CONNECT_TIMEOUT=2
|
|
#
|
|
# CLIP_BASE_URL=https://clip.internal
|
|
# CLIP_ANALYZE_ENDPOINT=/analyze
|
|
# CLIP_TIMEOUT_SECONDS=5
|
|
# CLIP_CONNECT_TIMEOUT_SECONDS=1
|
|
# CLIP_HTTP_RETRIES=1
|
|
# CLIP_HTTP_RETRY_DELAY_MS=150
|
|
# CLIP_EMBED_ENDPOINT=/embed
|
|
# CLIP_EMBED_TIMEOUT_SECONDS=5
|
|
# CLIP_EMBED_CONNECT_TIMEOUT_SECONDS=1
|
|
# CLIP_EMBED_HTTP_RETRIES=1
|
|
# CLIP_EMBED_HTTP_RETRY_DELAY_MS=150
|
|
# RECOMMENDATIONS_QUEUE=vision
|
|
# RECOMMENDATIONS_EMBEDDING_ENABLED=true
|
|
# RECOMMENDATIONS_EMBEDDING_MODEL=clip
|
|
# RECOMMENDATIONS_EMBEDDING_MODEL_VERSION=v1
|
|
# RECOMMENDATIONS_ALGO_VERSION=clip-cosine-v1
|
|
# RECOMMENDATIONS_AB_ALGO_VERSIONS=clip-cosine-v1,clip-cosine-v2
|
|
# RECOMMENDATIONS_BACKFILL_BATCH=250
|
|
# DISCOVERY_QUEUE=vision
|
|
# DISCOVERY_PROFILE_VERSION=profile-v1
|
|
# DISCOVERY_EVENT_VERSION=event-v1
|
|
# DISCOVERY_ALGO_VERSION=clip-cosine-v1
|
|
# DISCOVERY_CACHE_VERSION=cache-v1
|
|
# DISCOVERY_DECAY_HALF_LIFE_HOURS=72
|
|
# DISCOVERY_WEIGHT_VIEW=1
|
|
# DISCOVERY_WEIGHT_CLICK=2
|
|
# DISCOVERY_WEIGHT_FAVORITE=4
|
|
# DISCOVERY_WEIGHT_DOWNLOAD=3
|
|
# DISCOVERY_V3_ENABLED=true
|
|
# DISCOVERY_V3_CACHE_VERSION=cache-v3
|
|
# DISCOVERY_V3_CACHE_TTL_MINUTES=5
|
|
# DISCOVERY_V3_VECTOR_SIMILARITY_WEIGHT=0.8
|
|
# DISCOVERY_V3_VECTOR_BASE_SCORE=0.75
|
|
# DISCOVERY_V3_MAX_SEED_ARTWORKS=3
|
|
# DISCOVERY_V3_VECTOR_CANDIDATE_POOL=60
|
|
# DISCOVERY_V3_SECTION_SIMILAR_STYLE_LIMIT=3
|
|
# DISCOVERY_V3_SECTION_YOU_MAY_ALSO_LIKE_LIMIT=6
|
|
# DISCOVERY_V3_SECTION_VISUALLY_RELATED_LIMIT=6
|
|
# DISCOVERY_RANKING_WEIGHTS_VERSION=rank-w-v1
|
|
# DISCOVERY_RANKING_W1=0.65
|
|
# DISCOVERY_RANKING_W2=0.20
|
|
# DISCOVERY_RANKING_W3=0.10
|
|
# DISCOVERY_RANKING_W4=0.05
|
|
#
|
|
# YOLO_ENABLED=true
|
|
# YOLO_BASE_URL=https://yolo.internal
|
|
# YOLO_ANALYZE_ENDPOINT=/analyze
|
|
# YOLO_TIMEOUT_SECONDS=5
|
|
# YOLO_CONNECT_TIMEOUT_SECONDS=1
|
|
# YOLO_HTTP_RETRIES=1
|
|
# YOLO_HTTP_RETRY_DELAY_MS=150
|
|
# YOLO_PHOTOGRAPHY_ONLY=true
|
|
|
|
CACHE_STORE=database
|
|
# CACHE_PREFIX=
|
|
|
|
MEMCACHED_HOST=127.0.0.1
|
|
|
|
REDIS_CLIENT=phpredis
|
|
REDIS_HOST=127.0.0.1
|
|
REDIS_PASSWORD=null
|
|
REDIS_PORT=6379
|
|
|
|
MAIL_MAILER=log
|
|
MAIL_SCHEME=null
|
|
MAIL_HOST=127.0.0.1
|
|
MAIL_PORT=2525
|
|
MAIL_USERNAME=null
|
|
MAIL_PASSWORD=null
|
|
MAIL_FROM_ADDRESS="[email protected]"
|
|
MAIL_FROM_NAME="${APP_NAME}"
|
|
|
|
# Registration anti-spam
|
|
REGISTRATION_IP_PER_MINUTE_LIMIT=3
|
|
REGISTRATION_IP_PER_DAY_LIMIT=20
|
|
REGISTRATION_EMAIL_PER_MINUTE_LIMIT=6
|
|
REGISTRATION_EMAIL_COOLDOWN_MINUTES=30
|
|
REGISTRATION_VERIFY_TOKEN_TTL_HOURS=24
|
|
TURNSTILE_ENABLED=false
|
|
REGISTRATION_DISPOSABLE_DOMAINS_ENABLED=true
|
|
REGISTRATION_TURNSTILE_SUSPICIOUS_ATTEMPTS=2
|
|
REGISTRATION_TURNSTILE_ATTEMPT_WINDOW_MINUTES=30
|
|
REGISTRATION_EMAIL_GLOBAL_SEND_PER_MINUTE=30
|
|
REGISTRATION_MONTHLY_EMAIL_LIMIT=10000
|
|
TURNSTILE_SITE_KEY=
|
|
TURNSTILE_SECRET_KEY=
|
|
TURNSTILE_FAIL_OPEN=false
|
|
TURNSTILE_VERIFY_URL=https://challenges.cloudflare.com/turnstile/v0/siteverify
|
|
TURNSTILE_TIMEOUT=5
|
|
|
|
ENHANCE_DISK=public
|
|
ENHANCE_SOURCE_PREFIX=enhance/sources
|
|
ENHANCE_OUTPUT_PREFIX=enhance/outputs
|
|
ENHANCE_PREVIEW_PREFIX=enhance/previews
|
|
ENHANCE_ENGINE=stub
|
|
ENHANCE_MAX_UPLOAD_MB=20
|
|
ENHANCE_MAX_INPUT_WIDTH=4096
|
|
ENHANCE_MAX_INPUT_HEIGHT=4096
|
|
ENHANCE_MAX_OUTPUT_WIDTH=8192
|
|
ENHANCE_MAX_OUTPUT_HEIGHT=8192
|
|
ENHANCE_DAILY_LIMIT=10
|
|
ENHANCE_QUEUE=default
|
|
ENHANCE_COMPLETED_EXPIRES_AFTER_DAYS=30
|
|
ENHANCE_FAILED_EXPIRES_AFTER_DAYS=7
|
|
ENHANCE_DELETED_FILE_GRACE_DAYS=1
|
|
ENHANCE_CLEANUP_CHUNK_SIZE=100
|
|
ENHANCE_STUCK_PROCESSING_AFTER_MINUTES=30
|
|
ENHANCE_STUCK_QUEUED_AFTER_MINUTES=60
|
|
ENHANCE_STUB_SHOW_WARNING=true
|
|
ENHANCE_WORKER_URL=
|
|
ENHANCE_WORKER_TIMEOUT=300
|
|
ENHANCE_WORKER_TOKEN=
|
|
ENHANCE_WORKER_MAX_DOWNLOAD_MB=60
|
|
|
|
AWS_ACCESS_KEY_ID=
|
|
AWS_SECRET_ACCESS_KEY=
|
|
AWS_DEFAULT_REGION=us-east-1
|
|
AWS_BUCKET=
|
|
AWS_USE_PATH_STYLE_ENDPOINT=false
|
|
|
|
VITE_APP_NAME="${APP_NAME}"
|
|
|
|
# ─── Early-Stage Growth System ───────────────────────────────────────────────
|
|
# Set NOVA_EARLY_GROWTH_ENABLED=false to instantly revert to normal behaviour.
|
|
# NOVA_EARLY_GROWTH_MODE: off | light | aggressive
|
|
NOVA_EARLY_GROWTH_ENABLED=false
|
|
NOVA_EARLY_GROWTH_MODE=off
|
|
|
|
# Module toggles (only active when NOVA_EARLY_GROWTH_ENABLED=true)
|
|
NOVA_EGS_ADAPTIVE_WINDOW=true
|
|
NOVA_EGS_GRID_FILLER=true
|
|
NOVA_EGS_SPOTLIGHT=true
|
|
NOVA_EGS_ACTIVITY_LAYER=false
|
|
|
|
# AdaptiveTimeWindow thresholds
|
|
NOVA_EGS_UPLOADS_PER_DAY_NARROW=10
|
|
NOVA_EGS_UPLOADS_PER_DAY_WIDE=3
|
|
NOVA_EGS_WINDOW_NARROW_DAYS=7
|
|
NOVA_EGS_WINDOW_MEDIUM_DAYS=30
|
|
NOVA_EGS_WINDOW_WIDE_DAYS=90
|
|
|
|
# GridFiller minimum items per page
|
|
NOVA_EGS_GRID_MIN_RESULTS=12
|
|
|
|
# Auto-disable when site reaches organic scale
|
|
NOVA_EGS_AUTO_DISABLE=false
|
|
NOVA_EGS_AUTO_DISABLE_UPLOADS=50
|
|
NOVA_EGS_AUTO_DISABLE_USERS=500
|
|
|
|
# Cache TTLs (seconds)
|
|
NOVA_EGS_SPOTLIGHT_TTL=3600
|
|
NOVA_EGS_BLEND_TTL=300
|
|
NOVA_EGS_WINDOW_TTL=600
|
|
NOVA_EGS_ACTIVITY_TTL=1800
|
|
# ─── OAuth / Social Login ─────────────────────────────────────────────────────
|
|
# Google — https://console.cloud.google.com/apis/credentials
|
|
GOOGLE_CLIENT_ID=
|
|
GOOGLE_CLIENT_SECRET=
|
|
GOOGLE_REDIRECT_URI=/auth/google/callback
|
|
|
|
# Google AdSense Management API (admin analytics, read-only)
|
|
# Redirect URI must match the Google Cloud OAuth client exactly.
|
|
ADSENSE_CLIENT_ID=
|
|
ADSENSE_CLIENT_SECRET=
|
|
ADSENSE_REDIRECT_URI=https://skinbase.org/admin/adsense/oauth/callback
|
|
ADSENSE_SYNC_ENABLED=true
|
|
|
|
# Optional light theme feature
|
|
# Set LIGHT_THEME_ENABLED=true to allow a light theme in the client-side toggle.
|
|
# Set LIGHT_THEME_SHOW_SWITCH=true to display the theme switch in the toolbar.
|
|
LIGHT_THEME_ENABLED=false
|
|
LIGHT_THEME_SHOW_SWITCH=false
|
|
|
|
# Discord — https://discord.com/developers/applications
|
|
DISCORD_CLIENT_ID=
|
|
DISCORD_CLIENT_SECRET=
|
|
DISCORD_REDIRECT_URI=/auth/discord/callback
|
|
|
|
# Apple — https://developer.apple.com/account/resources/identifiers/list/serviceId
|
|
# Apple sign in removed
|