create-foliokit 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -2
  3. package/bin/index.js +6 -0
  4. package/package.json +50 -4
  5. package/src/cli.js +111 -0
  6. package/src/generator.js +133 -0
  7. package/src/prompts.js +44 -0
  8. package/src/utils/errors.js +7 -0
  9. package/src/utils/paths.js +12 -0
  10. package/src/utils/progress.js +5 -0
  11. package/src/utils/project-name.js +30 -0
  12. package/templates/default/.gitignore +20 -0
  13. package/templates/default/data.ts +227 -0
  14. package/templates/default/index.html +23 -0
  15. package/templates/default/package-lock.json +1280 -0
  16. package/templates/default/package.json +28 -0
  17. package/templates/default/public/avatar-placeholder.svg +10 -0
  18. package/templates/default/public/footer-heart.png +0 -0
  19. package/templates/default/public/love-always-wins.png +0 -0
  20. package/templates/default/public/project-placeholder.svg +10 -0
  21. package/templates/default/public/robots.txt +2 -0
  22. package/templates/default/public/stars-foreground-landscape.svg +202 -0
  23. package/templates/default/public/stars-foreground-portrait.svg +202 -0
  24. package/templates/default/public/stars-landscape.svg +322 -0
  25. package/templates/default/public/stars-portrait.svg +322 -0
  26. package/templates/default/scripts/generate-seo.mjs +34 -0
  27. package/templates/default/src/App.tsx +552 -0
  28. package/templates/default/src/BrandIcon.tsx +36 -0
  29. package/templates/default/src/ProjectMagazineGallery.css +90 -0
  30. package/templates/default/src/ProjectMagazineGallery.tsx +210 -0
  31. package/templates/default/src/main.tsx +10 -0
  32. package/templates/default/src/styles.css +536 -0
  33. package/templates/default/src/utils.ts +2 -0
  34. package/templates/default/src/vite-env.d.ts +1 -0
  35. package/templates/default/tests/portfolio.test.js +96 -0
  36. package/templates/default/tsconfig.app.json +21 -0
  37. package/templates/default/tsconfig.json +7 -0
  38. package/templates/default/tsconfig.node.json +16 -0
  39. package/templates/default/vite.config.ts +38 -0
@@ -0,0 +1,322 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 960" preserveAspectRatio="none">
2
+ <circle cx="369.8" cy="756.8" r="1.66" fill="white" opacity="0.90"/>
3
+ <circle cx="129.6" cy="862.7" r="2.11" fill="white" opacity="0.67"/>
4
+ <circle cx="193.2" cy="140.9" r="2.44" fill="white" opacity="0.53"/>
5
+ <circle cx="314.9" cy="184.1" r="1.33" fill="white" opacity="0.94"/>
6
+ <circle cx="357.9" cy="467.1" r="1.55" fill="white" opacity="0.40"/>
7
+ <circle cx="312.6" cy="341.0" r="1.86" fill="white" opacity="0.63"/>
8
+ <circle cx="56.3" cy="551.4" r="2.29" fill="white" opacity="0.49"/>
9
+ <circle cx="421.5" cy="877.2" r="1.72" fill="white" opacity="0.70"/>
10
+ <circle cx="61.9" cy="323.0" r="1.38" fill="white" opacity="0.86"/>
11
+ <circle cx="1.8" cy="782.1" r="1.66" fill="white" opacity="0.45"/>
12
+ <circle cx="37.6" cy="923.6" r="1.03" fill="white" opacity="0.64"/>
13
+ <circle cx="78.4" cy="899.4" r="0.71" fill="white" opacity="0.34"/>
14
+ <circle cx="433.6" cy="306.4" r="2.10" fill="white" opacity="0.97"/>
15
+ <circle cx="454.4" cy="877.2" r="1.29" fill="white" opacity="0.57"/>
16
+ <circle cx="336.9" cy="656.4" r="1.22" fill="white" opacity="0.98"/>
17
+ <circle cx="454.7" cy="256.7" r="1.07" fill="white" opacity="0.96"/>
18
+ <circle cx="388.6" cy="748.8" r="1.29" fill="white" opacity="0.50"/>
19
+ <circle cx="419.4" cy="822.0" r="2.20" fill="white" opacity="0.65"/>
20
+ <circle cx="213.3" cy="128.8" r="1.20" fill="white" opacity="0.50"/>
21
+ <circle cx="106.8" cy="609.5" r="1.55" fill="white" opacity="0.43"/>
22
+ <circle cx="436.9" cy="711.2" r="0.90" fill="white" opacity="0.82"/>
23
+ <circle cx="247.4" cy="697.0" r="1.95" fill="white" opacity="0.83"/>
24
+ <circle cx="175.2" cy="39.3" r="0.87" fill="white" opacity="0.37"/>
25
+ <circle cx="47.2" cy="773.2" r="0.87" fill="white" opacity="0.78"/>
26
+ <circle cx="72.6" cy="204.6" r="1.69" fill="white" opacity="0.71"/>
27
+ <circle cx="240.9" cy="767.3" r="1.88" fill="white" opacity="0.92"/>
28
+ <circle cx="330.1" cy="746.0" r="1.85" fill="white" opacity="0.52"/>
29
+ <circle cx="175.5" cy="857.9" r="1.62" fill="white" opacity="0.61"/>
30
+ <circle cx="444.2" cy="489.4" r="1.39" fill="white" opacity="1.00"/>
31
+ <circle cx="444.0" cy="822.8" r="1.56" fill="white" opacity="0.97"/>
32
+ <circle cx="174.7" cy="646.9" r="1.84" fill="white" opacity="0.77"/>
33
+ <circle cx="28.1" cy="648.1" r="0.86" fill="white" opacity="0.33"/>
34
+ <circle cx="304.1" cy="536.0" r="2.46" fill="white" opacity="0.33"/>
35
+ <circle cx="432.5" cy="478.0" r="0.78" fill="white" opacity="0.40"/>
36
+ <circle cx="305.1" cy="319.4" r="2.38" fill="white" opacity="0.77"/>
37
+ <circle cx="7.8" cy="863.4" r="1.63" fill="white" opacity="0.76"/>
38
+ <circle cx="119.3" cy="204.2" r="0.82" fill="white" opacity="0.49"/>
39
+ <circle cx="64.0" cy="432.0" r="1.62" fill="white" opacity="0.69"/>
40
+ <circle cx="286.2" cy="901.0" r="1.38" fill="white" opacity="0.51"/>
41
+ <circle cx="214.3" cy="577.6" r="1.71" fill="white" opacity="0.92"/>
42
+ <circle cx="420.9" cy="543.7" r="1.12" fill="white" opacity="0.86"/>
43
+ <circle cx="227.9" cy="848.9" r="0.91" fill="white" opacity="0.41"/>
44
+ <circle cx="362.7" cy="548.5" r="0.79" fill="white" opacity="0.91"/>
45
+ <circle cx="234.0" cy="399.6" r="1.31" fill="white" opacity="0.59"/>
46
+ <circle cx="153.9" cy="253.6" r="1.72" fill="white" opacity="0.97"/>
47
+ <circle cx="235.0" cy="697.2" r="1.78" fill="white" opacity="0.54"/>
48
+ <circle cx="288.0" cy="498.5" r="1.08" fill="white" opacity="0.95"/>
49
+ <circle cx="370.0" cy="852.8" r="1.30" fill="white" opacity="0.94"/>
50
+ <circle cx="308.0" cy="783.1" r="2.35" fill="white" opacity="0.39"/>
51
+ <circle cx="8.1" cy="930.2" r="2.39" fill="white" opacity="0.34"/>
52
+ <circle cx="75.1" cy="567.5" r="1.29" fill="white" opacity="0.95"/>
53
+ <circle cx="472.2" cy="755.4" r="1.42" fill="white" opacity="0.93"/>
54
+ <circle cx="346.9" cy="870.8" r="2.37" fill="white" opacity="0.67"/>
55
+ <circle cx="351.7" cy="945.8" r="1.72" fill="white" opacity="0.50"/>
56
+ <circle cx="266.0" cy="411.3" r="1.12" fill="white" opacity="0.38"/>
57
+ <circle cx="207.0" cy="400.0" r="2.29" fill="white" opacity="0.63"/>
58
+ <circle cx="398.4" cy="685.0" r="0.87" fill="white" opacity="0.38"/>
59
+ <circle cx="342.0" cy="806.7" r="1.61" fill="white" opacity="0.42"/>
60
+ <circle cx="281.9" cy="785.7" r="1.00" fill="white" opacity="0.48"/>
61
+ <circle cx="287.9" cy="894.3" r="1.76" fill="white" opacity="0.38"/>
62
+ <circle cx="84.7" cy="203.8" r="2.50" fill="white" opacity="0.51"/>
63
+ <circle cx="476.7" cy="580.3" r="1.15" fill="white" opacity="0.69"/>
64
+ <circle cx="133.4" cy="6.1" r="2.21" fill="white" opacity="0.75"/>
65
+ <circle cx="344.7" cy="620.4" r="0.71" fill="white" opacity="0.70"/>
66
+ <circle cx="232.1" cy="474.9" r="2.37" fill="white" opacity="0.88"/>
67
+ <circle cx="65.5" cy="638.5" r="0.65" fill="white" opacity="0.33"/>
68
+ <circle cx="210.2" cy="7.5" r="1.32" fill="white" opacity="0.81"/>
69
+ <circle cx="154.1" cy="335.2" r="1.24" fill="white" opacity="0.75"/>
70
+ <circle cx="261.3" cy="75.7" r="1.39" fill="white" opacity="0.72"/>
71
+ <circle cx="379.8" cy="38.1" r="1.71" fill="white" opacity="0.69"/>
72
+ <circle cx="111.2" cy="884.8" r="1.72" fill="white" opacity="0.98"/>
73
+ <circle cx="389.7" cy="590.2" r="1.17" fill="white" opacity="0.98"/>
74
+ <circle cx="376.9" cy="213.3" r="0.69" fill="white" opacity="0.56"/>
75
+ <circle cx="122.5" cy="660.4" r="1.65" fill="white" opacity="0.59"/>
76
+ <circle cx="354.6" cy="232.3" r="2.29" fill="white" opacity="0.79"/>
77
+ <circle cx="11.5" cy="111.7" r="1.64" fill="white" opacity="0.91"/>
78
+ <circle cx="398.1" cy="224.6" r="1.70" fill="white" opacity="0.78"/>
79
+ <circle cx="18.3" cy="791.6" r="1.25" fill="white" opacity="0.91"/>
80
+ <circle cx="247.7" cy="164.2" r="1.37" fill="white" opacity="0.92"/>
81
+ <circle cx="376.3" cy="900.7" r="1.66" fill="white" opacity="0.41"/>
82
+ <circle cx="28.1" cy="755.9" r="0.63" fill="white" opacity="0.78"/>
83
+ <circle cx="203.9" cy="222.4" r="1.05" fill="white" opacity="0.46"/>
84
+ <circle cx="77.1" cy="894.4" r="0.63" fill="white" opacity="0.98"/>
85
+ <circle cx="227.9" cy="852.6" r="1.92" fill="white" opacity="0.90"/>
86
+ <circle cx="84.2" cy="223.6" r="1.82" fill="white" opacity="0.86"/>
87
+ <circle cx="17.3" cy="548.4" r="1.47" fill="white" opacity="0.53"/>
88
+ <circle cx="418.7" cy="76.2" r="1.45" fill="white" opacity="0.77"/>
89
+ <circle cx="286.4" cy="777.9" r="1.16" fill="white" opacity="0.47"/>
90
+ <circle cx="368.2" cy="873.3" r="0.83" fill="white" opacity="0.81"/>
91
+ <circle cx="188.5" cy="669.6" r="1.05" fill="white" opacity="0.73"/>
92
+ <circle cx="7.4" cy="783.0" r="1.18" fill="white" opacity="0.85"/>
93
+ <circle cx="159.0" cy="861.5" r="2.00" fill="white" opacity="0.56"/>
94
+ <circle cx="416.0" cy="440.7" r="1.60" fill="white" opacity="0.39"/>
95
+ <circle cx="229.1" cy="930.8" r="2.21" fill="white" opacity="0.89"/>
96
+ <circle cx="327.5" cy="287.7" r="0.88" fill="white" opacity="0.34"/>
97
+ <circle cx="49.2" cy="3.1" r="1.52" fill="white" opacity="0.38"/>
98
+ <circle cx="247.6" cy="131.0" r="1.40" fill="white" opacity="0.60"/>
99
+ <circle cx="142.4" cy="541.7" r="1.96" fill="white" opacity="0.95"/>
100
+ <circle cx="122.5" cy="922.7" r="1.66" fill="white" opacity="0.89"/>
101
+ <circle cx="67.7" cy="917.2" r="0.91" fill="white" opacity="0.88"/>
102
+ <circle cx="157.4" cy="119.1" r="2.34" fill="white" opacity="0.81"/>
103
+ <circle cx="213.6" cy="756.5" r="1.42" fill="white" opacity="0.78"/>
104
+ <circle cx="465.1" cy="780.3" r="0.97" fill="white" opacity="0.42"/>
105
+ <circle cx="21.5" cy="832.6" r="1.77" fill="white" opacity="0.52"/>
106
+ <circle cx="24.0" cy="809.6" r="1.99" fill="white" opacity="0.71"/>
107
+ <circle cx="319.3" cy="373.9" r="2.22" fill="white" opacity="0.81"/>
108
+ <circle cx="227.1" cy="732.6" r="2.22" fill="white" opacity="0.51"/>
109
+ <circle cx="164.6" cy="433.3" r="2.44" fill="white" opacity="0.61"/>
110
+ <circle cx="60.0" cy="256.8" r="1.11" fill="white" opacity="0.82"/>
111
+ <circle cx="198.2" cy="837.7" r="0.88" fill="white" opacity="0.47"/>
112
+ <circle cx="189.6" cy="891.0" r="1.63" fill="white" opacity="0.78"/>
113
+ <circle cx="27.6" cy="317.6" r="1.92" fill="white" opacity="0.39"/>
114
+ <circle cx="122.5" cy="224.7" r="1.83" fill="white" opacity="0.35"/>
115
+ <circle cx="200.4" cy="776.1" r="2.22" fill="white" opacity="0.84"/>
116
+ <circle cx="433.1" cy="907.1" r="1.61" fill="white" opacity="0.82"/>
117
+ <circle cx="127.7" cy="338.6" r="1.88" fill="white" opacity="0.34"/>
118
+ <circle cx="462.6" cy="726.9" r="2.12" fill="white" opacity="0.45"/>
119
+ <circle cx="117.8" cy="142.1" r="2.41" fill="white" opacity="0.38"/>
120
+ <circle cx="127.1" cy="271.7" r="1.40" fill="white" opacity="0.78"/>
121
+ <circle cx="319.2" cy="864.2" r="1.07" fill="white" opacity="0.65"/>
122
+ <circle cx="75.9" cy="326.9" r="1.58" fill="white" opacity="0.70"/>
123
+ <circle cx="414.2" cy="513.2" r="2.36" fill="white" opacity="0.99"/>
124
+ <circle cx="200.3" cy="535.5" r="0.98" fill="white" opacity="0.50"/>
125
+ <circle cx="62.6" cy="196.9" r="1.17" fill="white" opacity="0.45"/>
126
+ <circle cx="331.8" cy="277.6" r="1.55" fill="white" opacity="0.35"/>
127
+ <circle cx="94.9" cy="591.9" r="2.15" fill="white" opacity="0.36"/>
128
+ <circle cx="250.7" cy="809.1" r="1.20" fill="white" opacity="0.79"/>
129
+ <circle cx="135.6" cy="633.7" r="1.18" fill="white" opacity="0.39"/>
130
+ <circle cx="444.4" cy="21.7" r="1.46" fill="white" opacity="0.89"/>
131
+ <circle cx="336.9" cy="345.2" r="1.16" fill="white" opacity="0.70"/>
132
+ <circle cx="255.6" cy="942.3" r="1.98" fill="white" opacity="0.56"/>
133
+ <circle cx="22.2" cy="126.7" r="1.35" fill="white" opacity="0.46"/>
134
+ <circle cx="141.5" cy="371.8" r="0.82" fill="white" opacity="0.50"/>
135
+ <circle cx="439.2" cy="344.8" r="1.97" fill="white" opacity="0.43"/>
136
+ <circle cx="361.4" cy="865.0" r="2.46" fill="white" opacity="0.80"/>
137
+ <circle cx="103.6" cy="262.3" r="1.40" fill="white" opacity="0.56"/>
138
+ <circle cx="415.7" cy="929.9" r="1.25" fill="white" opacity="0.70"/>
139
+ <circle cx="12.3" cy="147.1" r="1.00" fill="white" opacity="0.89"/>
140
+ <circle cx="193.8" cy="886.7" r="1.07" fill="white" opacity="1.00"/>
141
+ <circle cx="7.2" cy="801.8" r="0.64" fill="white" opacity="0.35"/>
142
+ <circle cx="433.2" cy="387.7" r="0.90" fill="white" opacity="0.81"/>
143
+ <circle cx="208.3" cy="513.2" r="1.89" fill="white" opacity="0.74"/>
144
+ <circle cx="87.6" cy="76.4" r="1.41" fill="white" opacity="0.43"/>
145
+ <circle cx="317.4" cy="941.2" r="1.87" fill="white" opacity="0.51"/>
146
+ <circle cx="205.0" cy="666.9" r="2.18" fill="white" opacity="0.54"/>
147
+ <circle cx="151.3" cy="828.8" r="2.36" fill="white" opacity="0.60"/>
148
+ <circle cx="396.8" cy="403.1" r="0.92" fill="white" opacity="0.73"/>
149
+ <circle cx="445.4" cy="571.0" r="2.03" fill="white" opacity="0.57"/>
150
+ <circle cx="375.9" cy="498.4" r="2.34" fill="white" opacity="0.51"/>
151
+ <circle cx="87.0" cy="364.4" r="1.93" fill="white" opacity="0.88"/>
152
+ <circle cx="324.9" cy="315.1" r="2.41" fill="white" opacity="0.98"/>
153
+ <circle cx="338.9" cy="576.6" r="1.79" fill="white" opacity="0.80"/>
154
+ <circle cx="95.0" cy="523.3" r="1.24" fill="white" opacity="0.80"/>
155
+ <circle cx="212.8" cy="495.2" r="1.98" fill="white" opacity="0.33"/>
156
+ <circle cx="114.3" cy="800.7" r="0.90" fill="white" opacity="0.34"/>
157
+ <circle cx="272.5" cy="257.9" r="1.89" fill="white" opacity="0.72"/>
158
+ <circle cx="165.9" cy="711.9" r="1.43" fill="white" opacity="0.81"/>
159
+ <circle cx="467.8" cy="201.1" r="2.15" fill="white" opacity="0.61"/>
160
+ <circle cx="356.8" cy="887.8" r="0.80" fill="white" opacity="0.63"/>
161
+ <circle cx="157.4" cy="509.7" r="1.35" fill="white" opacity="0.37"/>
162
+ <circle cx="436.1" cy="664.7" r="0.67" fill="white" opacity="0.49"/>
163
+ <circle cx="322.8" cy="206.5" r="2.31" fill="white" opacity="0.76"/>
164
+ <circle cx="343.4" cy="824.0" r="0.87" fill="white" opacity="0.75"/>
165
+ <circle cx="291.5" cy="281.3" r="1.39" fill="white" opacity="0.84"/>
166
+ <circle cx="67.3" cy="871.4" r="1.60" fill="white" opacity="0.87"/>
167
+ <circle cx="10.4" cy="400.6" r="0.76" fill="white" opacity="0.48"/>
168
+ <circle cx="254.1" cy="456.5" r="1.92" fill="white" opacity="0.63"/>
169
+ <circle cx="189.5" cy="716.7" r="1.73" fill="white" opacity="0.73"/>
170
+ <circle cx="205.8" cy="131.7" r="2.27" fill="white" opacity="0.59"/>
171
+ <circle cx="315.0" cy="137.4" r="2.02" fill="white" opacity="0.64"/>
172
+ <circle cx="468.6" cy="492.2" r="1.23" fill="white" opacity="0.44"/>
173
+ <circle cx="292.9" cy="654.8" r="0.75" fill="white" opacity="0.79"/>
174
+ <circle cx="411.6" cy="654.9" r="2.05" fill="white" opacity="0.49"/>
175
+ <circle cx="442.4" cy="455.4" r="1.67" fill="white" opacity="0.50"/>
176
+ <circle cx="395.2" cy="877.9" r="2.15" fill="white" opacity="0.45"/>
177
+ <circle cx="319.6" cy="768.9" r="1.27" fill="white" opacity="0.43"/>
178
+ <circle cx="369.4" cy="680.0" r="1.69" fill="white" opacity="0.74"/>
179
+ <circle cx="210.5" cy="537.9" r="1.73" fill="white" opacity="0.92"/>
180
+ <circle cx="182.0" cy="139.8" r="0.95" fill="white" opacity="0.92"/>
181
+ <circle cx="14.7" cy="27.2" r="1.19" fill="white" opacity="0.92"/>
182
+ <circle cx="157.7" cy="535.5" r="1.54" fill="white" opacity="0.78"/>
183
+ <circle cx="318.7" cy="893.0" r="1.23" fill="white" opacity="0.84"/>
184
+ <circle cx="25.9" cy="483.9" r="2.12" fill="white" opacity="0.59"/>
185
+ <circle cx="379.5" cy="792.4" r="1.20" fill="white" opacity="0.56"/>
186
+ <circle cx="39.5" cy="60.0" r="1.73" fill="white" opacity="0.51"/>
187
+ <circle cx="218.1" cy="773.1" r="2.08" fill="white" opacity="0.61"/>
188
+ <circle cx="443.3" cy="416.0" r="1.41" fill="white" opacity="0.63"/>
189
+ <circle cx="102.4" cy="482.2" r="1.10" fill="white" opacity="0.66"/>
190
+ <circle cx="252.0" cy="821.3" r="2.19" fill="white" opacity="0.82"/>
191
+ <circle cx="301.6" cy="395.8" r="1.54" fill="white" opacity="0.44"/>
192
+ <circle cx="139.5" cy="801.4" r="1.12" fill="white" opacity="0.46"/>
193
+ <circle cx="148.4" cy="508.5" r="1.82" fill="white" opacity="0.64"/>
194
+ <circle cx="316.5" cy="657.3" r="0.95" fill="white" opacity="0.80"/>
195
+ <circle cx="253.8" cy="282.9" r="1.85" fill="white" opacity="0.95"/>
196
+ <circle cx="119.4" cy="365.2" r="0.73" fill="white" opacity="0.33"/>
197
+ <circle cx="189.2" cy="818.4" r="1.76" fill="white" opacity="0.64"/>
198
+ <circle cx="268.6" cy="695.4" r="1.84" fill="white" opacity="0.98"/>
199
+ <circle cx="281.0" cy="601.3" r="0.89" fill="white" opacity="0.39"/>
200
+ <circle cx="116.9" cy="792.1" r="0.81" fill="white" opacity="0.50"/>
201
+ <circle cx="313.2" cy="193.4" r="0.64" fill="white" opacity="0.67"/>
202
+ <circle cx="448.1" cy="852.6" r="1.27" fill="white" opacity="0.46"/>
203
+ <circle cx="421.2" cy="502.2" r="1.73" fill="white" opacity="0.56"/>
204
+ <circle cx="305.1" cy="306.7" r="1.28" fill="white" opacity="0.44"/>
205
+ <circle cx="335.5" cy="389.7" r="1.61" fill="white" opacity="0.57"/>
206
+ <circle cx="328.9" cy="135.8" r="1.72" fill="white" opacity="0.93"/>
207
+ <circle cx="334.3" cy="341.9" r="1.43" fill="white" opacity="0.60"/>
208
+ <circle cx="126.4" cy="693.0" r="1.47" fill="white" opacity="0.74"/>
209
+ <circle cx="68.0" cy="678.3" r="1.81" fill="white" opacity="0.46"/>
210
+ <circle cx="229.3" cy="781.5" r="2.27" fill="white" opacity="0.34"/>
211
+ <circle cx="51.7" cy="61.1" r="2.47" fill="white" opacity="0.93"/>
212
+ <circle cx="2.4" cy="874.8" r="2.18" fill="white" opacity="0.97"/>
213
+ <circle cx="69.3" cy="64.7" r="1.99" fill="white" opacity="0.67"/>
214
+ <circle cx="141.8" cy="875.7" r="0.69" fill="white" opacity="1.00"/>
215
+ <circle cx="246.5" cy="445.2" r="1.53" fill="white" opacity="0.41"/>
216
+ <circle cx="163.9" cy="95.8" r="1.98" fill="white" opacity="0.87"/>
217
+ <circle cx="474.7" cy="469.3" r="0.97" fill="white" opacity="0.94"/>
218
+ <circle cx="3.1" cy="414.5" r="1.15" fill="white" opacity="0.56"/>
219
+ <circle cx="103.8" cy="544.4" r="1.01" fill="white" opacity="0.97"/>
220
+ <circle cx="440.9" cy="139.0" r="1.13" fill="white" opacity="0.91"/>
221
+ <circle cx="306.2" cy="307.1" r="1.42" fill="white" opacity="0.95"/>
222
+ <circle cx="443.9" cy="643.2" r="1.00" fill="white" opacity="0.78"/>
223
+ <circle cx="470.0" cy="853.5" r="1.50" fill="white" opacity="0.67"/>
224
+ <circle cx="52.6" cy="827.3" r="1.71" fill="white" opacity="0.85"/>
225
+ <circle cx="142.5" cy="547.8" r="2.37" fill="white" opacity="0.85"/>
226
+ <circle cx="179.5" cy="517.1" r="2.31" fill="white" opacity="0.55"/>
227
+ <circle cx="283.6" cy="732.1" r="1.94" fill="white" opacity="0.40"/>
228
+ <circle cx="277.6" cy="323.4" r="2.04" fill="white" opacity="0.91"/>
229
+ <circle cx="469.1" cy="215.7" r="1.28" fill="white" opacity="0.51"/>
230
+ <circle cx="119.1" cy="841.2" r="0.61" fill="white" opacity="0.55"/>
231
+ <circle cx="204.6" cy="624.3" r="1.65" fill="white" opacity="0.33"/>
232
+ <circle cx="403.5" cy="229.5" r="2.46" fill="white" opacity="0.99"/>
233
+ <circle cx="28.2" cy="529.8" r="1.70" fill="white" opacity="0.73"/>
234
+ <circle cx="276.3" cy="730.1" r="2.07" fill="white" opacity="0.38"/>
235
+ <circle cx="4.8" cy="439.2" r="2.30" fill="white" opacity="0.46"/>
236
+ <circle cx="397.2" cy="127.5" r="1.72" fill="white" opacity="0.56"/>
237
+ <circle cx="408.7" cy="404.1" r="2.04" fill="white" opacity="0.34"/>
238
+ <circle cx="38.8" cy="788.0" r="0.86" fill="white" opacity="0.51"/>
239
+ <circle cx="277.7" cy="810.2" r="2.36" fill="white" opacity="0.50"/>
240
+ <circle cx="214.9" cy="759.1" r="0.83" fill="white" opacity="0.53"/>
241
+ <circle cx="76.2" cy="586.8" r="1.36" fill="white" opacity="0.92"/>
242
+ <circle cx="358.7" cy="529.0" r="2.03" fill="white" opacity="0.77"/>
243
+ <circle cx="308.6" cy="515.7" r="1.03" fill="white" opacity="0.45"/>
244
+ <circle cx="71.8" cy="485.6" r="1.31" fill="white" opacity="0.44"/>
245
+ <circle cx="403.0" cy="121.0" r="1.37" fill="white" opacity="0.50"/>
246
+ <circle cx="182.1" cy="596.6" r="0.75" fill="white" opacity="0.87"/>
247
+ <circle cx="264.3" cy="618.5" r="2.12" fill="white" opacity="0.42"/>
248
+ <circle cx="232.5" cy="388.0" r="1.51" fill="white" opacity="0.36"/>
249
+ <circle cx="178.1" cy="484.7" r="0.90" fill="white" opacity="0.91"/>
250
+ <circle cx="79.4" cy="184.3" r="1.43" fill="white" opacity="0.35"/>
251
+ <circle cx="23.6" cy="926.4" r="0.91" fill="white" opacity="0.53"/>
252
+ <circle cx="320.9" cy="727.1" r="2.42" fill="white" opacity="0.76"/>
253
+ <circle cx="197.4" cy="130.3" r="1.68" fill="white" opacity="0.88"/>
254
+ <circle cx="115.3" cy="215.0" r="0.72" fill="white" opacity="0.43"/>
255
+ <circle cx="406.8" cy="291.7" r="1.34" fill="white" opacity="0.79"/>
256
+ <circle cx="69.8" cy="283.1" r="2.10" fill="white" opacity="0.34"/>
257
+ <circle cx="173.3" cy="544.9" r="0.87" fill="white" opacity="0.64"/>
258
+ <circle cx="118.7" cy="761.6" r="0.96" fill="white" opacity="0.48"/>
259
+ <circle cx="86.0" cy="751.5" r="0.94" fill="white" opacity="0.97"/>
260
+ <circle cx="71.6" cy="496.2" r="1.49" fill="white" opacity="0.68"/>
261
+ <circle cx="445.0" cy="790.5" r="0.69" fill="white" opacity="0.46"/>
262
+ <circle cx="432.5" cy="386.5" r="0.77" fill="white" opacity="0.67"/>
263
+ <circle cx="175.0" cy="147.4" r="2.36" fill="white" opacity="0.45"/>
264
+ <circle cx="127.6" cy="6.1" r="0.71" fill="white" opacity="0.64"/>
265
+ <circle cx="328.5" cy="683.6" r="0.90" fill="white" opacity="0.52"/>
266
+ <circle cx="264.2" cy="281.6" r="0.89" fill="white" opacity="0.41"/>
267
+ <circle cx="179.4" cy="105.8" r="2.07" fill="white" opacity="0.83"/>
268
+ <circle cx="478.6" cy="712.3" r="1.14" fill="white" opacity="0.35"/>
269
+ <circle cx="306.4" cy="135.4" r="0.88" fill="white" opacity="0.77"/>
270
+ <circle cx="355.1" cy="728.9" r="2.36" fill="white" opacity="0.32"/>
271
+ <circle cx="186.4" cy="577.8" r="1.88" fill="white" opacity="0.37"/>
272
+ <circle cx="154.3" cy="393.9" r="1.66" fill="white" opacity="0.38"/>
273
+ <circle cx="378.0" cy="411.9" r="1.60" fill="white" opacity="0.79"/>
274
+ <circle cx="371.1" cy="439.9" r="1.00" fill="white" opacity="0.73"/>
275
+ <circle cx="175.0" cy="139.2" r="1.47" fill="white" opacity="0.66"/>
276
+ <circle cx="123.9" cy="689.7" r="0.73" fill="white" opacity="0.91"/>
277
+ <circle cx="329.5" cy="593.7" r="1.94" fill="white" opacity="0.39"/>
278
+ <circle cx="132.1" cy="695.6" r="0.79" fill="white" opacity="0.83"/>
279
+ <circle cx="285.8" cy="130.5" r="2.30" fill="white" opacity="0.34"/>
280
+ <circle cx="205.6" cy="678.3" r="2.16" fill="white" opacity="0.99"/>
281
+ <circle cx="3.6" cy="756.1" r="0.74" fill="white" opacity="0.79"/>
282
+ <circle cx="362.3" cy="846.9" r="0.68" fill="white" opacity="0.64"/>
283
+ <circle cx="131.4" cy="156.9" r="2.04" fill="white" opacity="0.47"/>
284
+ <circle cx="297.0" cy="57.8" r="1.98" fill="white" opacity="0.40"/>
285
+ <circle cx="49.9" cy="349.1" r="0.70" fill="white" opacity="0.44"/>
286
+ <circle cx="80.0" cy="534.4" r="2.33" fill="white" opacity="0.85"/>
287
+ <circle cx="25.7" cy="308.1" r="2.26" fill="white" opacity="0.95"/>
288
+ <circle cx="164.9" cy="406.2" r="1.83" fill="white" opacity="0.87"/>
289
+ <circle cx="274.6" cy="417.4" r="0.90" fill="white" opacity="0.33"/>
290
+ <circle cx="227.8" cy="948.3" r="0.73" fill="white" opacity="0.66"/>
291
+ <circle cx="294.8" cy="498.6" r="0.99" fill="white" opacity="0.42"/>
292
+ <circle cx="195.2" cy="680.9" r="1.47" fill="white" opacity="0.56"/>
293
+ <circle cx="390.6" cy="60.4" r="0.70" fill="white" opacity="0.46"/>
294
+ <circle cx="102.7" cy="328.6" r="1.40" fill="white" opacity="0.39"/>
295
+ <circle cx="106.0" cy="767.8" r="2.32" fill="white" opacity="0.89"/>
296
+ <circle cx="223.1" cy="399.4" r="0.80" fill="white" opacity="0.71"/>
297
+ <circle cx="287.7" cy="572.0" r="1.81" fill="white" opacity="0.39"/>
298
+ <circle cx="25.5" cy="24.7" r="1.52" fill="white" opacity="0.62"/>
299
+ <circle cx="138.8" cy="619.4" r="1.30" fill="white" opacity="0.80"/>
300
+ <circle cx="283.0" cy="898.4" r="1.93" fill="white" opacity="0.75"/>
301
+ <circle cx="302.2" cy="941.1" r="0.75" fill="white" opacity="0.48"/>
302
+ <circle cx="171.6" cy="956.1" r="1.47" fill="white" opacity="0.77"/>
303
+ <circle cx="454.1" cy="282.2" r="1.19" fill="white" opacity="0.35"/>
304
+ <circle cx="398.5" cy="834.7" r="1.61" fill="white" opacity="0.87"/>
305
+ <circle cx="47.2" cy="71.1" r="2.31" fill="white" opacity="0.39"/>
306
+ <circle cx="360.5" cy="71.7" r="1.09" fill="white" opacity="0.97"/>
307
+ <circle cx="284.6" cy="49.3" r="2.15" fill="white" opacity="0.68"/>
308
+ <circle cx="372.4" cy="324.6" r="0.92" fill="white" opacity="0.60"/>
309
+ <circle cx="122.6" cy="920.2" r="0.63" fill="white" opacity="0.32"/>
310
+ <circle cx="325.8" cy="250.1" r="1.77" fill="white" opacity="0.59"/>
311
+ <circle cx="224.8" cy="578.7" r="1.38" fill="white" opacity="0.33"/>
312
+ <circle cx="56.9" cy="284.0" r="1.57" fill="white" opacity="0.64"/>
313
+ <circle cx="464.9" cy="241.0" r="2.19" fill="white" opacity="0.90"/>
314
+ <circle cx="465.5" cy="39.8" r="0.81" fill="white" opacity="0.80"/>
315
+ <circle cx="100.8" cy="313.2" r="0.85" fill="white" opacity="0.61"/>
316
+ <circle cx="103.1" cy="808.7" r="2.21" fill="white" opacity="0.75"/>
317
+ <circle cx="137.5" cy="401.1" r="1.12" fill="white" opacity="0.97"/>
318
+ <circle cx="191.7" cy="678.7" r="1.08" fill="white" opacity="0.41"/>
319
+ <circle cx="200.6" cy="579.9" r="1.67" fill="white" opacity="0.62"/>
320
+ <circle cx="311.7" cy="514.1" r="2.35" fill="white" opacity="0.97"/>
321
+ <circle cx="0.1" cy="82.8" r="2.23" fill="white" opacity="0.93"/>
322
+ </svg>
@@ -0,0 +1,34 @@
1
+ import { readFile, writeFile } from 'node:fs/promises'
2
+ import { resolve } from 'node:path'
3
+ import { loadEnv } from 'vite'
4
+
5
+ const outputDirectory = resolve('dist')
6
+ const env = loadEnv('production', process.cwd(), '')
7
+ const htmlPath = resolve(outputDirectory, 'index.html')
8
+ let html = await readFile(htmlPath, 'utf8')
9
+ const metadataSiteUrl = html.match(/<meta property="og:url" content="([^"]+)"\s*\/>/)?.[1]
10
+ const configuredSiteUrl = process.env.SITE_URL ?? env.SITE_URL ?? metadataSiteUrl
11
+
12
+ if (!configuredSiteUrl) process.exit(0)
13
+
14
+ const site = new URL(configuredSiteUrl)
15
+ if (site.protocol !== 'https:' || site.pathname !== '/' || site.search || site.hash) {
16
+ throw new Error('SITE_URL must be the HTTPS origin only, such as https://portfolio.example')
17
+ }
18
+
19
+ const origin = site.origin
20
+ const openGraphUrl = `<meta property="og:url" content="${origin}/" />`
21
+ if (/<meta property="og:url" content="[^"]+"\s*\/>/.test(html)) {
22
+ html = html.replace(/<meta property="og:url" content="[^"]+"\s*\/>/, openGraphUrl)
23
+ } else {
24
+ html = html.replace('</head>', ` ${openGraphUrl}\n </head>`)
25
+ }
26
+ html = html.replace('</head>', ` <link rel="canonical" href="${origin}/" />\n </head>`)
27
+ await writeFile(htmlPath, html)
28
+
29
+ const sitemap = '<?xml version="1.0" encoding="UTF-8"?>\n'
30
+ + '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
31
+ + ` <url><loc>${origin}/</loc></url>\n`
32
+ + '</urlset>\n'
33
+ await writeFile(resolve(outputDirectory, 'sitemap.xml'), sitemap)
34
+ await writeFile(resolve(outputDirectory, 'robots.txt'), `User-agent: *\nAllow: /\nSitemap: ${origin}/sitemap.xml\n`)