1- import { defineConfig } from 'astro/config' ;
2- import sitemap from '@astrojs/sitemap' ;
3- import vercel from '@astrojs/vercel' ;
4- import tailwindcss from '@tailwindcss/vite' ;
5- import fs from 'node:fs' ;
6- import path from 'node:path' ;
7- import os from 'node:os' ;
1+ import { defineConfig } from 'astro/config'
2+ import sitemap from '@astrojs/sitemap'
3+ import vercel from '@astrojs/vercel'
4+ import tailwindcss from '@tailwindcss/vite'
5+ import fs from 'node:fs'
6+ import path from 'node:path'
7+ import os from 'node:os'
88
9- import vue from '@astrojs/vue' ;
9+ import vue from '@astrojs/vue'
1010
1111// Build template date lookup at config time
12- const templatesDir = path . join ( process . cwd ( ) , 'src/content/templates' ) ;
13- const templateDates = new Map ( ) ;
12+ const templatesDir = path . join ( process . cwd ( ) , 'src/content/templates' )
13+ const templateDates = new Map ( )
1414
1515if ( fs . existsSync ( templatesDir ) ) {
16- const files = fs . readdirSync ( templatesDir ) . filter ( ( f ) => f . endsWith ( '.json' ) ) ;
16+ const files = fs . readdirSync ( templatesDir ) . filter ( ( f ) => f . endsWith ( '.json' ) )
1717 for ( const file of files ) {
1818 try {
19- const content = JSON . parse ( fs . readFileSync ( path . join ( templatesDir , file ) , 'utf-8' ) ) ;
19+ const content = JSON . parse (
20+ fs . readFileSync ( path . join ( templatesDir , file ) , 'utf-8' )
21+ )
2022 if ( content . name && content . date ) {
21- templateDates . set ( content . name , content . date ) ;
23+ templateDates . set ( content . name , content . date )
2224 }
2325 } catch {
2426 // Skip invalid JSON files
@@ -27,48 +29,69 @@ if (fs.existsSync(templatesDir)) {
2729}
2830
2931// Build timestamp used as lastmod fallback for pages without a specific date
30- const buildDate = new Date ( ) . toISOString ( ) ;
32+ const buildDate = new Date ( ) . toISOString ( )
3133
3234// Supported locales (matches src/i18n/config.ts)
33- const locales = [ 'en' , 'zh' , 'zh-TW' , 'ja' , 'ko' , 'es' , 'fr' , 'ru' , 'tr' , 'ar' , 'pt-BR' ] ;
34- const nonDefaultLocales = locales . filter ( ( l ) => l !== 'en' ) ;
35+ const locales = [
36+ 'en' ,
37+ 'zh' ,
38+ 'zh-TW' ,
39+ 'ja' ,
40+ 'ko' ,
41+ 'es' ,
42+ 'fr' ,
43+ 'ru' ,
44+ 'tr' ,
45+ 'ar' ,
46+ 'pt-BR'
47+ ]
48+ const nonDefaultLocales = locales . filter ( ( l ) => l !== 'en' )
3549
3650// Custom sitemap pages for ISR routes not discovered at build time
37- const siteOrigin = ( process . env . PUBLIC_SITE_ORIGIN || 'https://www.comfy.org' ) . replace ( / \/ $ / , '' ) ;
51+ const siteOrigin = (
52+ process . env . PUBLIC_SITE_ORIGIN || 'https://www.comfy.org'
53+ ) . replace ( / \/ $ / , '' )
3854
3955// Creator profile pages — extract unique usernames from synced templates
40- const creatorUsernames = new Set ( ) ;
56+ const creatorUsernames = new Set ( )
4157if ( fs . existsSync ( templatesDir ) ) {
42- const files = fs . readdirSync ( templatesDir ) . filter ( ( f ) => f . endsWith ( '.json' ) ) ;
58+ const files = fs . readdirSync ( templatesDir ) . filter ( ( f ) => f . endsWith ( '.json' ) )
4359 for ( const file of files ) {
4460 try {
45- const content = JSON . parse ( fs . readFileSync ( path . join ( templatesDir , file ) , 'utf-8' ) ) ;
46- if ( content . username ) creatorUsernames . add ( content . username ) ;
61+ const content = JSON . parse (
62+ fs . readFileSync ( path . join ( templatesDir , file ) , 'utf-8' )
63+ )
64+ if ( content . username ) creatorUsernames . add ( content . username )
4765 } catch {
4866 // Skip invalid JSON
4967 }
5068 }
5169}
5270
53- const creatorPages = [ ...creatorUsernames ] . map ( ( u ) => `${ siteOrigin } /workflows/${ u } /` ) ;
54- const localeCustomPages = nonDefaultLocales . map ( ( locale ) =>
55- `${ siteOrigin } /${ locale } /workflows/`
56- ) ;
57- const customPages = [ ...creatorPages , ...localeCustomPages ] ;
71+ const creatorPages = [ ...creatorUsernames ] . map (
72+ ( u ) => `${ siteOrigin } /workflows/${ u } /`
73+ )
74+ const localeCustomPages = nonDefaultLocales . map (
75+ ( locale ) => `${ siteOrigin } /${ locale } /workflows/`
76+ )
77+ const customPages = [ ...creatorPages , ...localeCustomPages ]
5878
5979// https://astro.build/config
6080export default defineConfig ( {
61- site : ( process . env . PUBLIC_SITE_ORIGIN || 'https://www.comfy.org' ) . replace ( / \/ $ / , '' ) ,
81+ site : ( process . env . PUBLIC_SITE_ORIGIN || 'https://www.comfy.org' ) . replace (
82+ / \/ $ / ,
83+ ''
84+ ) ,
6285 prefetch : {
6386 prefetchAll : false ,
64- defaultStrategy : 'hover' ,
87+ defaultStrategy : 'hover'
6588 } ,
6689 i18n : {
6790 defaultLocale : 'en' ,
6891 locales : locales ,
6992 routing : {
70- prefixDefaultLocale : false , // English at root, others prefixed (/zh/, /ja/, etc.)
71- } ,
93+ prefixDefaultLocale : false // English at root, others prefixed (/zh/, /ja/, etc.)
94+ }
7295 } ,
7396 integrations : [
7497 sitemap ( {
@@ -79,106 +102,124 @@ export default defineConfig({
79102 // Include on-demand locale pages that aren't discovered at build time
80103 customPages : customPages ,
81104 serialize ( item ) {
82- const url = new URL ( item . url ) ;
83- const pathname = url . pathname ;
105+ const url = new URL ( item . url )
106+ const pathname = url . pathname
84107
85108 // Template detail pages: /workflows/{slug}/ or /{locale}/workflows/{slug}/
86109 const templateMatch = pathname . match (
87110 / ^ (?: \/ ( [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ) ? \/ w o r k f l o w s \/ ( [ ^ / ] + ) \/ ? $ /
88- ) ;
111+ )
89112 if ( templateMatch ) {
90- const slug = templateMatch [ 2 ] ;
91- const date = templateDates . get ( slug ) ;
92- item . lastmod = date ? new Date ( date ) . toISOString ( ) : buildDate ;
113+ const slug = templateMatch [ 2 ]
114+ const date = templateDates . get ( slug )
115+ item . lastmod = date ? new Date ( date ) . toISOString ( ) : buildDate
93116 // @ts -expect-error - sitemap types are stricter than actual API
94- item . changefreq = 'monthly' ;
95- item . priority = 0.8 ;
96- return item ;
117+ item . changefreq = 'monthly'
118+ item . priority = 0.8
119+ return item
97120 }
98121
99122 // Homepage
100123 if ( pathname === '/' || pathname === '' ) {
101- item . lastmod = buildDate ;
124+ item . lastmod = buildDate
102125 // @ts -expect-error - sitemap types are stricter than actual API
103- item . changefreq = 'daily' ;
104- item . priority = 1.0 ;
105- return item ;
126+ item . changefreq = 'daily'
127+ item . priority = 1.0
128+ return item
106129 }
107130
108131 // Workflows index (including localized versions)
109132 if ( pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ ? $ / ) ) {
110- item . lastmod = buildDate ;
133+ item . lastmod = buildDate
111134 // @ts -expect-error - sitemap types are stricter than actual API
112- item . changefreq = 'daily' ;
113- item . priority = 0.9 ;
114- return item ;
135+ item . changefreq = 'daily'
136+ item . priority = 0.9
137+ return item
115138 }
116139
117140 // Category pages: /workflows/category/{type}/ or /{locale}/workflows/category/{type}/
118- if ( pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ c a t e g o r y \/ / ) ) {
141+ if (
142+ pathname . match (
143+ / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ c a t e g o r y \/ /
144+ )
145+ ) {
119146 // @ts -expect-error - sitemap types are stricter than actual API
120- item . changefreq = 'weekly' ;
121- item . priority = 0.7 ;
122- return item ;
147+ item . changefreq = 'weekly'
148+ item . priority = 0.7
149+ return item
123150 }
124151
125152 // Model pages: /workflows/model/{model}/ or /{locale}/workflows/model/{model}/
126- if ( pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ m o d e l \/ / ) ) {
153+ if (
154+ pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ m o d e l \/ / )
155+ ) {
127156 // @ts -expect-error - sitemap types are stricter than actual API
128- item . changefreq = 'weekly' ;
129- item . priority = 0.6 ;
130- return item ;
157+ item . changefreq = 'weekly'
158+ item . priority = 0.6
159+ return item
131160 }
132161
133162 // Tag pages: /workflows/tag/{tag}/ or /{locale}/workflows/tag/{tag}/
134- if ( pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ t a g \/ / ) ) {
163+ if (
164+ pathname . match ( / ^ (?: \/ [ a - z ] { 2 } (?: - [ A - Z ] { 2 } ) ? ) ? \/ w o r k f l o w s \/ t a g \/ / )
165+ ) {
135166 // @ts -expect-error - sitemap types are stricter than actual API
136- item . changefreq = 'weekly' ;
137- item . priority = 0.6 ;
138- return item ;
167+ item . changefreq = 'weekly'
168+ item . priority = 0.6
169+ return item
139170 }
140171
141172 // Default for other pages
142173 // @ts -expect-error - sitemap types are stricter than actual API
143- item . changefreq = 'weekly' ;
144- item . priority = 0.5 ;
145- return item ;
174+ item . changefreq = 'weekly'
175+ item . priority = 0.5
176+ return item
146177 } ,
147178 // Exclude OG image routes and legacy redirect pages from sitemap.
148179 // Legacy redirects are /workflows/{slug}/ without a 12-char hex share_id suffix.
149180 // Canonical detail pages are /workflows/{slug}-{shareId}/ (shareId = 12 hex chars).
150181 filter : ( page ) => {
151- if ( page . includes ( '/workflows/og/' ) || page . includes ( '/workflows/og.png' ) ) return false ;
182+ if (
183+ page . includes ( '/workflows/og/' ) ||
184+ page . includes ( '/workflows/og.png' )
185+ )
186+ return false
152187 // Check if this is a workflow detail path (not category/tag/model/creators)
153- const match = page . match ( / \/ w o r k f l o w s \/ ( [ ^ / ] + ) \/ $ / ) ;
188+ const match = page . match ( / \/ w o r k f l o w s \/ ( [ ^ / ] + ) \/ $ / )
154189 if ( match ) {
155- const segment = match [ 1 ] ;
190+ const segment = match [ 1 ]
156191 // Skip known sub-paths
157- if ( [ 'category' , 'tag' , 'model' , 'creators' ] . some ( ( p ) => page . includes ( `/workflows/${ p } /` ) ) ) return true ;
192+ if (
193+ [ 'category' , 'tag' , 'model' , 'creators' ] . some ( ( p ) =>
194+ page . includes ( `/workflows/${ p } /` )
195+ )
196+ )
197+ return true
158198 // Include if it has a share_id suffix (12 hex chars after last hyphen)
159- const lastHyphen = segment . lastIndexOf ( '-' ) ;
160- if ( lastHyphen === - 1 ) return false ; // No hyphen = legacy redirect
161- const candidate = segment . slice ( lastHyphen + 1 ) ;
162- if ( candidate . length === 12 && / ^ [ 0 - 9 a - f ] + $ / . test ( candidate ) ) return true ;
163- return false ; // Has hyphen but not a valid share_id = legacy redirect
199+ const lastHyphen = segment . lastIndexOf ( '-' )
200+ if ( lastHyphen === - 1 ) return false // No hyphen = legacy redirect
201+ const candidate = segment . slice ( lastHyphen + 1 )
202+ if ( candidate . length === 12 && / ^ [ 0 - 9 a - f ] + $ / . test ( candidate ) )
203+ return true
204+ return false // Has hyphen but not a valid share_id = legacy redirect
164205 }
165- return true ;
166- } ,
206+ return true
207+ }
167208 } ) ,
168- vue ( ) ,
209+ vue ( )
169210 ] ,
170211 output : 'static' ,
171212 adapter : vercel ( {
172213 webAnalytics : { enabled : true } ,
173- skewProtection : true ,
214+ skewProtection : true
174215 } ) ,
175216
176217 // Build performance optimizations
177218 build : {
178219 // Increase concurrency for faster builds on multi-core systems
179220 concurrency : Math . max ( 1 , os . cpus ( ) . length ) ,
180221 // Inline small stylesheets automatically
181- inlineStylesheets : 'auto' ,
222+ inlineStylesheets : 'auto'
182223 } ,
183224
184225 // HTML compression
@@ -190,9 +231,9 @@ export default defineConfig({
190231 entrypoint : 'astro/assets/services/sharp' ,
191232 config : {
192233 // Limit input pixels to prevent memory issues with large images
193- limitInputPixels : 268402689 , // ~16384x16384
194- } ,
195- } ,
234+ limitInputPixels : 268402689 // ~16384x16384
235+ }
236+ }
196237 } ,
197238
198239 // Responsive images for automatic srcset generation (now stable in Astro 5)
@@ -201,13 +242,13 @@ export default defineConfig({
201242 vite : {
202243 plugins : [ tailwindcss ( ) ] ,
203244 build : {
204- chunkSizeWarningLimit : 1000 ,
245+ chunkSizeWarningLimit : 1000
205246 } ,
206247 optimizeDeps : {
207- include : [ 'web-vitals' ] ,
248+ include : [ 'web-vitals' ]
208249 } ,
209250 css : {
210- devSourcemap : false ,
211- } ,
212- } ,
213- } ) ;
251+ devSourcemap : false
252+ }
253+ }
254+ } )
0 commit comments