Configuration Constants
Centralized configuration constants from the @pixflare/config package.
Constants Overview
270 constants across 28 categories
Auto-generated
Generated from config/src/. Run pnpm docs:gen to update.
About
Source: config/src/about.ts
SITE
{
title: 'Pixelflare',
icon: '/favicon.png',
description:
'Welcome to Pixelflare. The edge...REPO
{
host: 'https://github.com',
user: 'lissy93',
name: 'pixelflare',
}LINKS
{
homepage: 'https://pixelflare.cc',
web_ui: '',
docs: 'https://pixelflare.cc/docs',
api_spe...LEGAL
{
license: `${REPO.host}/${REPO.user}/${REPO.name}/blob/main/LICENSE`,
security: '/security.txt'...AUTHOR
{
name: 'Alicia Sykes',
github: 'https://github.com/lissy93',
sponsor: 'https://github.com/spo...LICENSE
{
name: 'MIT',
url: LEGAL.license,
author: AUTHOR.name,
authorUrl: AUTHOR.website,
date: n...SUPPORT
{
email: 'support@as93.net',
}PROFILE
{
name: AUTHOR.name,
username: '@Lissy93',
avatar: `${AUTHOR.github}.png`,
bio: 'I build and...OTHER_APPS
{
url: 'https://lissy93.github.io',
}GITHUB_ISSUES
{
url: `${REPO.host}/${REPO.user}/${REPO.name}/issues/new/choose`,
}Ai Classification
Source: config/src/ai-classification.ts
AI_MODELS
{
* CLASSIFIER: '@cf/microsoft/resnet-50', // Change this
* CAPTIONER: '@cf/unum/uform-gen2-q...AI_MODELS
{
/** Image classification model - ResNet-50 */
// Other options: @cf/facebook/detr-resnet-50, @...AI_SUPPORTED_FORMATS
['image/jpeg', 'image/png', 'image/avif'] as const;AI_PROCESSING
{
/** Downscale images to this width before AI processing (cost optimization) */
DOWNSCALE_WIDTH...AI_SEARCH
{
/** Weight for vector similarity in hybrid search (0.0-1.0) */
VECTOR_WEIGHT: 0.6,
/** Weigh...AI_COLORS
{
/** Maximum number of dominant colors to extract */
MAX_COLORS: 5,
/** Minimum percentage of...AI_ERROR_MESSAGES
{
VECTORIZE_LOCAL_DEV: 'run remotely',
AI_BINDING_MISSING: 'AI binding not available',
WORKERS...AI_FEATURES
{
/** Enable AI classification (labels + captions) */
CLASSIFICATION: true,
/** Enable NSFW de...Analytics
Source: config/src/analytics.ts
ANALYTICS_MAX_DAYS
90;ANALYTICS_DEFAULT_DAYS
30;ANALYTICS_REALTIME_ENABLED_DEFAULT
true;ANALYTICS_BATCH_ENABLED_DEFAULT
true;ANALYTICS_AGGREGATION_CRON_DEFAULT
'0 2 * * *';ANALYTICS_AGGREGATION_DAYS_DEFAULT
1;ANALYTICS_DATASET_DEFAULT
'pixflare_cdn_metrics';ANALYTICS_DATASET
ANALYTICS_DATASET_DEFAULT;ANALYTICS_RETENTION_DAYS_DEFAULT
90;ANALYTICS_UNKNOWN_COUNTRY
'XX';ANALYTICS_REFERRER_MAX_LENGTH
2048;ANALYTICS_TRACK_DIRECT_REFERRER
true;ANALYTICS_DEFAULT_REFERRER_LIMIT
20;Api
Source: config/src/api.ts
RATE_LIMITS
{
/**
* Base limits per minute for different request types
* These are multiplied by plan an...RATE_LIMIT_UPLOAD_BURST
RATE_LIMITS.uploads.burst;RATE_LIMIT_UPLOAD_WINDOW_MS
RATE_LIMITS.uploads.window;RATE_LIMIT_UPLOAD_DAILY
RATE_LIMITS.uploads.daily;RATE_LIMIT_CDN_VARIANT_MISS
RATE_LIMITS.cdn.variantMiss;RATE_LIMIT_PUBLIC_ENDPOINT
RATE_LIMITS.publicEndpoint.limit;RATE_LIMIT_PUBLIC_ENDPOINT_WINDOW_MS
RATE_LIMITS.publicEndpoint.window;RATE_LIMIT_MIN_TTL_SECONDS
RATE_LIMITS.cache.minBucketTtl;RATE_LIMIT_MULTIPLIER_FREE
RATE_LIMITS.planMultipliers.free;RATE_LIMIT_MULTIPLIER_STARTER
RATE_LIMITS.planMultipliers.starter;RATE_LIMIT_MULTIPLIER_PRO
RATE_LIMITS.planMultipliers.pro;RATE_LIMIT_PLAN_CACHE_TTL_SECONDS
RATE_LIMITS.cache.planTierTtl;RATE_LIMIT_WINDOW_MS
RATE_LIMITS.cdn.window;RATE_LIMIT_CDN_MAX
RATE_LIMITS.cdn.variantMiss;CUSTOM_TRANSFORM_RATE_LIMIT
RATE_LIMITS.customTransform.limit;CUSTOM_TRANSFORM_RATE_LIMIT_WINDOW_MS
RATE_LIMITS.customTransform.window;MAX_CUSTOM_VARIANTS_PER_IMAGE
RATE_LIMITS.customTransform.maxVariantsPerImage;API_KEY_PREFIX
'pxf_';API_KEY_LENGTH
32;MAX_API_KEY_EXPIRATION_DAYS
365;MAX_API_KEY_NAME_LENGTH
100;DEFAULT_RANDOM_ID_LENGTH
16;MS_PER_SECOND
1000;MS_PER_MINUTE
60 * MS_PER_SECOND;MS_PER_HOUR
60 * MS_PER_MINUTE;MS_PER_DAY
24 * MS_PER_HOUR;AUTO_COMPLETE_LOCK_TTL_SEC
120;AUTO_COMPLETE_RETRY_DELAY_MS
250;METADATA_REFRESH_RETRY_COUNT
3;METADATA_REFRESH_RETRY_DELAY_MS
50;LAST_ACCESSED_THROTTLE_TTL_SEC
3600;LOG_REQUEST_ID_LENGTH
8;SLOW_REQUEST_THRESHOLD_MS
1000;Audit
Source: config/src/audit.ts
AUDIT_LOG
{
/**
* Whether audit logging is enabled by default
* Can be overridden by AUDIT_LOG_ENABLED...Auth
Source: config/src/auth.ts
DEFAULT_NO_AUTH_OWNER
'admin';MAX_OWNER_USERNAME_LENGTH
24;OWNER_USERNAME_HASH_LENGTH
8;OWNER_USERNAME_PREFIX_LENGTH
16;Billing
Source: config/src/billing.ts
BILLING
{
// Stripe product/price IDs
STRIPE: {
// Real Stripe Price IDs (not lookup keys)
PRICE...Cleanup
Source: config/src/cleanup.ts
ORPHANED_UPLOAD_RETENTION_HOURS
24;Custom Domains
Source: config/src/custom-domains.ts
SUBDOMAIN_REGEX
/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i;MAX_HOSTNAME_LENGTH
253;MIN_HOSTNAME_LENGTH
3;MAX_LABEL_LENGTH
63;VERIFICATION_POLL_INTERVAL_MS
30_000;VERIFICATION_MAX_RETRIES
40;VERIFICATION_TIMEOUT_MS
1_200_000;HOSTNAME_CACHE_TTL_SECONDS
3600;HOSTNAME_CACHE_KEY_PREFIX
'custom_domain:';MAX_CUSTOM_DOMAINS
99;DEFAULT_SSL_MODE
'flexible' as const;VERIFICATION_METHODS
['txt', 'http'] as const;FORBIDDEN_SUBDOMAINS
[
'www',
'mail',
'smtp',
'pop',
'pop3',
'imap',
'ftp',
'localhost',
'admin',
'ro...ERROR_MESSAGES
{
INVALID_FORMAT: 'Hostname must be a valid subdomain (e.g., cdn.example.com)',
APEX_NOT_SUPPORT...Custom Transform Fields
Source: config/src/custom-transform-fields.ts
CUSTOM_TRANSFORM_FIELDS
[
{
key: 'w',
label: 'Width (px)',
type: 'number',
placeholder: 'Auto',
min: 1...Custom Transform Params
Source: config/src/custom-transform-params.ts
MAX_DIMENSION
4096;MIN_DIMENSION
1;COLOR_FACTOR_MIN
0.5;COLOR_FACTOR_MAX
2.0;SATURATION_MIN
0;SATURATION_MAX
2.0;CUSTOM_PARAM_KEYS
[
'w',
'h',
'fit',
'q',
'f',
'g',
'trim',
'blur',
'sharpen',
'br',
'co',
'sa...Deletion
Source: config/src/deletion.ts
DELETION_RETENTION_DAYS
30;DELETION_CLEANUP_INTERVAL_HOURS
24;Encryption
Source: config/src/encryption.ts
ENCRYPTION_ALGORITHM
'AES-GCM' as const;KEY_LENGTH_BYTES
32;IV_LENGTH_BYTES
12;TAG_LENGTH_BYTES
16;TMK_KV_PREFIX
'tmk' as const;DEFAULT_TMK_VERSION
1;MAX_TMK_VERSION
1000;TMK_KV_EXPIRATION_SECONDS
undefined;DEFAULT_ACCESS_TOKEN_EXPIRY_SECONDS
3600;MIN_ACCESS_TOKEN_EXPIRY_SECONDS
300;MAX_ACCESS_TOKEN_EXPIRY_SECONDS
7 * 24 * 3600;ACCESS_TOKEN_ALGORITHM
'HMAC' as const;ACCESS_TOKEN_SEPARATOR
'|' as const;BUNDLE_KDF
'PBKDF2' as const;BUNDLE_KDF_ITERATIONS
100000;BUNDLE_KDF_HASH
'SHA-256' as const;BUNDLE_SALT_LENGTH_BYTES
16;ENCRYPTION_METADATA_VERSION
1;MAX_TMK_ROTATIONS_PER_HOUR
5;MAX_BUNDLE_EXPORTS_PER_HOUR
10;MAX_TOKEN_GENERATIONS_PER_IMAGE_PER_MINUTE
20;CRYPTO_EVENT_TYPES
{
TMK_CREATE: 'tmk_create',
TMK_ROTATE: 'tmk_rotate',
IMG_ENCRYPT: 'img_encrypt',
BUNDLE_EXP...Headers
Source: config/src/headers.ts
CACHE_CONTROL_IMMUTABLE
'public, max-age=31536000, immutable';CACHE_CONTROL_PRIVATE
'private, no-cache, must-revalidate';CACHE_CONTROL_VARIANT_PENDING
'public, max-age=3600';CACHE_CONTROL_NO_STORE
'no-store, no-cache, must-revalidate, proxy-revalidate';CACHE_CONTROL_NOT_FOUND
'public, max-age=300';CORS_ALLOW_ALL_ORIGINS
'*';CORS_CDN_METHODS
'GET, HEAD, OPTIONS';CORS_API_METHODS
'GET, POST, PUT, PATCH, DELETE, OPTIONS';CORS_ALLOWED_HEADERS
'Content-Type, Authorization';CORS_MAX_AGE
'86400';X_CONTENT_TYPE_OPTIONS
'nosniff';X_FRAME_OPTIONS_DENY
'DENY';X_FRAME_OPTIONS_SAMEORIGIN
'SAMEORIGIN';REFERRER_POLICY
'strict-origin-when-cross-origin';PERMISSIONS_POLICY
'geolocation=(), microphone=(), camera=()';STRICT_TRANSPORT_SECURITY
'max-age=31536000CROSS_ORIGIN_RESOURCE_POLICY_CROSS_ORIGIN
'cross-origin';CROSS_ORIGIN_RESOURCE_POLICY_SAME_ORIGIN
'same-origin';CROSS_ORIGIN_EMBEDDER_POLICY
'require-corp';CROSS_ORIGIN_OPENER_POLICY
'same-origin';CSP_API
"default-src 'none'CSP_CDN
"default-src 'none'CSP_API_DOCS
"default-src 'self'CSP_AUTHJS
"default-src 'self'CONTENT_DISPOSITION_INLINE
'inline';CONTENT_DISPOSITION_ATTACHMENT
'attachment';X_REQUEST_ID
'X-Request-ID';X_MOCK_AUTH
'X-Mock-Auth';X_VARIANT_STATUS
'X-Variant-Status';X_IMAGE_ID
'X-Image-ID';PRAGMA_NO_CACHE
'no-cache';EXPIRES_IMMEDIATE
'0';SECURITY_HEADERS_API
{
'X-Content-Type-Options': X_CONTENT_TYPE_OPTIONS,
'X-Frame-Options': X_FRAME_OPTIONS_DENY,
'...SECURITY_HEADERS_CDN
{
'X-Content-Type-Options': X_CONTENT_TYPE_OPTIONS,
'Referrer-Policy': REFERRER_POLICY,
'Permi...SECURITY_HEADERS
SECURITY_HEADERS_API;CORS_HEADERS_CDN
{
'Access-Control-Allow-Origin': CORS_ALLOW_ALL_ORIGINS,
'Access-Control-Allow-Methods': CORS_CD...CORS_HEADERS_API_PREFLIGHT
{
'Access-Control-Allow-Methods': CORS_API_METHODS,
'Access-Control-Allow-Headers': CORS_ALLOWED...NO_CACHE_HEADERS
{
'Cache-Control': CACHE_CONTROL_NO_STORE,
Pragma: PRAGMA_NO_CACHE,
Expires: EXPIRES_IMMEDIATE...CLIENT_HINT_HEADERS
{
'Accept-CH': 'Sec-CH-DPR, Sec-CH-Viewport-Width, Sec-CH-Width',
'Critical-CH': 'Sec-CH-DPR',
...HSTS_HEADER
STRICT_TRANSPORT_SECURITY;Image Formats
Source: config/src/image-formats.ts
VALID_IMAGE_FORMATS
['webp', 'avif', 'png', 'jpg', 'jpeg'] as const;CONVERTIBLE_IMAGE_FORMATS
['webp', 'avif', 'jpg', 'jpeg'] as const;AVIF_SIZE_LIMITS
{
/** Hard limit when format=avif is explicitly requested */
EXPLICIT_REQUEST_MAX: 1600,
/** S...IMAGE_FORMAT_MIME_TYPES
{
webp: 'image/webp',
avif: 'image/avif',
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'imag...Image Transforms
Source: config/src/image-transforms.ts
IMAGE_FIT_MODES
['scale-down', 'contain', 'cover', 'crop', 'pad', 'squeeze'] as const;DEFAULT_FIT_MODE
'scale-down';IMAGE_FORMATS
[
'avif',
'webp',
'jpeg',
'baseline-jpeg',
'png',
'png-force',
'svg',
'json',
] as c...DEFAULT_IMAGE_FORMAT
undefined;IMAGE_GRAVITY_PRESETS
['auto', 'face', 'left', 'right', 'top', 'bottom', 'center'] as const;DEFAULT_GRAVITY
'auto';IMAGE_QUALITY_PRESETS
{
/** Maximum quality, larger file size */
max: 100,
/** High quality for hero images */
hig...IMAGE_QUALITY_MIN
1;IMAGE_QUALITY_MAX
100;DEFAULT_IMAGE_QUALITY
IMAGE_QUALITY_PRESETS.default;IMAGE_METADATA_OPTIONS
['none', 'copyright', 'keep'] as const;DEFAULT_METADATA_OPTION
'none';IMAGE_ROTATION_ANGLES
[0, 90, 180, 270] as const;IMAGE_FLIP_OPTIONS
['h', 'v', 'hv'] as const;BLUR_MIN
1;BLUR_MAX
250;SHARPEN_MIN
0;SHARPEN_MAX
10;COLOR_FACTOR_DEFAULT
1.0;IMAGE_SIZE_LIMITS
{
/** Minimum width/height in pixels */
minDimension: 1,
/** Maximum width in pixels */
maxW...DEFAULT_DPR
1;DEFAULT_TRANSFORM_OPTIONS
{
fit: DEFAULT_FIT_MODE,
format: DEFAULT_IMAGE_FORMAT,
quality: DEFAULT_IMAGE_QUALITY,
metad...Image Variants
Source: config/src/image-variants.ts
VARIANT_PRESETS
[
'original',
'w128',
'w256',
'w512',
'w1024',
'w1536',
'w2048',
'thumb',
'og-imag...DEFAULT_VARIANT
'original';VARIANT_CONFIG
{
original: {
description: 'Original image (no transformation)',
label: 'Original - Full r...Licenses
Source: config/src/licenses.ts
LICENSES
[
{
key: 'none',
name: 'None',
description: 'No license specifiedLogging
Source: config/src/logging.ts
VERY_SLOW_REQUEST_THRESHOLD_MS
5000;LOG_SAMPLING_RATES
{
development: 1.0, // 100% - log everything in dev
production: 0.1, // 10% - sample 10% of requ...LOG_RETENTION_DAYS
{
cloudflare_dashboard: 30, // Cloudflare Workers Logs retention
r2_archive: 365, // Long-term s...LOGPUSH_CONFIG
{
// R2 bucket path structure for logs
pathPrefix: 'logs/workers',
pathDateFormat: 'YYYY/MM/DD...STRUCTURED_LOG_FIELDS
[
'timestamp',
'level',
'message',
'requestId',
'userId',
'path',
'method',
'statusC...SENSITIVE_LOG_FIELDS
[
'password',
'token',
'secret',
'apiKey',
'privateKey',
'authorization',
'cookie',
...Mime Types
Source: config/src/mime-types.ts
MIME_IMAGE_JPEG
'image/jpeg';MIME_IMAGE_PNG
'image/png';MIME_IMAGE_WEBP
'image/webp';MIME_IMAGE_AVIF
'image/avif';MIME_IMAGE_GIF
'image/gif';MIME_IMAGE_SVG
'image/svg+xml';MIME_IMAGE_HEIC
'image/heic';MIME_IMAGE_HEIF
'image/heif';MIME_APPLICATION_JSON
'application/json';MIME_APPLICATION_OCTET_STREAM
'application/octet-stream';MIME_MULTIPART_FORM_DATA
'multipart/form-data';MIME_APPLICATION_FORM_URLENCODED
'application/x-www-form-urlencoded';DEFAULT_IMAGE_MIME_TYPE
MIME_IMAGE_JPEG;DEFAULT_MIME_TYPE
MIME_APPLICATION_OCTET_STREAM;Pagination
Source: config/src/pagination.ts
PAGINATION_OPTIONS
[5, 10, 25, 50, 100] as const;PAGINATION
{
DEFAULT_LIMIT: 10, // Default page size
MAX_LIMIT: 200, // Maximum page size allowed
MIN_LIM...DB_QUERY_BATCH_SIZE
90;Scheduled
Source: config/src/scheduled.ts
CLEANUP_CRON_DEFAULT
'0 1 * * *';ANALYTICS_CRON_DEFAULT
'0 2 * * *';BACKUP_SYNC_CRON_DEFAULT
'0 3 * * *';CLEANUP_ENABLED_DEFAULT
true;ANALYTICS_AGGREGATION_ENABLED_DEFAULT
true;BACKUP_SYNC_ENABLED_DEFAULT
true;SOFT_DELETE_RETENTION_DAYS_DEFAULT
30;SOFT_DELETE_RETENTION_MS_DEFAULT
SOFT_DELETE_RETENTION_DAYS_DEFAULT * 24 * 60 * 60 * 1000;Security
Source: config/src/security.ts
PATH_TRAVERSAL_PATTERN
/\.\.|\/\.\.|\.\/|\\|%2e%2e|%252e%252e|%2f|%5c/gi;MAX_PATH_DEPTH
5;BLOCKED_FILENAME_PATTERNS
[
/^\./, // Hidden files
/\.(exe|bat|cmd|sh|ps1|scr|com|pif)$/i, // Executable files
/\.\./g, ...CONTENT_TYPE_DETECTION_SAMPLE_SIZE
100;MAX_IMAGE_DIMENSION
50000;MIN_IMAGE_DIMENSION
1;IMAGE_MAGIC_BYTES
{
'image/jpeg': [0xff, 0xd8, 0xff],
'image/png': [0x89, 0x50, 0x4e, 0x47],
'image/gif': [0x47,...Status Checks
Source: config/src/status-checks.ts
DEPENDENCY_SERVICES
[
{
key: 'database',
label: 'Database (D1)',
icon: 'Database',
core: true,
des...QUEUE_BINDINGS
[
{ key: 'VARIANT_QUEUE', label: 'Variant Queue' },
{ key: 'BACKUP_QUEUE', label: 'Backup Queue'...Storage
Source: config/src/storage.ts
PRESIGNED_URL_EXPIRATION_SECONDS
3600;Ui
Source: config/src/ui.ts
UI_NAVIGATION_DELAY_MS
50;MAX_RECENT_SEARCHES
10;MAX_ITEMS_IN_MEMORY
500;SEARCH_DEFAULT_LIMIT
100;MAX_SAVED_VARIANTS
20;MAX_VARIANT_NAME_LENGTH
50;Upload Constraints
Source: config/src/upload-constraints.ts
EXPIRATION_OPTIONS
[
{ key: 'forever', name: 'Forever', description: 'Never expires', duration: null },
{ key: '1ho...DEFAULT_LICENSE
'none';DEFAULT_VISIBILITY
'unlisted';LOCKED_VISIBILITY
'public';NSFW_ALLOWED
false;DEFAULT_NSFW
false;MAX_FILE_SIZE
100 * 1024 * 1024;MAX_FILENAME_LEN
128;MAX_TAGS_PER_IMAGE
20;MAX_TAG_LENGTH
50;MAX_ALBUM_SLUG_LENGTH
50;MAX_ALBUM_TITLE_LENGTH
100;MAX_ALBUM_DESCRIPTION_LENGTH
500;MAX_ALT_TEXT_LENGTH
500;MAX_OWNER_SLUG_LENGTH
50;MAX_IMAGE_TITLE_LENGTH
255;MAX_TAG_DESCRIPTION_LENGTH
200;MAX_IMAGE_TITLE_TRUNCATION
128;SLUG_PATTERN
/^[a-z0-9-_]+$/;OWNER_SLUG_PATTERN
/^[a-z0-9-_]+$/;FILENAME_PATTERN
/^[a-zA-Z0-9-_. ]+$/;SHORT_ID_LENGTH
6;MAX_FILES
100;MAX_BULK_IMPORT
20;ALLOWED_FILE_TYPES
['image/*'] as const;ACCEPTED_IMAGE_TYPES
[
'image/jpeg',
'image/png',
'image/webp',
'image/avif',
'image/gif',
'image/svg+xml',
...DEFAULT_ALBUM
'images';THUMBNAIL_CONFIG
{
width: 256,
height: 192,
} as constDEFAULT_STRIP_METADATA
true;DEFAULT_PRESERVE_EXTENSION
true;DEFAULT_ENCRYPT
false;DEFAULT_PERMISSION
'inherit' as const;DEFAULT_EXPIRATION
'forever';LOCKED_EXPIRATION
'forever';LOCKED_EXPIRATION_MESSAGE
'Expiration time is currently set to Forever for all uploads on this instance.';Usage Limits
Source: config/src/usage-limits.ts
USAGE_LIMITS
{
// Allow 1% grace over limit to prevent edge case frustration
GRACE_PERCENTAGE: 1,
// Cache...Total Categories: 28 Total Constants: 270