optimizations

This commit is contained in:
2026-03-28 19:15:39 +01:00
parent 0b25d9570a
commit cab4fbd83e
509 changed files with 1016804 additions and 1605 deletions

View File

@@ -3,8 +3,8 @@
declare(strict_types=1);
return [
'files_url' => env('FILES_CDN_URL', 'https://files.skinbase.org'),
'avatar_url' => env('AVATAR_CDN_URL', 'https://files.skinbase.org'),
'files_url' => env('FILES_CDN_URL', 'https://cdn.skinbase.org'),
'avatar_url' => env('AVATAR_CDN_URL', 'https://cdn.skinbase.org'),
/**
* Optional CDN purge webhook URL.

155
config/collections.php Normal file
View File

@@ -0,0 +1,155 @@
<?php
declare(strict_types=1);
return [
'featured_limit' => 3,
'invites' => [
'expires_after_days' => (int) env('COLLECTIONS_INVITES_EXPIRE_AFTER_DAYS', 7),
],
'submissions' => [
'max_per_hour' => (int) env('COLLECTIONS_SUBMISSIONS_MAX_PER_HOUR', 8),
'duplicate_cooldown_minutes' => (int) env('COLLECTIONS_SUBMISSIONS_DUPLICATE_COOLDOWN_MINUTES', 15),
],
'editorial' => [
'system_owner_username' => env('COLLECTIONS_EDITORIAL_SYSTEM_OWNER_USERNAME'),
'system_owner_label' => env('COLLECTIONS_EDITORIAL_SYSTEM_OWNER_LABEL', 'Skinbase Editorial'),
],
'smart_rules' => [
'max_rules' => 8,
'preview_limit' => 12,
'allowed_match' => ['all', 'any'],
'allowed_sort' => ['newest', 'oldest', 'popular'],
'allowed_fields' => ['tags', 'category', 'subcategory', 'medium', 'style', 'color', 'ai_tag', 'created_at', 'is_featured', 'is_mature'],
'style_terms' => [
'abstract',
'anime',
'cartoon',
'cel shaded',
'cinematic',
'comic style',
'concept art',
'digital art',
'digital painting',
'fantasy art',
'illustration',
'low poly',
'matte painting',
'minimalist',
'oil painting',
'painterly',
'photorealistic',
'pixel art',
'realism',
'retro',
'sci fi',
'sketch',
'surreal',
'vector art',
'watercolor',
'3d render',
],
'color_terms' => [
'black and white',
'blue tones',
'cool colors',
'cyan tones',
'earth tones',
'gold tones',
'green tones',
'monochrome',
'neon colors',
'orange tones',
'pastel colors',
'pink tones',
'purple tones',
'red tones',
'teal tones',
'vibrant colors',
'warm colors',
'yellow tones',
],
],
'discovery' => [
'featured_limit' => 18,
'featured_cache_seconds' => 120,
],
'recommendations' => [
'related_limit' => 6,
],
'v5' => [
'health' => [
'stale_after_days' => (int) env('COLLECTIONS_V5_STALE_AFTER_DAYS', 90),
'low_engagement_after_days' => (int) env('COLLECTIONS_V5_LOW_ENGAGEMENT_AFTER_DAYS', 14),
],
'queue' => [
'name' => env('COLLECTIONS_V5_QUEUE', 'collections'),
'health_batch_size' => (int) env('COLLECTIONS_V5_HEALTH_BATCH_SIZE', 40),
'recommendation_batch_size' => (int) env('COLLECTIONS_V5_RECOMMENDATION_BATCH_SIZE', 40),
'duplicate_batch_size' => (int) env('COLLECTIONS_V5_DUPLICATE_BATCH_SIZE', 30),
'health_stale_after_hours' => (int) env('COLLECTIONS_V5_HEALTH_STALE_AFTER_HOURS', 24),
'recommendation_stale_after_hours' => (int) env('COLLECTIONS_V5_RECOMMENDATION_STALE_AFTER_HOURS', 12),
'duplicate_stale_after_hours' => (int) env('COLLECTIONS_V5_DUPLICATE_STALE_AFTER_HOURS', 24),
],
'search' => [
'public_per_page' => (int) env('COLLECTIONS_V5_PUBLIC_SEARCH_PER_PAGE', 18),
'owner_per_page' => (int) env('COLLECTIONS_V5_OWNER_SEARCH_PER_PAGE', 20),
],
],
'ai' => [
'enabled' => true,
'max_candidate_artworks' => 36,
],
'layout_modules' => [
'intro_block' => [
'label' => 'Intro Block',
'description' => 'Show the subtitle, curator summary, and smart context in the hero area.',
'default_slot' => 'full',
'slots' => ['full'],
'locked' => false,
],
'featured_artworks' => [
'label' => 'Featured Artworks Block',
'description' => 'Spotlight a compact highlights strip ahead of the main artwork grid.',
'default_slot' => 'main',
'slots' => ['full', 'main'],
],
'artwork_grid' => [
'label' => 'Artwork Grid',
'description' => 'Primary artwork gallery for the collection.',
'default_slot' => 'full',
'slots' => ['full', 'main'],
'locked' => true,
],
'editorial_note' => [
'label' => 'Editorial Note',
'description' => 'Premium context block for staff picks and campaign notes.',
'default_slot' => 'full',
'slots' => ['full', 'main', 'sidebar'],
],
'collaborators' => [
'label' => 'Contributor Block',
'description' => 'Show the curation team on the page.',
'default_slot' => 'sidebar',
'slots' => ['main', 'sidebar'],
],
'submissions' => [
'label' => 'Submission CTA',
'description' => 'Highlight community submission controls when enabled.',
'default_slot' => 'sidebar',
'slots' => ['main', 'sidebar'],
],
'discussion' => [
'label' => 'Discussion Block',
'description' => 'Render lightweight collection discussion.',
'default_slot' => 'main',
'slots' => ['main', 'sidebar'],
],
'related_collections' => [
'label' => 'Related Collections',
'description' => 'Surface collection recommendations.',
'default_slot' => 'main',
'slots' => ['main', 'sidebar'],
],
],
];

View File

@@ -22,11 +22,104 @@ return [
'click' => (float) env('DISCOVERY_WEIGHT_CLICK', 2.0),
'favorite' => (float) env('DISCOVERY_WEIGHT_FAVORITE', 4.0),
'download' => (float) env('DISCOVERY_WEIGHT_DOWNLOAD', 3.0),
'dwell' => (float) env('DISCOVERY_WEIGHT_DWELL', 1.5),
'scroll' => (float) env('DISCOVERY_WEIGHT_SCROLL', 0.75),
],
// Recommendation cache TTL in minutes (schema foundation only for now).
'cache_ttl_minutes' => (int) env('DISCOVERY_CACHE_TTL_MINUTES', 60),
'v2' => [
'enabled' => (bool) env('DISCOVERY_V2_ENABLED', false),
'algo_version' => env('DISCOVERY_V2_ALGO_VERSION', 'clip-cosine-v2-adaptive'),
'cache_version' => env('DISCOVERY_V2_CACHE_VERSION', 'cache-v2'),
'cache_ttl_minutes' => (int) env('DISCOVERY_V2_CACHE_TTL_MINUTES', 15),
'candidate_pool_max' => (int) env('DISCOVERY_V2_CANDIDATE_POOL_MAX', 300),
'feed_pool_size' => (int) env('DISCOVERY_V2_FEED_POOL_SIZE', 240),
'fresh_upload_hours' => (int) env('DISCOVERY_V2_FRESH_UPLOAD_HOURS', 72),
'new_creator_days' => (int) env('DISCOVERY_V2_NEW_CREATOR_DAYS', 45),
'max_per_creator' => (int) env('DISCOVERY_V2_MAX_PER_CREATOR', 3),
'repetition_window' => (int) env('DISCOVERY_V2_REPETITION_WINDOW', 24),
'rollout_percentage' => (int) env('DISCOVERY_V2_ROLLOUT_PERCENTAGE', 0),
'layers' => [
'personalized' => (float) env('DISCOVERY_V2_LAYER_PERSONALIZED', 0.50),
'social' => (float) env('DISCOVERY_V2_LAYER_SOCIAL', 0.20),
'trending' => (float) env('DISCOVERY_V2_LAYER_TRENDING', 0.20),
'exploration' => (float) env('DISCOVERY_V2_LAYER_EXPLORATION', 0.10),
],
'session' => [
'ttl_seconds' => (int) env('DISCOVERY_V2_SESSION_TTL_SECONDS', 14400),
'max_items' => (int) env('DISCOVERY_V2_SESSION_MAX_ITEMS', 120),
'half_life_hours' => (float) env('DISCOVERY_V2_SESSION_HALF_LIFE_HOURS', 8),
'merge_multiplier' => (float) env('DISCOVERY_V2_SESSION_MERGE_MULTIPLIER', 1.35),
'artwork_similarity_weight' => (float) env('DISCOVERY_V2_SESSION_ARTWORK_SIMILARITY_WEIGHT', 0.85),
'event_weights' => [
'view' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_VIEW', 1.0),
'click' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_CLICK', 2.0),
'favorite' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_FAVORITE', 4.5),
'download' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_DOWNLOAD', 3.5),
'dwell' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_DWELL', 1.75),
'scroll' => (float) env('DISCOVERY_V2_SESSION_WEIGHT_SCROLL', 0.75),
],
],
'weights' => [
'base' => (float) env('DISCOVERY_V2_WEIGHT_BASE', 1.0),
'session' => (float) env('DISCOVERY_V2_WEIGHT_SESSION', 1.4),
'social' => (float) env('DISCOVERY_V2_WEIGHT_SOCIAL', 1.1),
'trending' => (float) env('DISCOVERY_V2_WEIGHT_TRENDING', 0.95),
'exploration' => (float) env('DISCOVERY_V2_WEIGHT_EXPLORATION', 0.7),
'creator' => (float) env('DISCOVERY_V2_WEIGHT_CREATOR', 0.5),
'repetition_penalty' => (float) env('DISCOVERY_V2_WEIGHT_REPETITION_PENALTY', 0.45),
'negative_tag_penalty' => (float) env('DISCOVERY_V2_WEIGHT_NEGATIVE_TAG_PENALTY', 0.65),
'followed_creator' => (float) env('DISCOVERY_V2_WEIGHT_FOLLOWED_CREATOR', 0.85),
'followed_like' => (float) env('DISCOVERY_V2_WEIGHT_FOLLOWED_LIKE', 0.55),
],
'trending' => [
'period_weights' => [
'1h' => (float) env('DISCOVERY_V2_TRENDING_WEIGHT_1H', 1.0),
'24h' => (float) env('DISCOVERY_V2_TRENDING_WEIGHT_24H', 0.7),
'7d' => (float) env('DISCOVERY_V2_TRENDING_WEIGHT_7D', 0.45),
],
'velocity_weights' => [
'views' => (float) env('DISCOVERY_V2_TRENDING_VIEWS_WEIGHT', 1.0),
'favorites' => (float) env('DISCOVERY_V2_TRENDING_FAVORITES_WEIGHT', 3.0),
'comments' => (float) env('DISCOVERY_V2_TRENDING_COMMENTS_WEIGHT', 2.5),
'shares' => (float) env('DISCOVERY_V2_TRENDING_SHARES_WEIGHT', 2.0),
],
'age_decay_per_hour' => (float) env('DISCOVERY_V2_TRENDING_AGE_DECAY_PER_HOUR', 0.08),
],
'exploration' => [
'creator_bonus' => (float) env('DISCOVERY_V2_EXPLORATION_CREATOR_BONUS', 0.6),
'tag_bonus' => (float) env('DISCOVERY_V2_EXPLORATION_TAG_BONUS', 0.45),
'freshness_bonus' => (float) env('DISCOVERY_V2_EXPLORATION_FRESHNESS_BONUS', 0.55),
],
'negative_signals' => [
'hide_artwork_penalty' => (float) env('DISCOVERY_V2_HIDE_ARTWORK_PENALTY', 5.0),
'dislike_tag_penalty' => (float) env('DISCOVERY_V2_DISLIKE_TAG_PENALTY', 0.75),
],
],
'v3' => [
'enabled' => (bool) env('DISCOVERY_V3_ENABLED', false),
'cache_version' => env('DISCOVERY_V3_CACHE_VERSION', 'cache-v3'),
'cache_ttl_minutes' => (int) env('DISCOVERY_V3_CACHE_TTL_MINUTES', 5),
'vector_similarity_weight' => (float) env('DISCOVERY_V3_VECTOR_SIMILARITY_WEIGHT', 0.8),
'vector_base_score' => (float) env('DISCOVERY_V3_VECTOR_BASE_SCORE', 0.75),
'max_seed_artworks' => (int) env('DISCOVERY_V3_MAX_SEED_ARTWORKS', 3),
'vector_candidate_pool' => (int) env('DISCOVERY_V3_VECTOR_CANDIDATE_POOL', 60),
'sections' => [
'similar_style_limit' => (int) env('DISCOVERY_V3_SECTION_SIMILAR_STYLE_LIMIT', 3),
'you_may_also_like_limit' => (int) env('DISCOVERY_V3_SECTION_YOU_MAY_ALSO_LIKE_LIMIT', 6),
'visually_related_limit' => (int) env('DISCOVERY_V3_SECTION_VISUALLY_RELATED_LIMIT', 6),
],
],
// Phase 8B: versioned ranking blend weights.
// Blend components: w1=interest, w2=recency, w3=popularity, w4=novelty.
'ranking' => [

View File

@@ -1,7 +1,7 @@
<?php
return [
'enabled' => env('FORUM_BOT_PROTECTION_ENABLED', true),
'enabled' => env('FORUM_BOT_PROTECTION_ENABLED', env('APP_ENV') === 'production'),
'thresholds' => [
'allow' => 20,
@@ -21,6 +21,7 @@ return [
'actions' => [
'register',
'login',
'follow',
'forum_topic_create',
'forum_reply_create',
'forum_post_update',

381
config/nova_cards.php Normal file
View File

@@ -0,0 +1,381 @@
<?php
declare(strict_types=1);
return [
'brand' => [
'name' => 'Nova Cards',
'subtitle' => 'Create beautiful quote cards, mood cards, and visual text art.',
],
'formats' => [
'square' => ['width' => 1080, 'height' => 1080, 'label' => 'Square'],
'portrait' => ['width' => 1080, 'height' => 1350, 'label' => 'Portrait'],
'story' => ['width' => 1080, 'height' => 1920, 'label' => 'Story'],
'landscape' => ['width' => 1920, 'height' => 1080, 'label' => 'Landscape'],
],
'validation' => [
'quote_min' => 3,
'quote_max' => 420,
'title_min' => 3,
'title_max' => 120,
'description_max' => 500,
'max_tags' => 8,
'max_decorations' => 6,
'max_text_blocks' => 8,
'max_asset_items' => 12,
'max_background_upload_bytes' => 8 * 1024 * 1024,
'allowed_background_mimes' => [
'image/jpeg',
'image/png',
'image/webp',
],
'allowed_alignments' => ['left', 'center', 'right'],
'allowed_layouts' => ['quote_heavy', 'author_emphasis', 'centered', 'minimal'],
'allowed_overlay_styles' => ['none', 'dark-soft', 'dark-strong', 'light-soft'],
'allowed_positions' => ['top', 'upper-middle', 'center', 'lower-middle', 'bottom'],
'allowed_blur_levels' => [0, 4, 8, 12, 20],
'allowed_opacity_levels' => [20, 35, 50, 65, 80],
'allowed_padding_presets' => ['tight', 'comfortable', 'airy'],
'allowed_max_widths' => ['compact', 'balanced', 'wide'],
],
'storage' => [
'public_disk' => env('NOVA_CARDS_PUBLIC_DISK', 'public'),
'private_disk' => env('NOVA_CARDS_PRIVATE_DISK', 'local'),
'public_prefix' => 'cards',
'background_original_prefix' => 'cards/backgrounds/original',
'background_processed_prefix' => 'cards/backgrounds/processed',
'preview_prefix' => 'cards/previews',
],
'render' => [
'queue' => env('NOVA_CARDS_QUEUE', 'default'),
'preview_quality' => 86,
'og_quality' => 88,
'preview_format' => 'webp',
'og_format' => 'jpg',
],
'seed_demo_cards' => [
'enabled' => (bool) env('NOVA_CARDS_SEED_DEMO_CARDS', false),
'user' => [
'username' => env('NOVA_CARDS_DEMO_USERNAME', 'nova.cards'),
'name' => env('NOVA_CARDS_DEMO_NAME', 'Nova Cards'),
'email' => env('NOVA_CARDS_DEMO_EMAIL', 'nova-cards-demo@skinbase.test'),
'password' => env('NOVA_CARDS_DEMO_PASSWORD', 'password'),
],
],
'rate_limits' => [
'drafts' => ['per_user' => 20, 'per_ip' => 40],
'autosave' => ['per_user' => 120, 'per_ip' => 240],
'publish' => ['per_user' => 12, 'per_ip' => 24],
'background_upload' => ['per_user' => 30, 'per_ip' => 60],
'render' => ['per_user' => 30, 'per_ip' => 60],
],
'font_presets' => [
'modern-sans' => [
'label' => 'Modern Sans',
'family' => 'ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
'render_family' => 'arial',
'weight' => '600',
'recommended_use' => 'Clean motivational cards and bold statements.',
],
'elegant-serif' => [
'label' => 'Elegant Serif',
'family' => 'Georgia, Cambria, "Times New Roman", serif',
'render_family' => 'georgia',
'weight' => '700',
'recommended_use' => 'Classic quotes and romantic layouts.',
],
'bold-poster' => [
'label' => 'Bold Poster',
'family' => 'Impact, Haettenschweiler, "Arial Narrow Bold", sans-serif',
'render_family' => 'arial-black',
'weight' => '700',
'recommended_use' => 'High-contrast poster-like statements.',
],
'soft-handwritten' => [
'label' => 'Soft Handwritten',
'family' => '"Segoe Print", "Bradley Hand", cursive',
'render_family' => 'comic-sans',
'weight' => '400',
'recommended_use' => 'Warm, intimate, diary-like cards.',
],
'minimal-editorial' => [
'label' => 'Minimal Editorial',
'family' => '"Trebuchet MS", "Gill Sans", sans-serif',
'render_family' => 'trebuchet',
'weight' => '600',
'recommended_use' => 'Minimal editorial compositions.',
],
'dreamy-aesthetic' => [
'label' => 'Dreamy Aesthetic',
'family' => '"Palatino Linotype", "Book Antiqua", Palatino, serif',
'render_family' => 'palatino',
'weight' => '600',
'recommended_use' => 'Poetry, wallpaper quotes, and soft mood cards.',
],
],
'gradient_presets' => [
'midnight-nova' => ['label' => 'Midnight Nova', 'colors' => ['#0f172a', '#1d4ed8']],
'soft-pastel' => ['label' => 'Soft Pastel', 'colors' => ['#f9a8d4', '#c4b5fd']],
'amber-glow' => ['label' => 'Amber Glow', 'colors' => ['#451a03', '#f59e0b']],
'emerald-bloom' => ['label' => 'Emerald Bloom', 'colors' => ['#052e16', '#34d399']],
'romantic-dusk' => ['label' => 'Romantic Dusk', 'colors' => ['#4c0519', '#fb7185']],
'deep-cinema' => ['label' => 'Deep Cinema', 'colors' => ['#020617', '#334155']],
'dream-glow' => ['label' => 'Dream Glow', 'colors' => ['#312e81', '#ec4899']],
'nature-calm' => ['label' => 'Nature Calm', 'colors' => ['#064e3b', '#93c5fd']],
],
'decor_presets' => [
['key' => 'sparkle-cluster', 'label' => 'Sparkles', 'glyph' => '✦'],
['key' => 'soft-heart', 'label' => 'Heart', 'glyph' => '♥'],
['key' => 'moon-stars', 'label' => 'Moon', 'glyph' => '☾'],
['key' => 'minimal-dot', 'label' => 'Dot', 'glyph' => '•'],
['key' => 'asterisk-burst', 'label' => 'Burst', 'glyph' => '✷'],
],
'asset_packs' => [
[
'slug' => 'official-celestial',
'name' => 'Official Celestial Pack',
'description' => 'Sparkles, moons, and accent glyphs tuned for dreamy Nova Cards compositions.',
'type' => 'asset',
'official' => true,
'active' => true,
'manifest_json' => [
'items' => [
['key' => 'nova-sparkle', 'label' => 'Nova Sparkle', 'type' => 'glyph', 'glyph' => '✦'],
['key' => 'nova-moon', 'label' => 'Moon Accent', 'type' => 'glyph', 'glyph' => '☾'],
['key' => 'nova-heart', 'label' => 'Soft Heart', 'type' => 'glyph', 'glyph' => '♥'],
],
],
],
[
'slug' => 'official-editorial-frames',
'name' => 'Editorial Frame Pack',
'description' => 'Minimal frame treatments and lines for poster-style cards.',
'type' => 'asset',
'official' => true,
'active' => true,
'manifest_json' => [
'items' => [
['key' => 'line-top', 'label' => 'Top Line', 'type' => 'frame'],
['key' => 'line-bottom', 'label' => 'Bottom Line', 'type' => 'frame'],
],
],
],
],
'template_packs' => [
[
'slug' => 'official-story-pack',
'name' => 'Official Story Pack',
'description' => 'Tall layouts optimized for punchy story cards and serial prompts.',
'type' => 'template',
'official' => true,
'active' => true,
'manifest_json' => [
'templates' => ['story-vertical', 'dream-glow'],
],
],
[
'slug' => 'official-editorial-pack',
'name' => 'Official Editorial Pack',
'description' => 'Minimal serif and poster templates for headline-driven cards.',
'type' => 'template',
'official' => true,
'active' => true,
'manifest_json' => [
'templates' => ['classic-typography', 'golden-serif'],
],
],
],
'background_modes' => [
['key' => 'template', 'label' => 'Template Base'],
['key' => 'gradient', 'label' => 'Gradient'],
['key' => 'solid', 'label' => 'Solid'],
['key' => 'upload', 'label' => 'Upload'],
],
'layout_presets' => [
['key' => 'quote_heavy', 'label' => 'Quote Heavy'],
['key' => 'author_emphasis', 'label' => 'Author Emphasis'],
['key' => 'centered', 'label' => 'Centered'],
['key' => 'minimal', 'label' => 'Minimal'],
],
'alignment_presets' => [
['key' => 'left', 'label' => 'Left'],
['key' => 'center', 'label' => 'Center'],
['key' => 'right', 'label' => 'Right'],
],
'position_presets' => [
['key' => 'top', 'label' => 'Top'],
['key' => 'upper-middle', 'label' => 'Upper Middle'],
['key' => 'center', 'label' => 'Center'],
['key' => 'lower-middle', 'label' => 'Lower Middle'],
['key' => 'bottom', 'label' => 'Bottom'],
],
'padding_presets' => [
['key' => 'tight', 'label' => 'Tight'],
['key' => 'comfortable', 'label' => 'Comfortable'],
['key' => 'airy', 'label' => 'Airy'],
],
'max_width_presets' => [
['key' => 'compact', 'label' => 'Compact'],
['key' => 'balanced', 'label' => 'Balanced'],
['key' => 'wide', 'label' => 'Wide'],
],
'line_height_presets' => [
['key' => 'tight', 'label' => 'Tight', 'value' => 1.05],
['key' => 'balanced', 'label' => 'Balanced', 'value' => 1.2],
['key' => 'airy', 'label' => 'Airy', 'value' => 1.38],
],
'shadow_presets' => [
['key' => 'none', 'label' => 'None'],
['key' => 'soft', 'label' => 'Soft'],
['key' => 'strong', 'label' => 'Strong'],
],
'focal_positions' => [
['key' => 'center', 'label' => 'Center'],
['key' => 'top', 'label' => 'Top'],
['key' => 'bottom', 'label' => 'Bottom'],
['key' => 'left', 'label' => 'Left'],
['key' => 'right', 'label' => 'Right'],
['key' => 'top-left', 'label' => 'Top Left'],
['key' => 'top-right', 'label' => 'Top Right'],
['key' => 'bottom-left', 'label' => 'Bottom Left'],
['key' => 'bottom-right', 'label' => 'Bottom Right'],
],
'starter_templates' => [
'minimal-black-white',
'neon-nova',
'soft-pastel',
'romantic',
'cinematic-dark',
'golden-serif',
'nature-calm',
'bold-statement',
'wallpaper-style',
'story-vertical',
'dream-glow',
'classic-typography',
],
// v3 additions
'quote_mark_presets' => [
['key' => 'none', 'label' => 'None'],
['key' => 'classic', 'label' => 'Classic "…"'],
['key' => 'guillemets', 'label' => 'Guillemets «…»'],
['key' => 'large-open', 'label' => 'Large Open "'],
['key' => 'minimal-dash', 'label' => 'Dash —'],
['key' => 'decorative-star', 'label' => 'Star ✦'],
],
'text_panel_styles' => [
['key' => 'none', 'label' => 'None'],
['key' => 'frosted', 'label' => 'Frosted Glass'],
['key' => 'dark-solid', 'label' => 'Dark Solid'],
['key' => 'light-solid', 'label' => 'Light Solid'],
['key' => 'outline', 'label' => 'Outline'],
['key' => 'editorial-rule', 'label' => 'Editorial Rule'],
],
'frame_presets' => [
['key' => 'none', 'label' => 'None'],
['key' => 'thin-border', 'label' => 'Thin Border'],
['key' => 'double-line', 'label' => 'Double Line'],
['key' => 'corner-marks', 'label' => 'Corner Marks'],
['key' => 'editorial-top', 'label' => 'Editorial Top Rule'],
['key' => 'editorial-both', 'label' => 'Editorial Top & Bottom Rules'],
['key' => 'rounded-card', 'label' => 'Rounded Card'],
],
'color_grade_presets' => [
['key' => 'none', 'label' => 'None'],
['key' => 'warm', 'label' => 'Warm'],
['key' => 'cool', 'label' => 'Cool'],
['key' => 'cinematic', 'label' => 'Cinematic'],
['key' => 'muted', 'label' => 'Muted'],
['key' => 'vivid', 'label' => 'Vivid'],
['key' => 'noir', 'label' => 'Noir'],
['key' => 'golden-hour', 'label' => 'Golden Hour'],
],
'effect_presets' => [
['key' => 'none', 'label' => 'None'],
['key' => 'grain', 'label' => 'Film Grain'],
['key' => 'vignette', 'label' => 'Vignette'],
['key' => 'noise', 'label' => 'Noise'],
['key' => 'halftone', 'label' => 'Halftone'],
['key' => 'glitch', 'label' => 'Glitch'],
['key' => 'bokeh', 'label' => 'Bokeh'],
],
'style_families' => [
['key' => 'aesthetic', 'label' => 'Aesthetic'],
['key' => 'editorial', 'label' => 'Editorial'],
['key' => 'cinematic', 'label' => 'Cinematic'],
['key' => 'minimal', 'label' => 'Minimal'],
['key' => 'bold', 'label' => 'Bold'],
['key' => 'romantic', 'label' => 'Romantic'],
['key' => 'dark', 'label' => 'Dark'],
['key' => 'pastel', 'label' => 'Pastel'],
['key' => 'retro', 'label' => 'Retro'],
['key' => 'nature', 'label' => 'Nature'],
],
'palette_families' => [
['key' => 'monochrome', 'label' => 'Monochrome'],
['key' => 'warm-tones', 'label' => 'Warm Tones'],
['key' => 'cool-tones', 'label' => 'Cool Tones'],
['key' => 'earth-tones', 'label' => 'Earth Tones'],
['key' => 'pastels', 'label' => 'Pastels'],
['key' => 'neons', 'label' => 'Neons'],
['key' => 'jewel-tones', 'label' => 'Jewel Tones'],
],
'mood_families' => [
['key' => 'romantic', 'label' => 'Romantic', 'tag_slugs' => ['romantic', 'love', 'tender']],
['key' => 'dark-poetry', 'label' => 'Dark Poetry', 'tag_slugs' => ['dark', 'shadow', 'night']],
['key' => 'inspirational', 'label' => 'Inspirational', 'tag_slugs' => ['inspire', 'hope', 'believe']],
['key' => 'soft-morning', 'label' => 'Soft Morning', 'tag_slugs' => ['calm', 'morning', 'peace']],
['key' => 'minimal', 'label' => 'Minimal', 'tag_slugs' => ['minimal', 'quiet', 'still']],
['key' => 'motivational', 'label' => 'Motivational', 'tag_slugs' => ['power', 'bold', 'fire']],
['key' => 'cyber-mood', 'label' => 'Cyber Mood', 'tag_slugs' => ['cyber', 'neon', 'digital']],
],
'seasonal_hubs' => [
['key' => 'spring', 'label' => 'Spring', 'tag_slugs' => ['spring', 'bloom', 'floral']],
['key' => 'summer', 'label' => 'Summer', 'tag_slugs' => ['summer', 'sunlight', 'vacation']],
['key' => 'autumn', 'label' => 'Autumn', 'tag_slugs' => ['autumn', 'harvest', 'amber']],
['key' => 'winter', 'label' => 'Winter', 'tag_slugs' => ['winter', 'snow', 'frost']],
['key' => 'holiday', 'label' => 'Holiday', 'tag_slugs' => ['holiday', 'festive', 'celebration']],
],
'export_formats' => [
'preview' => ['width' => 1080, 'height' => 1080, 'format' => 'webp', 'label' => 'Preview (WebP)'],
'hires' => ['width' => 2160, 'height' => 2160, 'format' => 'png', 'label' => 'Hi-Res PNG'],
'square' => ['width' => 1080, 'height' => 1080, 'format' => 'png', 'label' => 'Square PNG'],
'story' => ['width' => 1080, 'height' => 1920, 'format' => 'png', 'label' => 'Story PNG'],
'wallpaper' => ['width' => 1920, 'height' => 1080, 'format' => 'png', 'label' => 'Wallpaper PNG'],
'og' => ['width' => 1200, 'height' => 630, 'format' => 'jpg', 'label' => 'OG Image (JPG)'],
],
'export_ttl_hours' => (int) env('NOVA_CARDS_EXPORT_TTL_HOURS', 48),
];

View File

@@ -82,7 +82,14 @@ return [
'scheme' => env('REVERB_SCHEME', 'https'),
'useTLS' => env('REVERB_SCHEME', 'https') === 'https',
],
'allowed_origins' => ['*'],
'allowed_origins' => [
'skinbase.org',
'www.skinbase.org',
'ws.skinbase.org',
'skinbase.top',
'www.skinbase.top',
'skinbase26.test'
],
'ping_interval' => env('REVERB_APP_PING_INTERVAL', 60),
'activity_timeout' => env('REVERB_APP_ACTIVITY_TIMEOUT', 30),
'max_connections' => env('REVERB_APP_MAX_CONNECTIONS'),

View File

@@ -10,6 +10,7 @@ return [
'clip' => [
'base_url' => env('CLIP_BASE_URL', ''),
'endpoint' => env('CLIP_ANALYZE_ENDPOINT', '/analyze'),
'api_key' => env('CLIP_API_KEY', env('VISION_API_KEY', env('VISION_VECTOR_GATEWAY_API_KEY', ''))),
'timeout_seconds' => (int) env('CLIP_TIMEOUT_SECONDS', 8),
'connect_timeout_seconds' => (int) env('CLIP_CONNECT_TIMEOUT_SECONDS', 2),
'retries' => (int) env('CLIP_HTTP_RETRIES', 1),
@@ -20,6 +21,7 @@ return [
'enabled' => env('YOLO_ENABLED', true),
'base_url' => env('YOLO_BASE_URL', ''),
'endpoint' => env('YOLO_ANALYZE_ENDPOINT', '/analyze'),
'api_key' => env('YOLO_API_KEY', env('VISION_API_KEY', env('VISION_VECTOR_GATEWAY_API_KEY', ''))),
'timeout_seconds' => (int) env('YOLO_TIMEOUT_SECONDS', 8),
'connect_timeout_seconds' => (int) env('YOLO_CONNECT_TIMEOUT_SECONDS', 2),
'retries' => (int) env('YOLO_HTTP_RETRIES', 1),
@@ -40,7 +42,8 @@ return [
*/
'gateway' => [
'base_url' => env('VISION_GATEWAY_URL', env('CLIP_BASE_URL', '')),
'timeout_seconds' => (int) env('VISION_GATEWAY_TIMEOUT', 10),
'api_key' => env('VISION_GATEWAY_API_KEY', env('VISION_API_KEY', env('VISION_VECTOR_GATEWAY_API_KEY', ''))),
'timeout_seconds' => (int) env('VISION_GATEWAY_TIMEOUT', 60),
'connect_timeout_seconds'=> (int) env('VISION_GATEWAY_CONNECT_TIMEOUT', 3),
],